Skip to content

Commit 4d1bd0d

Browse files
committed
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
2 parents 96df494 + 25216b6 commit 4d1bd0d

27 files changed

+822
-148
lines changed

compiler/rustc_lint/src/reference_casting.rs

+81-57
Original file line numberDiff line numberDiff line change
@@ -37,59 +37,73 @@ declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]);
3737

3838
impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
3939
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
40-
let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
41-
return;
42-
};
43-
44-
let init = cx.expr_or_init(e);
45-
46-
let Some(ty_has_interior_mutability) = is_cast_from_const_to_mut(cx, init) else {
47-
return;
48-
};
49-
let orig_cast = if init.span != e.span { Some(init.span) } else { None };
50-
let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
51-
52-
cx.emit_spanned_lint(
53-
INVALID_REFERENCE_CASTING,
54-
expr.span,
55-
if is_assignment {
56-
InvalidReferenceCastingDiag::AssignToRef { orig_cast, ty_has_interior_mutability }
57-
} else {
58-
InvalidReferenceCastingDiag::BorrowAsMut { orig_cast, ty_has_interior_mutability }
59-
},
60-
);
40+
if let Some((e, pat)) = borrow_or_assign(cx, expr) {
41+
if matches!(pat, PatternKind::Borrow { mutbl: Mutability::Mut } | PatternKind::Assign) {
42+
let init = cx.expr_or_init(e);
43+
44+
let Some(ty_has_interior_mutability) = is_cast_from_ref_to_mut_ptr(cx, init) else {
45+
return;
46+
};
47+
let orig_cast = if init.span != e.span { Some(init.span) } else { None };
48+
let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
49+
50+
cx.emit_spanned_lint(
51+
INVALID_REFERENCE_CASTING,
52+
expr.span,
53+
if pat == PatternKind::Assign {
54+
InvalidReferenceCastingDiag::AssignToRef {
55+
orig_cast,
56+
ty_has_interior_mutability,
57+
}
58+
} else {
59+
InvalidReferenceCastingDiag::BorrowAsMut {
60+
orig_cast,
61+
ty_has_interior_mutability,
62+
}
63+
},
64+
);
65+
}
66+
}
6167
}
6268
}
6369

64-
fn is_operation_we_care_about<'tcx>(
70+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71+
enum PatternKind {
72+
Borrow { mutbl: Mutability },
73+
Assign,
74+
}
75+
76+
fn borrow_or_assign<'tcx>(
6577
cx: &LateContext<'tcx>,
6678
e: &'tcx Expr<'tcx>,
67-
) -> Option<(bool, &'tcx Expr<'tcx>)> {
68-
fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> {
69-
// &mut <expr>
70-
let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
71-
expr
79+
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
80+
fn deref_assign_or_addr_of<'tcx>(
81+
expr: &'tcx Expr<'tcx>,
82+
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
83+
// &(mut) <expr>
84+
let (inner, pat) = if let ExprKind::AddrOf(_, mutbl, expr) = expr.kind {
85+
(expr, PatternKind::Borrow { mutbl })
7286
// <expr> = ...
7387
} else if let ExprKind::Assign(expr, _, _) = expr.kind {
74-
expr
88+
(expr, PatternKind::Assign)
7589
// <expr> += ...
7690
} else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
77-
expr
91+
(expr, PatternKind::Assign)
7892
} else {
7993
return None;
8094
};
8195

82-
if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind {
83-
Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e))
84-
} else {
85-
None
86-
}
96+
// *<inner>
97+
let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
98+
return None;
99+
};
100+
Some((e, pat))
87101
}
88102

89103
fn ptr_write<'tcx>(
90104
cx: &LateContext<'tcx>,
91105
e: &'tcx Expr<'tcx>,
92-
) -> Option<(bool, &'tcx Expr<'tcx>)> {
106+
) -> Option<(&'tcx Expr<'tcx>, PatternKind)> {
93107
if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind
94108
&& let ExprKind::Path(ref qpath) = path.kind
95109
&& 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>(
98112
Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned)
99113
)
100114
{
101-
Some((true, arg_ptr))
115+
Some((arg_ptr, PatternKind::Assign))
102116
} else {
103117
None
104118
}
@@ -107,20 +121,39 @@ fn is_operation_we_care_about<'tcx>(
107121
deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
108122
}
109123

110-
fn is_cast_from_const_to_mut<'tcx>(
124+
fn is_cast_from_ref_to_mut_ptr<'tcx>(
111125
cx: &LateContext<'tcx>,
112126
orig_expr: &'tcx Expr<'tcx>,
113127
) -> Option<bool> {
114-
let mut need_check_freeze = false;
115-
let mut e = orig_expr;
116-
117128
let end_ty = cx.typeck_results().node_type(orig_expr.hir_id);
118129

119130
// Bail out early if the end type is **not** a mutable pointer.
120131
if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) {
121132
return None;
122133
}
123134

