Skip to content

Commit 331249a

Browse files
committed
Auto merge of #112661 - matthiaskrgr:rollup-9u5i2zy, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #111212 (Add casting suggestion when assigning negative 2's complement bin or hex literal to a size compatible signed integer) - #112304 (Add chapter in rustdoc book for re-exports and add a regression test for `#[doc(hidden)]` behaviour) - #112486 (Fix suggestion for E0404 not dealing with multiple generics) - #112562 (rustdoc-gui: allow running on Windows) - #112621 (Mention `env!` in `option_env!`'s docs) - #112634 (add InlineConst check) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f9097f8 + c0a089e commit 331249a

File tree

20 files changed

+629
-49
lines changed

20 files changed

+629
-49
lines changed

compiler/rustc_ast_pretty/src/pprust/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
3232
State::new().bounds_to_string(bounds)
3333
}
3434

35+
pub fn where_bound_predicate_to_string(where_bound_predicate: &ast::WhereBoundPredicate) -> String {
36+
State::new().where_bound_predicate_to_string(where_bound_predicate)
37+
}
38+
3539
pub fn pat_to_string(pat: &ast::Pat) -> String {
3640
State::new().pat_to_string(pat)
3741
}

compiler/rustc_ast_pretty/src/pprust/state.rs

+7
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
824824
Self::to_string(|s| s.print_type_bounds(bounds))
825825
}
826826

827+
fn where_bound_predicate_to_string(
828+
&self,
829+
where_bound_predicate: &ast::WhereBoundPredicate,
830+
) -> String {
831+
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
832+
}
833+
827834
fn pat_to_string(&self, pat: &ast::Pat) -> String {
828835
Self::to_string(|s| s.print_pat(pat))
829836
}

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -623,19 +623,8 @@ impl<'a> State<'a> {
623623

624624
pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
625625
match predicate {
626-
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
627-
bound_generic_params,
628-
bounded_ty,
629-
bounds,
630-
..
631-
}) => {
632-
self.print_formal_generic_params(bound_generic_params);
633-
self.print_type(bounded_ty);
634-
self.word(":");
635-
if !bounds.is_empty() {
636-
self.nbsp();
637-
self.print_type_bounds(bounds);
638-
}
626+
ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
627+
self.print_where_bound_predicate(where_bound_predicate);
639628
}
640629
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
641630
lifetime,
@@ -658,6 +647,19 @@ impl<'a> State<'a> {
658647
}
659648
}
660649

