mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Auto merge of #118975 - GuillaumeGomez:rollup-0emhjx0, r=GuillaumeGomez
Rollup of 4 pull requests Successful merges: - #113091 (Don't merge cfg and doc(cfg) attributes for re-exports) - #115660 (rustdoc: allow resizing the sidebar / hiding the top bar) - #118863 (rustc_mir_build: Enforce `rustc::potential_query_instability` lint) - #118909 (Some cleanup and improvement for invalid ref casting impl) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4d1bd0db7f
@ -37,59 +37,73 @@ declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
|
||||
return;
|
||||
};
|
||||
if let Some((e, pat)) = borrow_or_assign(cx, expr) {
|
||||
if matches!(pat, PatternKind::Borrow { mutbl: Mutability::Mut } | PatternKind::Assign) {
|
||||
let init = cx.expr_or_init(e);
|
||||
|
||||
let init = cx.expr_or_init(e);
|
||||
let Some(ty_has_interior_mutability) = is_cast_from_ref_to_mut_ptr(cx, init) else {
|
||||
return;
|
||||
};
|
||||
let orig_cast = if init.span != e.span { Some(init.span) } else { None };
|
||||
let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
|
||||
|
||||
let Some(ty_has_interior_mutability) = is_cast_from_const_to_mut(cx, init) else {
|
||||
return;
|
||||
};
|
||||
let orig_cast = if init.span != e.span { Some(init.span) } else { None };
|
||||
let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
|
||||
|
||||
cx.emit_spanned_lint(
|
||||
INVALID_REFERENCE_CASTING,
|
||||
expr.span,
|
||||
if is_assignment {
|
||||
InvalidReferenceCastingDiag::AssignToRef { orig_cast, ty_has_interior_mutability }
|
||||
} else {
|
||||
InvalidReferenceCastingDiag::BorrowAsMut { orig_cast, ty_has_interior_mutability }
|
||||
},
|
||||
);
|
||||
cx.emit_spanned_lint(
|
||||
INVALID_REFERENCE_CASTING,
|
||||
expr.span,
|
||||
if pat == PatternKind::Assign {
|
||||
InvalidReferenceCastingDiag::AssignToRef {
|
||||
orig_cast,
|
||||
ty_has_interior_mutability,
|
||||
}
|
||||
} else {
|
||||
InvalidReferenceCastingDiag::BorrowAsMut {
|
||||
orig_cast,
|
||||
ty_has_interior_mutability,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_operation_we_care_about<'tcx>(
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum PatternKind {
|
||||
Borrow { mutbl: Mutability },
|
||||
Assign,
|
||||
}
|
||||
|
||||
fn borrow_or_assign<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'tcx>,
|
||||
) -> Option<(bool, &'tcx Expr<'tcx>)> {
|
||||
fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> {
|
||||
// &mut <expr>
|
||||
let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
|
||||
expr
|
||||
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
|
||||
fn deref_assign_or_addr_of<'tcx>(
|
||||
expr: &'tcx Expr<'tcx>,
|
||||
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
|
||||
// &(mut) <expr>
|
||||
let (inner, pat) = if let ExprKind::AddrOf(_, mutbl, expr) = expr.kind {
|
||||
(expr, PatternKind::Borrow { mutbl })
|
||||
// <expr> = ...
|
||||
} else if let ExprKind::Assign(expr, _, _) = expr.kind {
|
||||
expr
|
||||
(expr, PatternKind::Assign)
|
||||
// <expr> += ...
|
||||
} else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
|
||||
expr
|
||||
(expr, PatternKind::Assign)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind {
|
||||
Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// *<inner>
|
||||
let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
|
||||
return None;
|
||||
};
|
||||
Some((e, pat))
|
||||
}
|
||||
|
||||
fn ptr_write<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx Expr<'tcx>,
|
||||
) -> Option<(bool, &'tcx Expr<'tcx>)> {
|
||||
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
|
||||
if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind
|
||||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
@ -98,7 +112,7 @@ fn is_operation_we_care_about<'tcx>(
|
||||
Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned)
|
||||
)
|
||||
{
|
||||
Some((true, arg_ptr))
|
||||
Some((arg_ptr, PatternKind::Assign))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -107,13 +121,10 @@ fn is_operation_we_care_about<'tcx>(
|
||||
deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
|
||||
}
|
||||
|
||||
fn is_cast_from_const_to_mut<'tcx>(
|
||||
fn is_cast_from_ref_to_mut_ptr<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
orig_expr: &'tcx Expr<'tcx>,
|
||||
) -> Option<bool> {
|
||||
let mut need_check_freeze = false;
|
||||
let mut e = orig_expr;
|
||||
|
||||
let end_ty = cx.typeck_results().node_type(orig_expr.hir_id);
|
||||
|
||||
// Bail out early if the end type is **not** a mutable pointer.
|
||||
@ -121,6 +132,28 @@ fn is_cast_from_const_to_mut<'tcx>(
|
||||
return None;
|
||||
}
|
||||
|
||||
let (e, need_check_freeze) = peel_casts(cx, orig_expr);
|
||||
|
||||
let start_ty = cx.typeck_results().node_type(e.hir_id);
|
||||
if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() {
|
||||
// If an UnsafeCell method is involved, we need to additionally check the
|
||||
// inner type for the presence of the Freeze trait (ie does NOT contain
|
||||
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
|
||||
//
|
||||
// Except on the presence of non concrete skeleton types (ie generics)
|
||||
// since there is no way to make it safe for arbitrary types.
|
||||
let inner_ty_has_interior_mutability =
|
||||
!inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton();
|
||||
(!need_check_freeze || !inner_ty_has_interior_mutability)
|
||||
.then_some(inner_ty_has_interior_mutability)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
|
||||
let mut gone_trough_unsafe_cell_raw_get = false;
|
||||
|
||||
loop {
|
||||
e = e.peel_blocks();
|
||||
// <expr> as ...
|
||||
@ -145,27 +178,18 @@ fn is_cast_from_const_to_mut<'tcx>(
|
||||
)
|
||||
{
|
||||
if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
|
||||
need_check_freeze = true;
|
||||
gone_trough_unsafe_cell_raw_get = true;
|
||||
}
|
||||
arg
|
||||
} else {
|
||||
break;
|
||||
let init = cx.expr_or_init(e);
|
||||
if init.hir_id != e.hir_id {
|
||||
init
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let start_ty = cx.typeck_results().node_type(e.hir_id);
|
||||
if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() {
|
||||
// If an UnsafeCell method is involved we need to additionally check the
|
||||
// inner type for the presence of the Freeze trait (ie does NOT contain
|
||||
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
|
||||
//
|
||||
// We also consider non concrete skeleton types (ie generics)
|
||||
// to be an issue since there is no way to make it safe for abitrary types.
|
||||
let inner_ty_has_interior_mutability =
|
||||
!inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton();
|
||||
(!need_check_freeze || !inner_ty_has_interior_mutability)
|
||||
.then_some(inner_ty_has_interior_mutability)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
(e, gone_trough_unsafe_cell_raw_get)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! Construction of MIR from HIR.
|
||||
//!
|
||||
//! This crate also contains the match exhaustiveness and usefulness checking.
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(box_patterns)]
|
||||
|
@ -9,7 +9,7 @@ use crate::errors::*;
|
||||
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
@ -948,7 +948,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
|
||||
err.note(format!("the matched value is of type `{}`", scrut_ty));
|
||||
|
||||
if !is_empty_match {
|
||||
let mut non_exhaustive_tys = FxHashSet::default();
|
||||
let mut non_exhaustive_tys = FxIndexSet::default();
|
||||
// Look at the first witness.
|
||||
collect_non_exhaustive_tys(cx, &witnesses[0], &mut non_exhaustive_tys);
|
||||
|
||||
@ -1104,7 +1104,7 @@ fn joined_uncovered_patterns<'p, 'tcx>(
|
||||
fn collect_non_exhaustive_tys<'tcx>(
|
||||
cx: &MatchCheckCtxt<'_, 'tcx>,
|
||||
pat: &WitnessPat<'tcx>,
|
||||
non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
|
||||
non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
|
||||
) {
|
||||
if matches!(pat.ctor(), Constructor::NonExhaustive) {
|
||||
non_exhaustive_tys.insert(pat.ty());
|
||||
|
@ -2646,6 +2646,40 @@ fn filter_tokens_from_list(
|
||||
tokens
|
||||
}
|
||||
|
||||
fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
|
||||
if is_inline {
|
||||
ident == sym::hidden || ident == sym::inline || ident == sym::no_inline
|
||||
} else {
|
||||
ident == sym::cfg
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove attributes from `normal` that should not be inherited by `use` re-export.
|
||||
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
|
||||
fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
||||
match normal.item.args {
|
||||
ast::AttrArgs::Delimited(ref mut args) => {
|
||||
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
||||
!matches!(
|
||||
token,
|
||||
TokenTree::Token(
|
||||
Token {
|
||||
kind: TokenKind::Ident(
|
||||
ident,
|
||||
_,
|
||||
),
|
||||
..
|
||||
},
|
||||
_,
|
||||
) if filter_doc_attr_ident(*ident, is_inline),
|
||||
)
|
||||
});
|
||||
args.tokens = TokenStream::new(tokens);
|
||||
}
|
||||
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// When inlining items, we merge their attributes (and all the reexports attributes too) with the
|
||||
/// final reexport. For example:
|
||||
///
|
||||
@ -2672,13 +2706,6 @@ fn add_without_unwanted_attributes<'hir>(
|
||||
is_inline: bool,
|
||||
import_parent: Option<DefId>,
|
||||
) {
|
||||
// If it's not `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
|
||||
if !is_inline {
|
||||
for attr in new_attrs {
|
||||
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||
}
|
||||
return;
|
||||
}
|
||||
for attr in new_attrs {
|
||||
if matches!(attr.kind, ast::AttrKind::DocComment(..)) {
|
||||
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||
@ -2687,33 +2714,14 @@ fn add_without_unwanted_attributes<'hir>(
|
||||
let mut attr = attr.clone();
|
||||
match attr.kind {
|
||||
ast::AttrKind::Normal(ref mut normal) => {
|
||||
if let [ident] = &*normal.item.path.segments
|
||||
&& let ident = ident.ident.name
|
||||
&& ident == sym::doc
|
||||
{
|
||||
match normal.item.args {
|
||||
ast::AttrArgs::Delimited(ref mut args) => {
|
||||
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
||||
!matches!(
|
||||
token,
|
||||
TokenTree::Token(
|
||||
Token {
|
||||
kind: TokenKind::Ident(
|
||||
sym::hidden | sym::inline | sym::no_inline,
|
||||
_,
|
||||
),
|
||||
..
|
||||
},
|
||||
_,
|
||||
),
|
||||
)
|
||||
});
|
||||
args.tokens = TokenStream::new(tokens);
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
}
|
||||
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
}
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
let ident = ident.ident.name;
|
||||
if ident == sym::doc {
|
||||
filter_doc_attr(normal, is_inline);
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
} else if ident != sym::cfg {
|
||||
// If it's not a `cfg()` attribute, we keep it.
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2013,6 +2013,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
|
||||
map.insert("themeStyle".into(), 1);
|
||||
map.insert("settings-menu".into(), 1);
|
||||
map.insert("help-button".into(), 1);
|
||||
map.insert("sidebar-button".into(), 1);
|
||||
map.insert("main-content".into(), 1);
|
||||
map.insert("toggle-all-docs".into(), 1);
|
||||
map.insert("all-types".into(), 1);
|
||||
|
@ -1,5 +1,3 @@
|
||||
use clean::AttributesExt;
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir as hir;
|
||||
@ -465,16 +463,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
|
||||
|
||||
clean::ImportItem(ref import) => {
|
||||
let stab_tags = if let Some(import_def_id) = import.source.did {
|
||||
let ast_attrs = tcx.get_attrs_unchecked(import_def_id);
|
||||
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
|
||||
|
||||
// Just need an item with the correct def_id and attrs
|
||||
let import_item = clean::Item {
|
||||
item_id: import_def_id.into(),
|
||||
attrs: import_attrs,
|
||||
cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg),
|
||||
..myitem.clone()
|
||||
};
|
||||
let import_item =
|
||||
clean::Item { item_id: import_def_id.into(), ..myitem.clone() };
|
||||
|
||||
let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string());
|
||||
stab_tags
|
||||
|
@ -9,7 +9,7 @@ rules.
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
#copy-path {
|
||||
#copy-path, #sidebar-button, .sidebar-resizer {
|
||||
/* It requires JS to work so no need to display it in this case. */
|
||||
display: none;
|
||||
}
|
||||
@ -132,6 +132,8 @@ nav.sub {
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(207, 90%, 66%);
|
||||
--sidebar-resizer-active: hsl(207, 90%, 54%);
|
||||
}
|
||||
/* End theme: light */
|
||||
|
||||
@ -238,6 +240,8 @@ nav.sub {
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(207, 30%, 54%);
|
||||
--sidebar-resizer-active: hsl(207, 90%, 54%);
|
||||
}
|
||||
/* End theme: dark */
|
||||
}
|
||||
|
@ -9,6 +9,11 @@
|
||||
:root {
|
||||
--nav-sub-mobile-padding: 8px;
|
||||
--search-typename-width: 6.75rem;
|
||||
/* DEFAULT_SIDEBAR_WIDTH
|
||||
see main.js for information on these values
|
||||
and on the RUSTDOC_MOBILE_BREAKPOINT */
|
||||
--desktop-sidebar-width: 200px;
|
||||
--src-sidebar-width: 300px;
|
||||
}
|
||||
|
||||
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
|
||||
@ -383,13 +388,15 @@ img {
|
||||
|
||||
.sidebar {
|
||||
font-size: 0.875rem;
|
||||
flex: 0 0 200px;
|
||||
flex: 0 0 var(--desktop-sidebar-width);
|
||||
width: var(--desktop-sidebar-width);
|
||||
overflow-y: scroll;
|
||||
overscroll-behavior: contain;
|
||||
position: sticky;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.rustdoc.src .sidebar {
|
||||
@ -398,7 +405,95 @@ img {
|
||||
overflow-x: hidden;
|
||||
/* The sidebar is by default hidden */
|
||||
overflow-y: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hide-sidebar .sidebar,
|
||||
.hide-sidebar .sidebar-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-resizer {
|
||||
touch-action: none;
|
||||
width: 9px;
|
||||
cursor: col-resize;
|
||||
z-index: 200;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
/* make sure there's a 1px gap between the scrollbar and resize handle */
|
||||
left: calc(var(--desktop-sidebar-width) + 1px);
|
||||
}
|
||||
|
||||
.rustdoc.src .sidebar-resizer {
|
||||
/* when closed, place resizer glow on top of the normal src sidebar border (no need to worry
|
||||
about sidebar) */
|
||||
left: 49px;
|
||||
}
|
||||
|
||||
.src-sidebar-expanded .rustdoc.src .sidebar-resizer {
|
||||
/* for src sidebar, gap is already provided by 1px border on sidebar itself, so place resizer
|
||||
to right of it */
|
||||
left: var(--src-sidebar-width);
|
||||
}
|
||||
|
||||
.sidebar-resizing {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sidebar-resizing * {
|
||||
cursor: col-resize !important;
|
||||
}
|
||||
|
||||
.sidebar-resizing .sidebar {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
}
|
||||
.sidebar-resizing > body {
|
||||
padding-left: var(--resizing-sidebar-width);
|
||||
}
|
||||
|
||||
.sidebar-resizer:hover,
|
||||
.sidebar-resizer:active,
|
||||
.sidebar-resizer:focus,
|
||||
.sidebar-resizer.active {
|
||||
width: 10px;
|
||||
margin: 0;
|
||||
/* when active or hovered, place resizer glow on top of the sidebar (right next to, or even
|
||||
on top of, the scrollbar) */
|
||||
left: var(--desktop-sidebar-width);
|
||||
border-left: solid 1px var(--sidebar-resizer-hover);
|
||||
}
|
||||
|
||||
.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,
|
||||
.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,
|
||||
.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,
|
||||
.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active {
|
||||
/* when active or hovered, place resizer glow on top of the normal src sidebar border */
|
||||
left: calc(var(--src-sidebar-width) - 1px);
|
||||
}
|
||||
|
||||
@media (pointer: coarse) {
|
||||
.sidebar-resizer {
|
||||
/* too easy to hit the resizer while trying to hit the [-] toggle */
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-resizer.active {
|
||||
/* make the resize tool bigger when actually resizing, to avoid :hover styles on other stuff
|
||||
while resizing */
|
||||
padding: 0 140px;
|
||||
width: 2px;
|
||||
margin-left: -140px;
|
||||
border-left: none;
|
||||
}
|
||||
.sidebar-resizer.active:before {
|
||||
border-left: solid 2px var(--sidebar-resizer-active);
|
||||
display: block;
|
||||
height: 100%;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.sidebar, .mobile-topbar, .sidebar-menu-toggle,
|
||||
@ -416,7 +511,8 @@ img {
|
||||
|
||||
.src-sidebar-expanded .src .sidebar {
|
||||
overflow-y: auto;
|
||||
flex-basis: 300px;
|
||||
flex-basis: var(--src-sidebar-width);
|
||||
width: var(--src-sidebar-width);
|
||||
}
|
||||
|
||||
.src-sidebar-expanded .src .sidebar > *:not(#src-sidebar-toggle) {
|
||||
@ -477,6 +573,7 @@ ul.block, .block li {
|
||||
display: block;
|
||||
padding: 0.25rem; /* 4px */
|
||||
margin-left: -0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
@ -775,7 +872,7 @@ h2.section-header > .anchor {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.crate.block a.current { font-weight: 500; }
|
||||
.crate.block li.current a { font-weight: 500; }
|
||||
|
||||
/* In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap
|
||||
as much as needed on mobile (see
|
||||
@ -1478,7 +1575,20 @@ a.tooltip:hover::after {
|
||||
margin-left: 4px;
|
||||
display: flex;
|
||||
}
|
||||
#settings-menu > a, #help-button > a {
|
||||
#sidebar-button {
|
||||
display: none;
|
||||
}
|
||||
.hide-sidebar #sidebar-button {
|
||||
display: flex;
|
||||
margin-right: 4px;
|
||||
position: fixed;
|
||||
left: 6px;
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
background-color: var(--main-background-color);
|
||||
z-index: 1;
|
||||
}
|
||||
#settings-menu > a, #help-button > a, #sidebar-button > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -1493,10 +1603,21 @@ a.tooltip:hover::after {
|
||||
}
|
||||
|
||||
#settings-menu > a:hover, #settings-menu > a:focus,
|
||||
#help-button > a:hover, #help-button > a:focus {
|
||||
#help-button > a:hover, #help-button > a:focus,
|
||||
#sidebar-button > a:hover, #sidebar-button > a:focus {
|
||||
border-color: var(--settings-button-border-focus);
|
||||
}
|
||||
|
||||
#sidebar-button > a:before {
|
||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" \
|
||||
fill="none" stroke="black">\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5"/>\
|
||||
<circle cx="4.375" cy="4.375" r="1" stroke-width=".75"/>\
|
||||
<path d="m7.6121 3v16 M5.375 7.625h-2 m2 3h-2 m2 3h-2" stroke-width="1.25"/></svg>');
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#copy-path {
|
||||
color: var(--copy-path-button-color);
|
||||
background: var(--main-background-color);
|
||||
@ -1711,7 +1832,7 @@ However, it's not needed with smaller screen width because the doc/code block is
|
||||
/*
|
||||
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||
If you update this line, then you also need to update the line with the same warning
|
||||
in src-script.js
|
||||
in src-script.js and main.js
|
||||
*/
|
||||
@media (max-width: 700px) {
|
||||
/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
|
||||
@ -1722,6 +1843,10 @@ in src-script.js
|
||||
scroll-margin-top: 45px;
|
||||
}
|
||||
|
||||
.hide-sidebar #sidebar-button {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.rustdoc {
|
||||
/* Sidebar should overlay main content, rather than pushing main content to the right.
|
||||
Turn off `display: flex` on the body element. */
|
||||
@ -1750,7 +1875,8 @@ in src-script.js
|
||||
/* Hide the logo and item name from the sidebar. Those are displayed
|
||||
in the mobile-topbar instead. */
|
||||
.sidebar .logo-container,
|
||||
.sidebar .location {
|
||||
.sidebar .location,
|
||||
.sidebar-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -1818,6 +1944,10 @@ in src-script.js
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.hide-sidebar .mobile-topbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-menu-toggle {
|
||||
width: 45px;
|
||||
/* Rare exception to specifying font sizes in rem. Since this is acting
|
||||
@ -1827,6 +1957,10 @@ in src-script.js
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
.hide-sidebar .sidebar-menu-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-elems {
|
||||
margin-top: 1em;
|
||||
}
|
||||
@ -1870,6 +2004,17 @@ in src-script.js
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* sidebar button becomes topbar button */
|
||||
#sidebar-button > a:before {
|
||||
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \
|
||||
viewBox="0 0 22 22" fill="none" stroke="black">\
|
||||
<rect x="1" y="1" width="20" height="20" ry="1.5" stroke-width="1.5"/>\
|
||||
<circle cx="4.375" cy="4.375" r="1" stroke-width=".75"/>\
|
||||
<path d="m3 7.375h16m0-3h-4" stroke-width="1.25"/></svg>');
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
/* Display an alternating layout on tablets and phones */
|
||||
.item-table, .item-row, .item-table > li, .item-table > li > div,
|
||||
.search-results > a, .search-results > a > div {
|
||||
@ -2274,6 +2419,8 @@ in src-script.js
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(207, 90%, 66%);
|
||||
--sidebar-resizer-active: hsl(207, 90%, 54%);
|
||||
}
|
||||
/* End theme: light */
|
||||
|
||||
@ -2379,6 +2526,8 @@ in src-script.js
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(207, 30%, 54%);
|
||||
--sidebar-resizer-active: hsl(207, 90%, 54%);
|
||||
}
|
||||
/* End theme: dark */
|
||||
|
||||
@ -2488,6 +2637,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(34, 50%, 33%);
|
||||
--sidebar-resizer-active: hsl(34, 100%, 66%);
|
||||
}
|
||||
|
||||
:root[data-theme="ayu"] h1,
|
||||
@ -2519,6 +2670,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
}
|
||||
|
||||
:root[data-theme="ayu"] .sidebar .current,
|
||||
:root[data-theme="ayu"] .sidebar .current a,
|
||||
:root[data-theme="ayu"] .sidebar a:hover,
|
||||
:root[data-theme="ayu"] #src-sidebar div.files > a:hover,
|
||||
:root[data-theme="ayu"] details.dir-entry summary:hover,
|
||||
@ -2569,7 +2721,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
|
||||
border-bottom: 1px solid rgba(242, 151, 24, 0.3);
|
||||
}
|
||||
|
||||
:root[data-theme="ayu"] #settings-menu > a img {
|
||||
:root[data-theme="ayu"] #settings-menu > a img,
|
||||
:root[data-theme="ayu"] #sidebar-button > a:before {
|
||||
filter: invert(100);
|
||||
}
|
||||
/* End theme: ayu */
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Local js definitions:
|
||||
/* global addClass, getSettingValue, hasClass, searchState */
|
||||
/* global addClass, getSettingValue, hasClass, searchState, updateLocalStorage */
|
||||
/* global onEach, onEachLazy, removeClass, getVar */
|
||||
|
||||
"use strict";
|
||||
@ -495,7 +495,7 @@ function preLoadCss(cssUrl) {
|
||||
}
|
||||
const link = document.createElement("a");
|
||||
link.href = path;
|
||||
if (link.href === current_page) {
|
||||
if (path === current_page) {
|
||||
link.className = "current";
|
||||
}
|
||||
link.textContent = name;
|
||||
@ -857,12 +857,12 @@ function preLoadCss(cssUrl) {
|
||||
for (const crate of window.ALL_CRATES) {
|
||||
const link = document.createElement("a");
|
||||
link.href = window.rootPath + crate + "/index.html";
|
||||
if (window.rootPath !== "./" && crate === window.currentCrate) {
|
||||
link.className = "current";
|
||||
}
|
||||
link.textContent = crate;
|
||||
|
||||
const li = document.createElement("li");
|
||||
if (window.rootPath !== "./" && crate === window.currentCrate) {
|
||||
li.className = "current";
|
||||
}
|
||||
li.appendChild(link);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
@ -1473,6 +1473,264 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
searchState.setup();
|
||||
}());
|
||||
|
||||
// Hide, show, and resize the sidebar
|
||||
//
|
||||
// The body class and CSS variable are initially set up in storage.js,
|
||||
// but in this file, we implement:
|
||||
//
|
||||
// * the show sidebar button, which appears if the sidebar is hidden
|
||||
// and, by clicking on it, will bring it back
|
||||
// * the sidebar resize handle, which appears only on large viewports
|
||||
// with a [fine precision pointer] to allow the user to change
|
||||
// the size of the sidebar
|
||||
//
|
||||
// [fine precision pointer]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer
|
||||
(function() {
|
||||
// 100 is the size of the logo
|
||||
// don't let the sidebar get smaller than that, or it'll get squished
|
||||
const SIDEBAR_MIN = 100;
|
||||
// Don't let the sidebar get bigger than this
|
||||
const SIDEBAR_MAX = 500;
|
||||
// Don't let the body (including the gutter) get smaller than this
|
||||
//
|
||||
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||
// Acceptable values for BODY_MIN are constrained by the mobile breakpoint
|
||||
// (which is the minimum size of the whole page where the sidebar exists)
|
||||
// and the default sidebar width:
|
||||
//
|
||||
// BODY_MIN <= RUSTDOC_MOBILE_BREAKPOINT - DEFAULT_SIDEBAR_WIDTH
|
||||
//
|
||||
// At the time of this writing, the DEFAULT_SIDEBAR_WIDTH on src pages is
|
||||
// 300px, and the RUSTDOC_MOBILE_BREAKPOINT is 700px, so BODY_MIN must be
|
||||
// at most 400px. Otherwise, it would start out at the default size, then
|
||||
// grabbing the resize handle would suddenly cause it to jank to
|
||||
// its contraint-generated maximum.
|
||||
const RUSTDOC_MOBILE_BREAKPOINT = 700;
|
||||
const BODY_MIN = 400;
|
||||
// At half-way past the minimum size, vanish the sidebar entirely
|
||||
const SIDEBAR_VANISH_THRESHOLD = SIDEBAR_MIN / 2;
|
||||
|
||||
// Toolbar button to show the sidebar.
|
||||
//
|
||||
// On small, "mobile-sized" viewports, it's not persistent and it
|
||||
// can only be activated by going into Settings and hiding the nav bar.
|
||||
// On larger, "desktop-sized" viewports (though that includes many
|
||||
// tablets), it's fixed-position, appears in the left side margin,
|
||||
// and it can be activated by resizing the sidebar into nothing.
|
||||
const sidebarButton = document.getElementById("sidebar-button");
|
||||
if (sidebarButton) {
|
||||
sidebarButton.addEventListener("click", e => {
|
||||
removeClass(document.documentElement, "hide-sidebar");
|
||||
updateLocalStorage("hide-sidebar", "false");
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
// Pointer capture.
|
||||
//
|
||||
// Resizing is a single-pointer gesture. Any secondary pointer is ignored
|
||||
let currentPointerId = null;
|
||||
|
||||
// "Desired" sidebar size.
|
||||
//
|
||||
// This is stashed here for window resizing. If the sidebar gets
|
||||
// shrunk to maintain BODY_MIN, and then the user grows the window again,
|
||||
// it gets the sidebar to restore its size.
|
||||
let desiredSidebarSize = null;
|
||||
|
||||
// Sidebar resize debouncer.
|
||||
//
|
||||
// The sidebar itself is resized instantly, but the body HTML can be too
|
||||
// big for that, causing reflow jank. To reduce this, we queue up a separate
|
||||
// animation frame and throttle it.
|
||||
let pendingSidebarResizingFrame = false;
|
||||
|
||||
// If this page has no sidebar at all, bail out.
|
||||
const resizer = document.querySelector(".sidebar-resizer");
|
||||
const sidebar = document.querySelector(".sidebar");
|
||||
if (!resizer || !sidebar) {
|
||||
return;
|
||||
}
|
||||
|
||||
// src page and docs page use different variables, because the contents of
|
||||
// the sidebar are so different that it's reasonable to thing the user
|
||||
// would want them to have different sizes
|
||||
const isSrcPage = hasClass(document.body, "src");
|
||||
|
||||
// Call this function to hide the sidebar when using the resize handle
|
||||
//
|
||||
// This function also nulls out the sidebar width CSS variable and setting,
|
||||
// causing it to return to its default. This does not happen if you do it
|
||||
// from settings.js, which uses a separate function. It's done here because
|
||||
// the minimum sidebar size is rather uncomfortable, and it must pass
|
||||
// through that size when using the shrink-to-nothing gesture.
|
||||
function hideSidebar() {
|
||||
if (isSrcPage) {
|
||||
window.rustdocCloseSourceSidebar();
|
||||
updateLocalStorage("src-sidebar-width", null);
|
||||
// [RUSTDOCIMPL] CSS variable fast path
|
||||
//
|
||||
// The sidebar width variable is attached to the <html> element by
|
||||
// storage.js, because the sidebar and resizer don't exist yet.
|
||||
// But the resize code, in `resize()`, sets the property on the
|
||||
// sidebar and resizer elements (which are the only elements that
|
||||
// use the variable) to avoid recalculating CSS on the entire
|
||||
// document on every frame.
|
||||
//
|
||||
// So, to clear it, we need to clear all three.
|
||||
document.documentElement.style.removeProperty("--src-sidebar-width");
|
||||
sidebar.style.removeProperty("--src-sidebar-width");
|
||||
resizer.style.removeProperty("--src-sidebar-width");
|
||||
} else {
|
||||
addClass(document.documentElement, "hide-sidebar");
|
||||
updateLocalStorage("hide-sidebar", "true");
|
||||
updateLocalStorage("desktop-sidebar-width", null);
|
||||
document.documentElement.style.removeProperty("--desktop-sidebar-width");
|
||||
sidebar.style.removeProperty("--desktop-sidebar-width");
|
||||
resizer.style.removeProperty("--desktop-sidebar-width");
|
||||
}
|
||||
}
|
||||
|
||||
// Call this function to show the sidebar from the resize handle.
|
||||
// On docs pages, this can only happen if the user has grabbed the resize
|
||||
// handle, shrunk the sidebar down to nothing, and then pulls back into
|
||||
// the visible range without releasing it. You can, however, grab the
|
||||
// resize handle on a source page with the sidebar closed, because it
|
||||
// remains visible all the time on there.
|
||||
function showSidebar() {
|
||||
if (isSrcPage) {
|
||||
window.rustdocShowSourceSidebar();
|
||||
} else {
|
||||
removeClass(document.documentElement, "hide-sidebar");
|
||||
updateLocalStorage("hide-sidebar", "false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to set the correct CSS variable and setting.
|
||||
* This function doesn't enforce size constraints. Do that before calling it!
|
||||
*
|
||||
* @param {number} size - CSS px width of the sidebar.
|
||||
*/
|
||||
function changeSidebarSize(size) {
|
||||
if (isSrcPage) {
|
||||
updateLocalStorage("src-sidebar-width", size);
|
||||
// [RUSTDOCIMPL] CSS variable fast path
|
||||
//
|
||||
// While this property is set on the HTML element at load time,
|
||||
// because the sidebar isn't actually loaded yet,
|
||||
// we scope this update to the sidebar to avoid hitting a slow
|
||||
// path in WebKit.
|
||||
sidebar.style.setProperty("--src-sidebar-width", size + "px");
|
||||
resizer.style.setProperty("--src-sidebar-width", size + "px");
|
||||
} else {
|
||||
updateLocalStorage("desktop-sidebar-width", size);
|
||||
sidebar.style.setProperty("--desktop-sidebar-width", size + "px");
|
||||
resizer.style.setProperty("--desktop-sidebar-width", size + "px");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the sidebar is hidden. Since src pages and doc pages have
|
||||
// different settings, this function has to check that.
|
||||
function isSidebarHidden() {
|
||||
return isSrcPage ?
|
||||
!hasClass(document.documentElement, "src-sidebar-expanded") :
|
||||
hasClass(document.documentElement, "hide-sidebar");
|
||||
}
|
||||
|
||||
// Respond to the resize handle event.
|
||||
// This function enforces size constraints, and implements the
|
||||
// shrink-to-nothing gesture based on thresholds defined above.
|
||||
function resize(e) {
|
||||
if (currentPointerId === null || currentPointerId !== e.pointerId) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
const pos = e.clientX - sidebar.offsetLeft - 3;
|
||||
if (pos < SIDEBAR_VANISH_THRESHOLD) {
|
||||
hideSidebar();
|
||||
} else if (pos >= SIDEBAR_MIN) {
|
||||
if (isSidebarHidden()) {
|
||||
showSidebar();
|
||||
}
|
||||
// don't let the sidebar get wider than SIDEBAR_MAX, or the body narrower
|
||||
// than BODY_MIN
|
||||
const constrainedPos = Math.min(pos, window.innerWidth - BODY_MIN, SIDEBAR_MAX);
|
||||
changeSidebarSize(constrainedPos);
|
||||
desiredSidebarSize = constrainedPos;
|
||||
if (pendingSidebarResizingFrame !== false) {
|
||||
clearTimeout(pendingSidebarResizingFrame);
|
||||
}
|
||||
pendingSidebarResizingFrame = setTimeout(() => {
|
||||
if (currentPointerId === null || pendingSidebarResizingFrame === false) {
|
||||
return;
|
||||
}
|
||||
pendingSidebarResizingFrame = false;
|
||||
document.documentElement.style.setProperty(
|
||||
"--resizing-sidebar-width",
|
||||
desiredSidebarSize + "px"
|
||||
);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
// Respond to the window resize event.
|
||||
window.addEventListener("resize", () => {
|
||||
if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
|
||||
return;
|
||||
}
|
||||
stopResize();
|
||||
if (desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
|
||||
changeSidebarSize(window.innerWidth - BODY_MIN);
|
||||
} else if (desiredSidebarSize !== null && desiredSidebarSize > SIDEBAR_MIN) {
|
||||
changeSidebarSize(desiredSidebarSize);
|
||||
}
|
||||
});
|
||||
function stopResize(e) {
|
||||
if (currentPointerId === null) {
|
||||
return;
|
||||
}
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
desiredSidebarSize = sidebar.getBoundingClientRect().width;
|
||||
removeClass(resizer, "active");
|
||||
window.removeEventListener("pointermove", resize, false);
|
||||
window.removeEventListener("pointerup", stopResize, false);
|
||||
removeClass(document.documentElement, "sidebar-resizing");
|
||||
document.documentElement.style.removeProperty( "--resizing-sidebar-width");
|
||||
if (resizer.releasePointerCapture) {
|
||||
resizer.releasePointerCapture(currentPointerId);
|
||||
currentPointerId = null;
|
||||
}
|
||||
}
|
||||
function initResize(e) {
|
||||
if (currentPointerId !== null || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
if (resizer.setPointerCapture) {
|
||||
resizer.setPointerCapture(e.pointerId);
|
||||
if (!resizer.hasPointerCapture(e.pointerId)) {
|
||||
// unable to capture pointer; something else has it
|
||||
// on iOS, this usually means you long-clicked a link instead
|
||||
resizer.releasePointerCapture(e.pointerId);
|
||||
return;
|
||||
}
|
||||
currentPointerId = e.pointerId;
|
||||
}
|
||||
e.preventDefault();
|
||||
window.addEventListener("pointermove", resize, false);
|
||||
window.addEventListener("pointercancel", stopResize, false);
|
||||
window.addEventListener("pointerup", stopResize, false);
|
||||
addClass(resizer, "active");
|
||||
addClass(document.documentElement, "sidebar-resizing");
|
||||
const pos = e.clientX - sidebar.offsetLeft - 3;
|
||||
document.documentElement.style.setProperty( "--resizing-sidebar-width", pos + "px");
|
||||
desiredSidebarSize = null;
|
||||
}
|
||||
resizer.addEventListener("pointerdown", initResize, false);
|
||||
}());
|
||||
|
||||
// This section handles the copy button that appears next to the path breadcrumbs
|
||||
(function() {
|
||||
let reset_button_timeout = null;
|
||||
|
||||
|
@ -29,6 +29,13 @@
|
||||
window.rustdoc_remove_line_numbers_from_examples();
|
||||
}
|
||||
break;
|
||||
case "hide-sidebar":
|
||||
if (value === true) {
|
||||
addClass(document.documentElement, "hide-sidebar");
|
||||
} else {
|
||||
removeClass(document.documentElement, "hide-sidebar");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,6 +193,11 @@
|
||||
"js_name": "line-numbers",
|
||||
"default": false,
|
||||
},
|
||||
{
|
||||
"name": "Hide persistent navigation bar",
|
||||
"js_name": "hide-sidebar",
|
||||
"default": false,
|
||||
},
|
||||
{
|
||||
"name": "Disable keyboard shortcuts",
|
||||
"js_name": "disable-shortcuts",
|
||||
@ -216,6 +228,13 @@
|
||||
|
||||
function displaySettings() {
|
||||
settingsMenu.style.display = "";
|
||||
onEachLazy(settingsMenu.querySelectorAll("input[type='checkbox']"), el => {
|
||||
const val = getSettingValue(el.id);
|
||||
const checked = val === "true";
|
||||
if (checked !== el.checked && val !== null) {
|
||||
el.checked = checked;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function settingsBlurHandler(event) {
|
||||
|
@ -71,16 +71,31 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
|
||||
return hasFoundFile;
|
||||
}
|
||||
|
||||
let toggleLabel;
|
||||
|
||||
function getToggleLabel() {
|
||||
toggleLabel = toggleLabel || document.querySelector("#src-sidebar-toggle button");
|
||||
return toggleLabel;
|
||||
}
|
||||
|
||||
window.rustdocCloseSourceSidebar = () => {
|
||||
removeClass(document.documentElement, "src-sidebar-expanded");
|
||||
getToggleLabel().innerText = ">";
|
||||
updateLocalStorage("source-sidebar-show", "false");
|
||||
};
|
||||
|
||||
window.rustdocShowSourceSidebar = () => {
|
||||
addClass(document.documentElement, "src-sidebar-expanded");
|
||||
getToggleLabel().innerText = "<";
|
||||
updateLocalStorage("source-sidebar-show", "true");
|
||||
};
|
||||
|
||||
function toggleSidebar() {
|
||||
const child = this.parentNode.children[0];
|
||||
if (child.innerText === ">") {
|
||||
addClass(document.documentElement, "src-sidebar-expanded");
|
||||
child.innerText = "<";
|
||||
updateLocalStorage("source-sidebar-show", "true");
|
||||
window.rustdocShowSourceSidebar();
|
||||
} else {
|
||||
removeClass(document.documentElement, "src-sidebar-expanded");
|
||||
child.innerText = ">";
|
||||
updateLocalStorage("source-sidebar-show", "false");
|
||||
window.rustdocCloseSourceSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,11 +183,38 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
|
||||
|
||||
updateTheme();
|
||||
|
||||
// Hide, show, and resize the sidebar at page load time
|
||||
//
|
||||
// This needs to be done here because this JS is render-blocking,
|
||||
// so that the sidebar doesn't "jump" after appearing on screen.
|
||||
// The user interaction to change this is set up in main.js.
|
||||
if (getSettingValue("source-sidebar-show") === "true") {
|
||||
// At this point in page load, `document.body` is not available yet.
|
||||
// Set a class on the `<html>` element instead.
|
||||
addClass(document.documentElement, "src-sidebar-expanded");
|
||||
}
|
||||
if (getSettingValue("hide-sidebar") === "true") {
|
||||
// At this point in page load, `document.body` is not available yet.
|
||||
// Set a class on the `<html>` element instead.
|
||||
addClass(document.documentElement, "hide-sidebar");
|
||||
}
|
||||
function updateSidebarWidth() {
|
||||
const desktopSidebarWidth = getSettingValue("desktop-sidebar-width");
|
||||
if (desktopSidebarWidth && desktopSidebarWidth !== "null") {
|
||||
document.documentElement.style.setProperty(
|
||||
"--desktop-sidebar-width",
|
||||
desktopSidebarWidth + "px"
|
||||
);
|
||||
}
|
||||
const srcSidebarWidth = getSettingValue("src-sidebar-width");
|
||||
if (srcSidebarWidth && srcSidebarWidth !== "null") {
|
||||
document.documentElement.style.setProperty(
|
||||
"--src-sidebar-width",
|
||||
srcSidebarWidth + "px"
|
||||
);
|
||||
}
|
||||
}
|
||||
updateSidebarWidth();
|
||||
|
||||
// If we navigate away (for example to a settings page), and then use the back or
|
||||
// forward button to get back to a page, the theme may have changed in the meantime.
|
||||
@ -201,5 +228,6 @@ if (getSettingValue("source-sidebar-show") === "true") {
|
||||
window.addEventListener("pageshow", ev => {
|
||||
if (ev.persisted) {
|
||||
setTimeout(updateTheme, 0);
|
||||
setTimeout(updateSidebarWidth, 0);
|
||||
}
|
||||
});
|
||||
|
@ -114,6 +114,7 @@
|
||||
{% endif %}
|
||||
{{ sidebar|safe }}
|
||||
</nav> {# #}
|
||||
<div class="sidebar-resizer"></div>
|
||||
<main> {# #}
|
||||
{% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
|
||||
<nav class="sub"> {# #}
|
||||
@ -128,6 +129,11 @@
|
||||
{% endif %}
|
||||
<form class="search-form"> {# #}
|
||||
<span></span> {# This empty span is a hacky fix for Safari - See #93184 #}
|
||||
{% if page.css_class != "src" %}
|
||||
<div id="sidebar-button" tabindex="-1"> {# #}
|
||||
<a href="{{page.root_path|safe}}{{layout.krate|safe}}/all.html" title="show sidebar"></a> {# #}
|
||||
</div> {# #}
|
||||
{% endif %}
|
||||
<input {#+ #}
|
||||
class="search-input" {#+ #}
|
||||
name="search" {#+ #}
|
||||
@ -136,8 +142,8 @@
|
||||
spellcheck="false" {#+ #}
|
||||
placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {#+ #}
|
||||
type="search"> {# #}
|
||||
<div id="help-button" title="help" tabindex="-1"> {# #}
|
||||
<a href="{{page.root_path|safe}}help.html">?</a> {# #}
|
||||
<div id="help-button" tabindex="-1"> {# #}
|
||||
<a href="{{page.root_path|safe}}help.html" title="help">?</a> {# #}
|
||||
</div> {# #}
|
||||
<div id="settings-menu" tabindex="-1"> {# #}
|
||||
<a href="{{page.root_path|safe}}settings.html" title="settings"> {# #}
|
||||
|
20
tests/rustdoc-gui/hide-mobile-topbar.goml
Normal file
20
tests/rustdoc-gui/hide-mobile-topbar.goml
Normal file
@ -0,0 +1,20 @@
|
||||
// Checks sidebar resizing stays synced with the setting
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
set-window-size: (400, 600)
|
||||
|
||||
// Verify that the "hide" option is unchecked
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: ("#settings", {"display": "block"})
|
||||
assert-property: ("#hide-sidebar", {"checked": "false"})
|
||||
assert-css: (".mobile-topbar", {"display": "flex"})
|
||||
|
||||
// Toggle it
|
||||
click: "#hide-sidebar"
|
||||
assert-property: ("#hide-sidebar", {"checked": "true"})
|
||||
assert-css: (".mobile-topbar", {"display": "none"})
|
||||
|
||||
// Toggle it again
|
||||
click: "#hide-sidebar"
|
||||
assert-property: ("#hide-sidebar", {"checked": "false"})
|
||||
assert-css: (".mobile-topbar", {"display": "flex"})
|
@ -26,12 +26,12 @@ define-function: (
|
||||
assert-css: (".item-table .keyword", {"color": |keyword|}, ALL)
|
||||
// Checking sidebar elements.
|
||||
assert-css: (
|
||||
".sidebar-elems a:not(.current)",
|
||||
".sidebar-elems li:not(.current) a",
|
||||
{"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
|
||||
ALL,
|
||||
)
|
||||
assert-css: (
|
||||
".sidebar-elems a.current",
|
||||
".sidebar-elems li.current a",
|
||||
{
|
||||
"color": |sidebar_current|,
|
||||
"background-color": |sidebar_current_background|,
|
||||
|
@ -17,10 +17,10 @@ define-function: (
|
||||
reload:
|
||||
// Struct
|
||||
assert-css: (
|
||||
".sidebar .block.struct a:not(.current)",
|
||||
".sidebar .block.struct li:not(.current) a",
|
||||
{"color": |struct|, "background-color": "rgba(0, 0, 0, 0)"},
|
||||
)
|
||||
move-cursor-to: ".sidebar .block.struct a:not(.current)"
|
||||
move-cursor-to: ".sidebar .block.struct li:not(.current) a"
|
||||
assert-css: (
|
||||
".sidebar .block.struct a:hover",
|
||||
{"color": |struct_hover|, "background-color": |struct_hover_background|},
|
||||
|
23
tests/rustdoc-gui/sidebar-resize-setting.goml
Normal file
23
tests/rustdoc-gui/sidebar-resize-setting.goml
Normal file
@ -0,0 +1,23 @@
|
||||
// Checks sidebar resizing stays synced with the setting
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
show-text: true
|
||||
|
||||
// Verify that the "hide" option is unchecked
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: ("#settings", {"display": "block"})
|
||||
assert-property: ("#hide-sidebar", {"checked": "false"})
|
||||
press-key: "Escape"
|
||||
wait-for-css: ("#settings", {"display": "none"})
|
||||
|
||||
drag-and-drop: ((205, 100), (5, 100))
|
||||
assert-css: (".sidebar", {"display": "none"})
|
||||
|
||||
// Verify that the "hide" option is checked
|
||||
focus: "#settings-menu a"
|
||||
press-key: "Enter"
|
||||
wait-for-css: ("#settings", {"display": "block"})
|
||||
assert-property: ("#hide-sidebar", {"checked": "true"})
|
||||
click: "#hide-sidebar"
|
||||
wait-for-css: (".sidebar", {"display": "block"})
|
37
tests/rustdoc-gui/sidebar-resize-window.goml
Normal file
37
tests/rustdoc-gui/sidebar-resize-window.goml
Normal file
@ -0,0 +1,37 @@
|
||||
// Checks sidebar resizing
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
set-window-size: (1280, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 200}, [NEAR])
|
||||
|
||||
// resize past maximum (don't grow past 500)
|
||||
drag-and-drop: ((205, 100), (600, 100))
|
||||
wait-for-property: (".sidebar", {"clientWidth": 500}, [NEAR])
|
||||
|
||||
// make the window small enough that the sidebar has to shrink
|
||||
set-window-size: (750, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 350}, [NEAR])
|
||||
|
||||
// grow the window again to make the sidebar bigger
|
||||
set-window-size: (1280, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 500}, [NEAR])
|
||||
|
||||
// make the window small enough that the sidebar has to shrink
|
||||
set-window-size: (750, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 350}, [NEAR])
|
||||
assert-local-storage: {"rustdoc-desktop-sidebar-width": "350"}
|
||||
set-window-size: (400, 600)
|
||||
wait-for-css: (".sidebar", {"display": "block", "left": "-1000px"})
|
||||
assert-local-storage: {"rustdoc-desktop-sidebar-width": "350"}
|
||||
|
||||
// grow the window again to make the sidebar bigger
|
||||
set-window-size: (1280, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 500}, [NEAR])
|
||||
|
||||
// shrink back down again, then reload the page
|
||||
// the "desired size" is a bit of remembered implicit state,
|
||||
// and rustdoc tries to minimize things like this
|
||||
set-window-size: (800, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 400}, [NEAR])
|
||||
reload:
|
||||
set-window-size: (1280, 600)
|
||||
wait-for-property: (".sidebar", {"clientWidth": 400}, [NEAR])
|
28
tests/rustdoc-gui/sidebar-resize.goml
Normal file
28
tests/rustdoc-gui/sidebar-resize.goml
Normal file
@ -0,0 +1,28 @@
|
||||
// Checks sidebar resizing
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
show-text: true
|
||||
// normal resizing
|
||||
drag-and-drop: ((205, 100), (185, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "182"})
|
||||
// resize past maximum (don't grow past 500)
|
||||
drag-and-drop: ((185, 100), (600, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "500"})
|
||||
// resize past minimum (hide sidebar)
|
||||
drag-and-drop: ((501, 100), (5, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "0"})
|
||||
assert-css: (".sidebar", {"display": "none"})
|
||||
assert-local-storage: {"rustdoc-hide-sidebar": "true"}
|
||||
set-local-storage: {"rustdoc-hide-sidebar": "false"}
|
||||
|
||||
// Now same thing, but for source code
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "49"})
|
||||
drag-and-drop: ((52, 100), (185, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "181"})
|
||||
drag-and-drop: ((185, 100), (600, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "499"})
|
||||
drag-and-drop: ((500, 100), (5, 100))
|
||||
// instead of hiding the sidebar entirely, this
|
||||
// will switch to the toggle mode
|
||||
assert-property: (".sidebar", {"clientWidth": "49"})
|
@ -48,6 +48,7 @@ call-function: (
|
||||
|
||||
// Next, desktop mode layout.
|
||||
set-window-size: (1100, 800)
|
||||
wait-for: "#src-sidebar-toggle"
|
||||
// We check that the sidebar isn't expanded and has the expected width.
|
||||
assert-css: ("nav.sidebar", {"width": "50px"})
|
||||
// We now click on the button to expand the sidebar.
|
||||
@ -58,7 +59,7 @@ assert-css: (".src-sidebar-expanded nav.sidebar a", {"font-size": "14px"})
|
||||
// We collapse the sidebar.
|
||||
click: (10, 10)
|
||||
// We ensure that the class has been removed.
|
||||
wait-for: "html:not(.expanded)"
|
||||
wait-for: "html:not(.src-sidebar-expanded)"
|
||||
assert: "nav.sidebar"
|
||||
|
||||
// Checking that only the path to the current file is "open".
|
||||
|
@ -57,7 +57,7 @@ assert-count: (".sidebar h2", 1)
|
||||
assert-text: ("#all-types", "All Items")
|
||||
assert-css: ("#all-types", {"color": "#356da4"})
|
||||
// We check that we have the crates list and that the "current" on is "test_docs".
|
||||
assert-text: (".sidebar-elems ul.crate > li > a.current", "test_docs")
|
||||
assert-text: (".sidebar-elems ul.crate > li.current > a", "test_docs")
|
||||
// And we're also supposed to have the list of items in the current module.
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Re-exports")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Modules")
|
||||
@ -98,7 +98,7 @@ assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
|
||||
assert-count: (".sidebar .location", 0)
|
||||
// We check that we have the crates list and that the "current" on is now "lib2".
|
||||
assert-text: (".sidebar-elems ul.crate > li > a.current", "lib2")
|
||||
assert-text: (".sidebar-elems ul.crate > li.current > a", "lib2")
|
||||
// We now go to the "foobar" function page.
|
||||
assert-text: (".sidebar-elems > section ul.block > li:nth-child(1)", "Modules")
|
||||
assert-text: (".sidebar-elems > section ul.block > li:nth-child(2)", "Structs")
|
||||
|
@ -96,4 +96,6 @@
|
||||
--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);
|
||||
--sidebar-resizer-hover: hsl(207, 90%, 66%);
|
||||
--sidebar-resizer-active: hsl(207, 90%, 54%);
|
||||
}
|
||||
|
30
tests/rustdoc/reexport-cfg.rs
Normal file
30
tests/rustdoc/reexport-cfg.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// This test ensures that only the re-export `cfg` will be displayed and that it won't
|
||||
// include `cfg`s from the previous chained items.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
#![feature(doc_auto_cfg, doc_cfg)]
|
||||
|
||||
mod foo {
|
||||
#[cfg(not(feature = "foo"))]
|
||||
pub struct Bar;
|
||||
|
||||
#[doc(cfg(not(feature = "bar")))]
|
||||
pub struct Bar2;
|
||||
}
|
||||
|
||||
// @has 'foo/index.html'
|
||||
// @has - '//*[@class="item-name"]' 'BabarNon-lie'
|
||||
#[cfg(not(feature = "lie"))]
|
||||
pub use crate::foo::Bar as Babar;
|
||||
|
||||
// @has - '//*[@class="item-name"]' 'Babar2Non-cake'
|
||||
#[doc(cfg(not(feature = "cake")))]
|
||||
pub use crate::foo::Bar2 as Babar2;
|
||||
|
||||
// @has - '//*[@class="item-table"]/li' 'pub use crate::Babar as Elephant;Non-robot'
|
||||
#[cfg(not(feature = "robot"))]
|
||||
pub use crate::Babar as Elephant;
|
||||
|
||||
// @has - '//*[@class="item-table"]/li' 'pub use crate::Babar2 as Elephant2;Non-cat'
|
||||
#[doc(cfg(not(feature = "cat")))]
|
||||
pub use crate::Babar2 as Elephant2;
|
@ -27,7 +27,7 @@ pub mod mod1 {
|
||||
pub mod mod2 {
|
||||
// @has - '//code' 'pub use tag::Portability;'
|
||||
// @!has - '//span' 'Deprecated'
|
||||
// @has - '//span' 'sync'
|
||||
// @!has - '//span' 'sync'
|
||||
pub use tag::Portability;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ pub mod mod2 {
|
||||
pub mod mod3 {
|
||||
// @has - '//code' 'pub use tag::Both;'
|
||||
// @has - '//span' 'Deprecated'
|
||||
// @has - '//span' 'sync'
|
||||
// @!has - '//span' 'sync'
|
||||
pub use tag::Both;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ pub mod mod1 {
|
||||
pub mod mod2 {
|
||||
// @has - '//code' 'pub use tag::Portability;'
|
||||
// @!has - '//span' 'Experimental'
|
||||
// @has - '//span' 'sync'
|
||||
// @!has - '//span' 'sync'
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use tag::Portability;
|
||||
}
|
||||
@ -45,7 +45,7 @@ pub mod mod2 {
|
||||
pub mod mod3 {
|
||||
// @has - '//code' 'pub use tag::Both;'
|
||||
// @has - '//span' 'Experimental'
|
||||
// @has - '//span' 'sync'
|
||||
// @!has - '//span' 'sync'
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use tag::Both;
|
||||
}
|
||||
|
@ -113,6 +113,13 @@ unsafe fn assign_to_ref() {
|
||||
*((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5;
|
||||
//~^ ERROR assigning to `&T` is undefined behavior
|
||||
|
||||
let value = num as *const i32 as *mut i32;
|
||||
*value = 1;
|
||||
//~^ ERROR assigning to `&T` is undefined behavior
|
||||
let value = num as *const i32;
|
||||
let value = value as *mut i32;
|
||||
*value = 1;
|
||||
//~^ ERROR assigning to `&T` is undefined behavior
|
||||
let value = num as *const i32 as *mut i32;
|
||||
*value = 1;
|
||||
//~^ ERROR assigning to `&T` is undefined behavior
|
||||
|
@ -286,7 +286,27 @@ LL | *value = 1;
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:120:5
|
||||
--> $DIR/reference_casting.rs:121:5
|
||||
|
|
||||
LL | let value = value as *mut i32;
|
||||
| ----------------- casting happend here
|
||||
LL | *value = 1;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:124:5
|
||||
|
|
||||
LL | let value = num as *const i32 as *mut i32;
|
||||
| ----------------------------- casting happend here
|
||||
LL | *value = 1;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:127:5
|
||||
|
|
||||
LL | let value = num as *const i32 as *mut i32;
|
||||
| ----------------------------- casting happend here
|
||||
@ -297,7 +317,7 @@ LL | *value_rebind = 1;
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:122:5
|
||||
--> $DIR/reference_casting.rs:129:5
|
||||
|
|
||||
LL | *(num as *const i32).cast::<i32>().cast_mut() = 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -305,7 +325,7 @@ LL | *(num as *const i32).cast::<i32>().cast_mut() = 2;
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:124:5
|
||||
--> $DIR/reference_casting.rs:131:5
|
||||
|
|
||||
LL | *(num as *const _ as usize as *mut i32) = 2;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -313,7 +333,7 @@ LL | *(num as *const _ as usize as *mut i32) = 2;
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:126:5
|
||||
--> $DIR/reference_casting.rs:133:5
|
||||
|
|
||||
LL | let value = num as *const i32 as *mut i32;
|
||||
| ----------------------------- casting happend here
|
||||
@ -324,7 +344,7 @@ LL | std::ptr::write(value, 2);
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:128:5
|
||||
--> $DIR/reference_casting.rs:135:5
|
||||
|
|
||||
LL | let value = num as *const i32 as *mut i32;
|
||||
| ----------------------------- casting happend here
|
||||
@ -335,7 +355,7 @@ LL | std::ptr::write_unaligned(value, 2);
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:130:5
|
||||
--> $DIR/reference_casting.rs:137:5
|
||||
|
|
||||
LL | let value = num as *const i32 as *mut i32;
|
||||
| ----------------------------- casting happend here
|
||||
@ -346,12 +366,12 @@ LL | std::ptr::write_volatile(value, 2);
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
|
||||
--> $DIR/reference_casting.rs:134:9
|
||||
--> $DIR/reference_casting.rs:141:9
|
||||
|
|
||||
LL | *(this as *const _ as *mut _) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
|
||||
|
||||
error: aborting due to 40 previous errors
|
||||
error: aborting due to 42 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user