135+
let (e, need_check_freeze) = peel_casts(cx, orig_expr);
136+
137+
let start_ty = cx.typeck_results().node_type(e.hir_id);
138+
if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() {
139+
// If an UnsafeCell method is involved, we need to additionally check the
140+
// inner type for the presence of the Freeze trait (ie does NOT contain
141+
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
142+
//
143+
// Except on the presence of non concrete skeleton types (ie generics)
144+
// since there is no way to make it safe for arbitrary types.
145+
let inner_ty_has_interior_mutability =
146+
!inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton();
147+
(!need_check_freeze || !inner_ty_has_interior_mutability)
148+
.then_some(inner_ty_has_interior_mutability)
149+
} else {
150+
None
151+
}
152+
}
153+
154+
fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
155+
let mut gone_trough_unsafe_cell_raw_get = false;
156+
124157
loop {
125158
e = e.peel_blocks();
126159
// <expr> as ...
@@ -145,27 +178,18 @@ fn is_cast_from_const_to_mut<'tcx>(
145178
)
146179
{
147180
if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
148-
need_check_freeze = true;
181+
gone_trough_unsafe_cell_raw_get = true;
149182
}
150183
arg
151184
} else {
152-
break;
185+
let init = cx.expr_or_init(e);
186+
if init.hir_id != e.hir_id {
187+
init
188+
} else {
189+
break;
190+
}
153191
};
154192
}
155193

156-
let start_ty = cx.typeck_results().node_type(e.hir_id);
157-
if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() {
158-
// If an UnsafeCell method is involved we need to additionally check the
159-
// inner type for the presence of the Freeze trait (ie does NOT contain
160-
// an UnsafeCell), since in that case we would incorrectly lint on valid casts.
161-
//
162-
// We also consider non concrete skeleton types (ie generics)
163-
// to be an issue since there is no way to make it safe for abitrary types.
164-
let inner_ty_has_interior_mutability =
165-
!inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton();
166-
(!need_check_freeze || !inner_ty_has_interior_mutability)
167-
.then_some(inner_ty_has_interior_mutability)
168-
} else {
169-
None
170-
}
194+
(e, gone_trough_unsafe_cell_raw_get)
171195
}

compiler/rustc_mir_build/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Construction of MIR from HIR.
22
//!
33
//! This crate also contains the match exhaustiveness and usefulness checking.
4-
#![allow(rustc::potential_query_instability)]
54
#![feature(assert_matches)]
65
#![feature(associated_type_bounds)]
76
#![feature(box_patterns)]

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::errors::*;
99

1010
use rustc_arena::TypedArena;
1111
use rustc_ast::Mutability;
12-
use rustc_data_structures::fx::FxHashSet;
12+
use rustc_data_structures::fx::FxIndexSet;
1313
use rustc_data_structures::stack::ensure_sufficient_stack;
1414
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
1515
use rustc_hir as hir;
@@ -948,7 +948,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
948948
err.note(format!("the matched value is of type `{}`", scrut_ty));
949949