650+
pub fn print_where_bound_predicate(
651+
&mut self,
652+
where_bound_predicate: &ast::WhereBoundPredicate,
653+
) {
654+
self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
655+
self.print_type(&where_bound_predicate.bounded_ty);
656+
self.word(":");
657+
if !where_bound_predicate.bounds.is_empty() {
658+
self.nbsp();
659+
self.print_type_bounds(&where_bound_predicate.bounds);
660+
}
661+
}
662+
661663
fn print_use_tree(&mut self, tree: &ast::UseTree) {
662664
match &tree.kind {
663665
ast::UseTreeKind::Simple(rename) => {

compiler/rustc_lint/messages.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ lint_overflowing_bin_hex = literal out of range for `{$ty}`
425425
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
426426
.positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
427427
.suggestion = consider using the type `{$suggestion_ty}` instead
428+
.sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`
428429
.help = consider using the type `{$suggestion_ty}` instead
429430
430431
lint_overflowing_int = literal out of range for `{$ty}`

compiler/rustc_lint/src/lints.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,8 @@ pub struct OverflowingBinHex<'a> {
13421342
pub sign: OverflowingBinHexSign,
13431343
#[subdiagnostic]
13441344
pub sub: Option<OverflowingBinHexSub<'a>>,
1345+
#[subdiagnostic]
1346+
pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
13451347
}
13461348

13471349
pub enum OverflowingBinHexSign {
@@ -1386,6 +1388,21 @@ pub enum OverflowingBinHexSub<'a> {
13861388
Help { suggestion_ty: &'a str },
13871389
}
13881390

1391+
#[derive(Subdiagnostic)]
1392+
#[suggestion(
1393+
lint_sign_bit_suggestion,
1394+
code = "{lit_no_suffix}{uint_ty} as {int_ty}",
1395+
applicability = "maybe-incorrect"
1396+
)]
1397+
pub struct OverflowingBinHexSignBitSub<'a> {
1398+
#[primary_span]
1399+
pub span: Span,
1400+
pub lit_no_suffix: &'a str,
1401+
pub negative_val: String,
1402+
pub uint_ty: &'a str,
1403+
pub int_ty: &'a str,
1404+
}
1405+
13891406
#[derive(LintDiagnostic)]
13901407
#[diag(lint_overflowing_int)]
13911408
#[note]

compiler/rustc_lint/src/types.rs

+45-4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use crate::{
33
lints::{
44
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
55
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
6-
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
7-
OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
8-
RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
6+
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
7+
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
8+
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
9+
VariantSizeDifferencesDiag,
910
},
1011
};
1112
use crate::{LateContext, LateLintPass, LintContext};
@@ -297,10 +298,50 @@ fn report_bin_hex_error(
297298
}
298299
},
299300
);
301+
let sign_bit_sub = (!negative)
302+
.then(|| {
303+
let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
304+
return None;
305+
};
306+
307+
let Some(bit_width) = int_ty.bit_width() else {
308+
return None; // isize case
309+
};
310+
311+
// Skip if sign bit is not set
312+
if (val & (1 << (bit_width - 1))) == 0 {
313+
return None;
314+
}
315+
316+
let lit_no_suffix =
317+
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
318+
repr_str.split_at(pos).0
319+
} else {
320+
&repr_str
321+
};
322+
323+
Some(OverflowingBinHexSignBitSub {
324+
span: expr.span,
325+
lit_no_suffix,
326+
negative_val: actually.clone(),
327+
int_ty: int_ty.name_str(),
328+
uint_ty: int_ty.to_unsigned().name_str(),
329+
})
330+
})
331+
.flatten();
332+
300333
cx.emit_spanned_lint(
301334
OVERFLOWING_LITERALS,
302335
expr.span,
303-
OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub },
336+
OverflowingBinHex {
337+
ty: t,
338+
lit: repr_str.clone(),
339+
dec: val,
340+
actually,
341+
sign,
342+
sub,
343+
sign_bit_sub,
344+
},
304345
)
305346
}
306347

compiler/rustc_middle/src/mir/interpret/queries.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ impl<'tcx> TyCtxt<'tcx> {
9595
// used generic parameters is a bug of evaluation, so checking for it
9696
// here does feel somewhat sensible.
9797
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
98-
assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
98+
assert!(matches!(
99+
self.def_kind(ct.def),
100+
DefKind::InlineConst | DefKind::AnonConst
101+
));
99102
let mir_body = self.mir_for_ctfe(ct.def);
100103
if mir_body.is_polymorphic {
101104
let Some(local_def_id) = ct.def.as_local() else { return };

compiler/rustc_resolve/src/late/diagnostics.rs

+69-23
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_ast::{
1010
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
1111
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
1212
};
13-
use rustc_ast_pretty::pprust::path_segment_to_string;
13+
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
1414
use rustc_data_structures::fx::FxHashSet;
1515
use rustc_errors::{
1616
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -1050,7 +1050,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
10501050
};
10511051

10521052
// Confirm that the target is an associated type.
1053-
let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
1053+
let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
10541054
// use this to verify that ident is a type param.
10551055
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
10561056
return false;
@@ -1079,37 +1079,19 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
10791079
return false;
10801080
}
10811081
if let (
1082-
[ast::PathSegment { ident: constrain_ident, args: None, .. }],
1082+
[ast::PathSegment { args: None, .. }],
10831083
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
10841084
) = (&type_param_path.segments[..], &bounds[..])
10851085
{
10861086
if let [ast::PathSegment { ident, args: None, .. }] =
10871087
&poly_trait_ref.trait_ref.path.segments[..]
10881088
{
10891089
if ident.span == span {
1090+
let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
10901091
err.span_suggestion_verbose(
10911092
*where_span,
10921093
format!("constrain the associated type to `{}`", ident),
1093-
format!(
1094-
"{}: {}<{} = {}>",
1095-
self.r
1096-
.tcx
1097-
.sess
1098-
.source_map()
1099-
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
1100-
.unwrap_or_else(|_| constrain_ident.to_string()),
1101-
path.segments[..position]
1102-
.iter()
1103-
.map(|segment| path_segment_to_string(segment))
1104-
.collect::<Vec<_>>()
1105-
.join("::"),
1106-
path.segments[position..]
1107-
.iter()
1108-
.map(|segment| path_segment_to_string(segment))
1109-
.collect::<Vec<_>>()
1110-
.join("::"),
1111-
ident,
1112-
),
1094+
where_bound_predicate_to_string(&new_where_bound_predicate),
11131095
Applicability::MaybeIncorrect,
11141096
);
11151097
}
@@ -2605,6 +2587,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
26052587
}
26062588
}
26072589

2590+
fn mk_where_bound_predicate(
2591+
path: &Path,
2592+
poly_trait_ref: &ast::PolyTraitRef,
2593+
ty: &ast::Ty,
2594+
) -> Option<ast::WhereBoundPredicate> {
2595+
use rustc_span::DUMMY_SP;
2596+
let modified_segments = {
2597+
let mut segments = path.segments.clone();
2598+
let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
2599+
let mut segments = ThinVec::from(preceding);
2600+
2601+
let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
2602+
id: DUMMY_NODE_ID,
2603+
ident: last.ident,
2604+
gen_args: None,
2605+
kind: ast::AssocConstraintKind::Equality {
2606+
term: ast::Term::Ty(ast::ptr::P(ast::Ty {
2607+
kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
2608+
id: DUMMY_NODE_ID,
2609+
span: DUMMY_SP,
2610+
tokens: None,
2611+
})),
2612+
},
2613+
span: DUMMY_SP,
2614+
});
2615+
2616+
match second_last.args.as_deref_mut() {
2617+
Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
2618+
args.push(added_constraint);
2619+
}
2620+
Some(_) => return None,
2621+
None => {
2622+
second_last.args =
2623+
Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
2624+
args: ThinVec::from([added_constraint]),
2625+
span: DUMMY_SP,
2626+
})));
2627+
}
2628+
}
2629+
2630+
segments.push(second_last.clone());
2631+
segments
2632+
};
2633+
2634+
let new_where_bound_predicate = ast::WhereBoundPredicate {
2635+
span: DUMMY_SP,
2636+
bound_generic_params: ThinVec::new(),
2637+
bounded_ty: ast::ptr::P(ty.clone()),
2638+
bounds: vec![ast::GenericBound::Trait(
2639+
ast::PolyTraitRef {
2640+
bound_generic_params: ThinVec::new(),
2641+
trait_ref: ast::TraitRef {
2642+
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
2643+
ref_id: DUMMY_NODE_ID,
2644+
},
2645+
span: DUMMY_SP,
2646+
},
2647+
ast::TraitBoundModifier::None,
2648+
)],
2649+
};
2650+
2651+
Some(new_where_bound_predicate)
2652+
}
2653+
26082654
/// Report lifetime/lifetime shadowing as an error.
26092655
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
26102656
let mut err = struct_span_err!(

config.example.toml

+7
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ changelog-seen = 2
250250
# target when running tests, otherwise this can be omitted.
251251
#nodejs = "node"
252252

253+
# The npm executable to use. Note that this is used for rustdoc-gui tests,
254+
# otherwise this can be omitted.
255+
#
256+
# Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or
257+
# error will be emitted.
258+
#npm = "npm"
259+
253260
# Python interpreter to use for various tasks throughout the build, notably
254261
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
255262
#

library/core/src/macros/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,8 @@ pub(crate) mod builtin {
960960
///
961961
/// A compile time error is never emitted when using this macro regardless
962962
/// of whether the environment variable is present or not.
963+
/// To emit a compile error if the environment variable is not present,
964+
/// use the [`env!`] macro instead.
963965
///
964966
/// # Examples
965967
///

src/doc/rustdoc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [How to write documentation](how-to-write-documentation.md)
88
- [What to include (and exclude)](write-documentation/what-to-include.md)
99
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
10+
- [Re-exports](write-documentation/re-exports.md)
1011
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
1112
- [Documentation tests](write-documentation/documentation-tests.md)
1213
- [Rustdoc-specific lints](lints.md)

0 commit comments

Comments
 (0)