Skip to content

Commit e1d1848

Browse files
committed
Auto merge of rust-lang#98904 - matthiaskrgr:rollup-05owsx7, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#98738 (Clarify MIR semantics of checked binary operations) - rust-lang#98782 (Improve spans for specialization error) - rust-lang#98793 (Lint against executable files in the root directory) - rust-lang#98814 (rustdoc: Censor certain complex unevaluated const exprs) - rust-lang#98878 (add more `rustc_pass_by_value`) - rust-lang#98879 (Fix "wrap closure in parenthesis" suggestion for `async` closure) - rust-lang#98886 (incr.comp.: Make split-dwarf commandline options [TRACKED].) - rust-lang#98898 (Add "no-div-regex" eslint rule) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 27eb6d7 + 08d558d commit e1d1848

27 files changed

+426
-63
lines changed

compiler/rustc_borrowck/src/constraint_generation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
149149
fn visit_ascribe_user_ty(
150150
&mut self,
151151
_place: &Place<'tcx>,
152-
_variance: &ty::Variance,
152+
_variance: ty::Variance,
153153
_user_ty: &UserTypeProjection,
154154
_location: Location,
155155
) {

compiler/rustc_middle/src/mir/syntax.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ pub enum StatementKind<'tcx> {
311311

312312
/// Describes what kind of retag is to be performed.
313313
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
314+
#[rustc_pass_by_value]
314315
pub enum RetagKind {
315316
/// The initial retag when entering a function.
316317
FnEntry,
@@ -990,11 +991,19 @@ pub enum Rvalue<'tcx> {
990991
/// matching types and return a value of that type.
991992
BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
992993

993-
/// Same as `BinaryOp`, but yields `(T, bool)` instead of `T`. In addition to performing the
994-
/// same computation as the matching `BinaryOp`, checks if the infinite precison result would be
995-
/// unequal to the actual result and sets the `bool` if this is the case.
994+
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
996995
///
997-
/// This only supports addition, subtraction, multiplication, and shift operations on integers.
996+
/// When overflow checking is disabled, the error condition is false. Otherwise, the error
997+
/// condition is determined as described below.
998+
///
999+
/// For addition, subtraction, and multiplication on integers the error condition is set when
1000+
/// the infinite precision result would be unequal to the actual result.
1001+
///
1002+
/// For shift operations on integers the error condition is set when the value of right-hand
1003+
/// side is greater than or equal to the number of bits in the type of the left-hand side, or
1004+
/// when the value of right-hand side is negative.
1005+
///
1006+
/// Other combinations of types and operators are unsupported.
9981007
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
9991008

10001009
/// Computes a value as described by the operation.

compiler/rustc_middle/src/mir/visit.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ macro_rules! make_mir_visitor {
147147
fn visit_ascribe_user_ty(
148148
&mut self,
149149
place: & $($mutability)? Place<'tcx>,
150-
variance: & $($mutability)? ty::Variance,
150+
variance: $(& $mutability)? ty::Variance,
151151
user_ty: & $($mutability)? UserTypeProjection,
152152
location: Location,
153153
) {
@@ -164,7 +164,7 @@ macro_rules! make_mir_visitor {
164164

165165
fn visit_retag(
166166
&mut self,
167-
kind: & $($mutability)? RetagKind,
167+
kind: $(& $mutability)? RetagKind,
168168
place: & $($mutability)? Place<'tcx>,
169169
location: Location,
170170
) {
@@ -425,7 +425,7 @@ macro_rules! make_mir_visitor {
425425
self.visit_source_info(source_info);
426426
match kind {
427427
StatementKind::Assign(
428-
box(ref $($mutability)? place, ref $($mutability)? rvalue)
428+
box (place, rvalue)
429429
) => {
430430
self.visit_assign(place, rvalue, location);
431431
}
@@ -465,13 +465,13 @@ macro_rules! make_mir_visitor {
465465
);
466466
}
467467
StatementKind::Retag(kind, place) => {
468-
self.visit_retag(kind, place, location);
468+
self.visit_retag($(& $mutability)? *kind, place, location);
469469
}
470470
StatementKind::AscribeUserType(
471-
box(ref $($mutability)? place, ref $($mutability)? user_ty),
471+
box (place, user_ty),
472472
variance
473473
) => {
474-
self.visit_ascribe_user_ty(place, variance, user_ty, location);
474+
self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location);
475475
}
476476
StatementKind::Coverage(coverage) => {
477477
self.visit_coverage(
@@ -480,9 +480,9 @@ macro_rules! make_mir_visitor {
480480
)
481481
}
482482
StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{
483-
ref $($mutability)? src,
484-
ref $($mutability)? dst,
485-
ref $($mutability)? count,
483+
src,
484+
dst,
485+
count,
486486
}) => {
487487
self.visit_operand(src, location);
488488
self.visit_operand(dst, location);
@@ -517,8 +517,7 @@ macro_rules! make_mir_visitor {
517517
TerminatorKind::GeneratorDrop |
518518
TerminatorKind::Unreachable |
519519
TerminatorKind::FalseEdge { .. } |
520-
TerminatorKind::FalseUnwind { .. } => {
521-
}
520+
TerminatorKind::FalseUnwind { .. } => {}
522521

523522
TerminatorKind::Return => {
524523
// `return` logically moves from the return place `_0`. Note that the place
@@ -830,7 +829,7 @@ macro_rules! make_mir_visitor {
830829

831830
fn super_ascribe_user_ty(&mut self,
832831
place: & $($mutability)? Place<'tcx>,
833-
_variance: & $($mutability)? ty::Variance,
832+
_variance: $(& $mutability)? ty::Variance,
834833
user_ty: & $($mutability)? UserTypeProjection,
835834
location: Location) {
836835
self.visit_place(
@@ -847,7 +846,7 @@ macro_rules! make_mir_visitor {
847846
}
848847

849848
fn super_retag(&mut self,
850-
_kind: & $($mutability)? RetagKind,
849+
_kind: $(& $mutability)? RetagKind,
851850
place: & $($mutability)? Place<'tcx>,
852851
location: Location) {
853852
self.visit_place(

compiler/rustc_session/src/config.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2724,8 +2724,8 @@ pub(crate) mod dep_tracking {
27242724
use super::{
27252725
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType,
27262726
InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel,
2727-
OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
2728-
SymbolManglingVersion, TrimmedDefPaths,
2727+
OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind,
2728+
SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths,
27292729
};
27302730
use crate::lint;
27312731
use crate::options::WasiExecModel;
@@ -2812,6 +2812,7 @@ pub(crate) mod dep_tracking {
28122812
Edition,
28132813
LinkerPluginLto,
28142814
SplitDebuginfo,
2815+
SplitDwarfKind,
28152816
StackProtector,
28162817
SwitchWithOptPath,
28172818
SymbolManglingVersion,

compiler/rustc_session/src/options.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1496,15 +1496,15 @@ options! {
14961496
"control if mem::uninitialized and mem::zeroed panic on more UB"),
14971497
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
14981498
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
1499-
split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED],
1499+
split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED],
15001500
"split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
15011501
(default: `split`)
15021502
15031503
`split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
15041504
file which is ignored by the linker
15051505
`single`: sections which do not require relocation are written into object file but ignored
15061506
by the linker"),
1507-
split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED],
1507+
split_dwarf_inlining: bool = (true, parse_bool, [TRACKED],
15081508
"provide minimal debug info in the object/executable to facilitate online \
15091509
symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"),
15101510
symbol_mangling_version: Option<SymbolManglingVersion> = (None,

compiler/rustc_type_ir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ impl UnifyKey for FloatVid {
599599
}
600600

601601
#[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)]
602+
#[rustc_pass_by_value]
602603
pub enum Variance {
603604
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
604605
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell

compiler/rustc_typeck/src/check/callee.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
280280
callee_node: &hir::ExprKind<'_>,
281281
callee_span: Span,
282282
) {
283-
let hir_id = self.tcx.hir().get_parent_node(hir_id);
284-
let parent_node = self.tcx.hir().get(hir_id);
283+
let hir = self.tcx.hir();
284+
let parent_hir_id = hir.get_parent_node(hir_id);
285+
let parent_node = hir.get(parent_hir_id);
285286
if let (
286287
hir::Node::Expr(hir::Expr {
287-
kind: hir::ExprKind::Closure { fn_decl_span, .. }, ..
288+
kind: hir::ExprKind::Closure { fn_decl_span, body, .. },
289+
..
288290
}),
289291
hir::ExprKind::Block(..),
290292
) = (parent_node, callee_node)
291293
{
294+
let fn_decl_span = if hir.body(*body).generator_kind
295+
== Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
296+
{
297+
// Actually need to unwrap a few more layers of HIR to get to
298+
// the _real_ closure...
299+
let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
300+
if let hir::Node::Expr(hir::Expr {
301+
kind: hir::ExprKind::Closure { fn_decl_span, .. },
302+
..
303+
}) = hir.get(async_closure)
304+
{
305+
*fn_decl_span
306+
} else {
307+
return;
308+
}
309+
} else {
310+
*fn_decl_span
311+
};
312+
292313
let start = fn_decl_span.shrink_to_lo();
293314
let end = callee_span.shrink_to_hi();
294315
err.multipart_suggestion(

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,16 @@ fn check_predicates<'tcx>(
279279
span: Span,
280280
) {
281281
let tcx = infcx.tcx;
282-
let impl1_predicates: Vec<_> = traits::elaborate_predicates(
282+
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
283+
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
283284
tcx,
284-
tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(),
285+
std::iter::zip(
286+
instantiated.predicates,
287+
// Don't drop predicates (unsound!) because `spans` is too short
288+
instantiated.spans.into_iter().chain(std::iter::repeat(span)),
289+
),
285290
)
286-
.map(|obligation| obligation.predicate)
291+
.map(|obligation| (obligation.predicate, obligation.cause.span))
287292
.collect();
288293

289294
let mut impl2_predicates = if impl2_node.is_from_trait() {
@@ -321,7 +326,7 @@ fn check_predicates<'tcx>(
321326
// which is sound because we forbid impls like the following
322327
//
323328
// impl<D: Debug> AlwaysApplicable for D { }
324-
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| {
329+
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
325330
matches!(
326331
trait_predicate_kind(tcx, predicate),
327332
Some(TraitSpecializationKind::AlwaysApplicable)
@@ -345,11 +350,11 @@ fn check_predicates<'tcx>(
345350
}
346351
}
347352
impl2_predicates.extend(
348-
traits::elaborate_predicates(tcx, always_applicable_traits)
353+
traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
349354
.map(|obligation| obligation.predicate),
350355
);
351356

352-
for predicate in impl1_predicates {
357+
for (predicate, span) in impl1_predicates {
353358
if !impl2_predicates.contains(&predicate) {
354359
check_specialization_on(tcx, predicate, span)
355360
}
@@ -384,9 +389,17 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
384389
.emit();
385390
}
386391
}
392+
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
393+
tcx.sess
394+
.struct_span_err(
395+
span,
396+
&format!("cannot specialize on associated type `{projection_ty} == {term}`",),
397+
)
398+
.emit();
399+
}
387400
_ => {
388401
tcx.sess
389-
.struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
402+
.struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
390403
.emit();
391404
}
392405
}

src/librustdoc/clean/utils.rs

+87-6
Original file line numberDiff line numberDiff line change
@@ -340,17 +340,98 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
340340
false
341341
}
342342

343+
/// Build a textual representation of an unevaluated constant expression.
344+
///
345+
/// If the const expression is too complex, an underscore `_` is returned.
346+
/// For const arguments, it's `{ _ }` to be precise.
347+
/// This means that the output is not necessarily valid Rust code.
348+
///
349+
/// Currently, only
350+
///
351+
/// * literals (optionally with a leading `-`)
352+
/// * unit `()`
353+
/// * blocks (`{ … }`) around simple expressions and
354+
/// * paths without arguments
355+
///
356+
/// are considered simple enough. Simple blocks are included since they are
357+
/// necessary to disambiguate unit from the unit type.
358+
/// This list might get extended in the future.
359+
///
360+
/// Without this censoring, in a lot of cases the output would get too large
361+
/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs.
362+
/// Further, private and `doc(hidden)` fields of structs would get leaked
363+
/// since HIR datatypes like the `body` parameter do not contain enough
364+
/// semantic information for this function to be able to hide them –
365+
/// at least not without significant performance overhead.
366+
///
367+
/// Whenever possible, prefer to evaluate the constant first and try to
368+
/// use a different method for pretty-printing. Ideally this function
369+
/// should only ever be used as a fallback.
343370
pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
344371
let hir = tcx.hir();
345372
let value = &hir.body(body).value;
346373

347-
let snippet = if !value.span.from_expansion() {
348-
tcx.sess.source_map().span_to_snippet(value.span).ok()
349-
} else {
350-
None
351-
};
374+
#[derive(PartialEq, Eq)]
375+
enum Classification {
376+
Literal,
377+
Simple,
378+
Complex,
379+
}
352380

353-
snippet.unwrap_or_else(|| rustc_hir_pretty::id_to_string(&hir, body.hir_id))
381+
use Classification::*;
382+
383+
fn classify(expr: &hir::Expr<'_>) -> Classification {
384+
match &expr.kind {
385+
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
386+
if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex }
387+
}
388+
hir::ExprKind::Lit(_) => Literal,
389+
hir::ExprKind::Tup([]) => Simple,
390+
hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => {
391+
if classify(expr) == Complex { Complex } else { Simple }
392+
}
393+
// Paths with a self-type or arguments are too “complex” following our measure since
394+
// they may leak private fields of structs (with feature `adt_const_params`).
395+
// Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`.
396+
// Paths without arguments are definitely harmless though.
397+
hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => {
398+
if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex }
399+
}
400+
// FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty
401+
// contains const arguments. Is there a *concise* way to check for this?
402+
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple,
403+
// FIXME: Can they contain const arguments and thus leak private struct fields?
404+
hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple,
405+
_ => Complex,
406+
}
407+
}
408+
409+
let classification = classify(value);
410+
411+
if classification == Literal
412+
&& !value.span.from_expansion()
413+
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) {
414+
// For literals, we avoid invoking the pretty-printer and use the source snippet instead to
415+
// preserve certain stylistic choices the user likely made for the sake legibility like
416+
//
417+
// * hexadecimal notation
418+
// * underscores
419+
// * character escapes
420+
//
421+
// FIXME: This passes through `-/*spacer*/0` verbatim.
422+
snippet
423+
} else if classification == Simple {
424+
// Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
425+
// other formatting artifacts.
426+
rustc_hir_pretty::id_to_string(&hir, body.hir_id)
427+
} else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
428+
// FIXME: Omit the curly braces if the enclosing expression is an array literal
429+
// with a repeated element (an `ExprKind::Repeat`) as in such case it
430+
// would not actually need any disambiguation.
431+
"{ _ }".to_owned()
432+
} else {
433+
"_".to_owned()
434+
}
354435
}
355436

356437
/// Given a type Path, resolve it to a Type using the TyCtxt

src/librustdoc/html/render/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,14 @@ fn assoc_const(
716716
ty = ty.print(cx),
717717
);
718718
if let Some(default) = default {
719+
write!(w, " = ");
720+
719721
// FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
720722
// hood which adds noisy underscores and a type suffix to number literals.
721723
// This hurts readability in this context especially when more complex expressions
722724
// are involved and it doesn't add much of value.
723725
// Find a way to print constants here without all that jazz.
724-
write!(w, " = {}", default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx())));
726+
write!(w, "{}", Escape(&default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx()))));
725727
}
726728
}
727729

0 commit comments

Comments
 (0)