950950
if !is_empty_match {
951-
let mut non_exhaustive_tys = FxHashSet::default();
951+
let mut non_exhaustive_tys = FxIndexSet::default();
952952
// Look at the first witness.
953953
collect_non_exhaustive_tys(cx, &witnesses[0], &mut non_exhaustive_tys);
954954

@@ -1104,7 +1104,7 @@ fn joined_uncovered_patterns<'p, 'tcx>(
11041104
fn collect_non_exhaustive_tys<'tcx>(
11051105
cx: &MatchCheckCtxt<'_, 'tcx>,
11061106
pat: &WitnessPat<'tcx>,
1107-
non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>,
1107+
non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
11081108
) {
11091109
if matches!(pat.ctor(), Constructor::NonExhaustive) {
11101110
non_exhaustive_tys.insert(pat.ty());

src/librustdoc/clean/mod.rs

+42-34
Original file line numberDiff line numberDiff line change
@@ -2646,6 +2646,40 @@ fn filter_tokens_from_list(
26462646
tokens
26472647
}
26482648

2649+
fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
2650+
if is_inline {
2651+
ident == sym::hidden || ident == sym::inline || ident == sym::no_inline
2652+
} else {
2653+
ident == sym::cfg
2654+
}
2655+
}
2656+
2657+
/// Remove attributes from `normal` that should not be inherited by `use` re-export.
2658+
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
2659+
fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
2660+
match normal.item.args {
2661+
ast::AttrArgs::Delimited(ref mut args) => {
2662+
let tokens = filter_tokens_from_list(&args.tokens, |token| {
2663+
!matches!(
2664+
token,
2665+
TokenTree::Token(
2666+
Token {
2667+
kind: TokenKind::Ident(
2668+
ident,
2669+
_,
2670+
),
2671+
..
2672+
},
2673+
_,
2674+
) if filter_doc_attr_ident(*ident, is_inline),
2675+
)
2676+
});
2677+
args.tokens = TokenStream::new(tokens);
2678+
}
2679+
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {}
2680+
}
2681+
}
2682+
26492683
/// When inlining items, we merge their attributes (and all the reexports attributes too) with the
26502684
/// final reexport. For example:
26512685
///
@@ -2672,13 +2706,6 @@ fn add_without_unwanted_attributes<'hir>(
26722706
is_inline: bool,
26732707
import_parent: Option<DefId>,
26742708
) {
2675-
// If it's not `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
2676-
if !is_inline {
2677-
for attr in new_attrs {
2678-
attrs.push((Cow::Borrowed(attr), import_parent));
2679-
}
2680-
return;
2681-
}
26822709
for attr in new_attrs {
26832710
if matches!(attr.kind, ast::AttrKind::DocComment(..)) {
26842711
attrs.push((Cow::Borrowed(attr), import_parent));
@@ -2687,33 +2714,14 @@ fn add_without_unwanted_attributes<'hir>(
26872714
let mut attr = attr.clone();
26882715
match attr.kind {
26892716
ast::AttrKind::Normal(ref mut normal) => {
2690-
if let [ident] = &*normal.item.path.segments
2691-
&& let ident = ident.ident.name
2692-
&& ident == sym::doc
2693-
{
2694-
match normal.item.args {
2695-
ast::AttrArgs::Delimited(ref mut args) => {
2696-
let tokens = filter_tokens_from_list(&args.tokens, |token| {
2697-
!matches!(
2698-
token,
2699-
TokenTree::Token(
2700-
Token {
2701-
kind: TokenKind::Ident(
2702-
sym::hidden | sym::inline | sym::no_inline,
2703-
_,
2704-
),
2705-
..
2706-
},
2707-
_,
2708-
),
2709-
)
2710-
});
2711-
args.tokens = TokenStream::new(tokens);
2712-
attrs.push((Cow::Owned(attr), import_parent));
2713-
}
2714-
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
2715-
attrs.push((Cow::Owned(attr), import_parent));
2716-
}
2717+
if let [ident] = &*normal.item.path.segments {
2718+
let ident = ident.ident.name;
2719+
if ident == sym::doc {
2720+
filter_doc_attr(normal, is_inline);
2721+
attrs.push((Cow::Owned(attr), import_parent));
2722+
} else if ident != sym::cfg {
2723+
// If it's not a `cfg()` attribute, we keep it.
2724+
attrs.push((Cow::Owned(attr), import_parent));
27172725
}
27182726
}
27192727
}

src/librustdoc/html/markdown.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
20132013
map.insert("themeStyle".into(), 1);
20142014
map.insert("settings-menu".into(), 1);
20152015
map.insert("help-button".into(), 1);
2016+
map.insert("sidebar-button".into(), 1);
20162017
map.insert("main-content".into(), 1);
20172018
map.insert("toggle-all-docs".into(), 1);
20182019
map.insert("all-types".into(), 1);

src/librustdoc/html/render/print_item.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use clean::AttributesExt;
2-
31
use rustc_data_structures::captures::Captures;
42
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
53
use rustc_hir as hir;
@@ -465,16 +463,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
465463

466464
clean::ImportItem(ref import) => {
467465
let stab_tags = if let Some(import_def_id) = import.source.did {
468-
let ast_attrs = tcx.get_attrs_unchecked(import_def_id);
469-
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
470-
471466
// Just need an item with the correct def_id and attrs
472-
let import_item = clean::Item {
473-
item_id: import_def_id.into(),
474-
attrs: import_attrs,
475-
cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg),
476-
..myitem.clone()
477-
};
467+
let import_item =
468+
clean::Item { item_id: import_def_id.into(), ..myitem.clone() };
478469

479470
let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string());
480471
stab_tags

src/librustdoc/html/static/css/noscript.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ rules.
99
margin-left: 0 !important;
1010
}
1111

12-
#copy-path {
12+
#copy-path, #sidebar-button, .sidebar-resizer {
1313
/* It requires JS to work so no need to display it in this case. */
1414
display: none;
1515
}
@@ -132,6 +132,8 @@ nav.sub {
132132
--scrape-example-help-hover-color: #000;
133133
--scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1);
134134
--scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0);
135+
--sidebar-resizer-hover: hsl(207, 90%, 66%);
136+
--sidebar-resizer-active: hsl(207, 90%, 54%);
135137
}
136138
/* End theme: light */
137139

@@ -238,6 +240,8 @@ nav.sub {
238240
--scrape-example-help-hover-color: #fff;
239241
--scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1);
240242
--scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0);
243+
--sidebar-resizer-hover: hsl(207, 30%, 54%);
244+
--sidebar-resizer-active: hsl(207, 90%, 54%);
241245
}
242246
/* End theme: dark */
243247
}

0 commit comments

Comments
 (0)