Skip to content

Commit

Permalink
Auto merge of #112661 - matthiaskrgr:rollup-9u5i2zy, r=matthiaskrgr
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jun 15, 2023
2 parents f9097f8 + c0a089e commit 331249a
Show file tree
Hide file tree
Showing 20 changed files with 629 additions and 49 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
State::new().bounds_to_string(bounds)
}

pub fn where_bound_predicate_to_string(where_bound_predicate: &ast::WhereBoundPredicate) -> String {
State::new().where_bound_predicate_to_string(where_bound_predicate)
}

pub fn pat_to_string(pat: &ast::Pat) -> String {
State::new().pat_to_string(pat)
}
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
Self::to_string(|s| s.print_type_bounds(bounds))
}

fn where_bound_predicate_to_string(
&self,
where_bound_predicate: &ast::WhereBoundPredicate,
) -> String {
Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
}

fn pat_to_string(&self, pat: &ast::Pat) -> String {
Self::to_string(|s| s.print_pat(pat))
}
Expand Down
28 changes: 15 additions & 13 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,19 +623,8 @@ impl<'a> State<'a> {

pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
match predicate {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
bound_generic_params,
bounded_ty,
bounds,
..
}) => {
self.print_formal_generic_params(bound_generic_params);
self.print_type(bounded_ty);
self.word(":");
if !bounds.is_empty() {
self.nbsp();
self.print_type_bounds(bounds);
}
ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
self.print_where_bound_predicate(where_bound_predicate);
}
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
lifetime,
Expand All @@ -658,6 +647,19 @@ impl<'a> State<'a> {
}
}

pub fn print_where_bound_predicate(
&mut self,
where_bound_predicate: &ast::WhereBoundPredicate,
) {
self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
self.print_type(&where_bound_predicate.bounded_ty);
self.word(":");
if !where_bound_predicate.bounds.is_empty() {
self.nbsp();
self.print_type_bounds(&where_bound_predicate.bounds);
}
}

fn print_use_tree(&mut self, tree: &ast::UseTree) {
match &tree.kind {
ast::UseTreeKind::Simple(rename) => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ lint_overflowing_bin_hex = literal out of range for `{$ty}`
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
.positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
.suggestion = consider using the type `{$suggestion_ty}` instead
.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}`
.help = consider using the type `{$suggestion_ty}` instead
lint_overflowing_int = literal out of range for `{$ty}`
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,8 @@ pub struct OverflowingBinHex<'a> {
pub sign: OverflowingBinHexSign,
#[subdiagnostic]
pub sub: Option<OverflowingBinHexSub<'a>>,
#[subdiagnostic]
pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
}

pub enum OverflowingBinHexSign {
Expand Down Expand Up @@ -1386,6 +1388,21 @@ pub enum OverflowingBinHexSub<'a> {
Help { suggestion_ty: &'a str },
}

#[derive(Subdiagnostic)]
#[suggestion(
lint_sign_bit_suggestion,
code = "{lit_no_suffix}{uint_ty} as {int_ty}",
applicability = "maybe-incorrect"
)]
pub struct OverflowingBinHexSignBitSub<'a> {
#[primary_span]
pub span: Span,
pub lit_no_suffix: &'a str,
pub negative_val: String,
pub uint_ty: &'a str,
pub int_ty: &'a str,
}

#[derive(LintDiagnostic)]
#[diag(lint_overflowing_int)]
#[note]
Expand Down
49 changes: 45 additions & 4 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use crate::{
lints::{
AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
VariantSizeDifferencesDiag,
},
};
use crate::{LateContext, LateLintPass, LintContext};
Expand Down Expand Up @@ -297,10 +298,50 @@ fn report_bin_hex_error(
}
},
);
let sign_bit_sub = (!negative)
.then(|| {
let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
return None;
};

let Some(bit_width) = int_ty.bit_width() else {
return None; // isize case
};

// Skip if sign bit is not set
if (val & (1 << (bit_width - 1))) == 0 {
return None;
}

let lit_no_suffix =
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
repr_str.split_at(pos).0
} else {
&repr_str
};

Some(OverflowingBinHexSignBitSub {
span: expr.span,
lit_no_suffix,
negative_val: actually.clone(),
int_ty: int_ty.name_str(),
uint_ty: int_ty.to_unsigned().name_str(),
})
})
.flatten();

cx.emit_spanned_lint(
OVERFLOWING_LITERALS,
expr.span,
OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub },
OverflowingBinHex {
ty: t,
lit: repr_str.clone(),
dec: val,
actually,
sign,
sub,
sign_bit_sub,
},
)
}

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ impl<'tcx> TyCtxt<'tcx> {
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
assert!(matches!(
self.def_kind(ct.def),
DefKind::InlineConst | DefKind::AnonConst
));
let mir_body = self.mir_for_ctfe(ct.def);
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.def.as_local() else { return };
Expand Down
92 changes: 69 additions & 23 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
Expand Down Expand Up @@ -1050,7 +1050,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
};

// Confirm that the target is an associated type.
let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
Expand Down Expand Up @@ -1079,37 +1079,19 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
return false;
}
if let (
[ast::PathSegment { ident: constrain_ident, args: None, .. }],
[ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
) = (&type_param_path.segments[..], &bounds[..])
{
if let [ast::PathSegment { ident, args: None, .. }] =
&poly_trait_ref.trait_ref.path.segments[..]
{
if ident.span == span {
let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
err.span_suggestion_verbose(
*where_span,
format!("constrain the associated type to `{}`", ident),
format!(
"{}: {}<{} = {}>",
self.r
.tcx
.sess
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
path.segments[..position]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
path.segments[position..]
.iter()
.map(|segment| path_segment_to_string(segment))
.collect::<Vec<_>>()
.join("::"),
ident,
),
where_bound_predicate_to_string(&new_where_bound_predicate),
Applicability::MaybeIncorrect,
);
}
Expand Down Expand Up @@ -2605,6 +2587,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}

fn mk_where_bound_predicate(
path: &Path,
poly_trait_ref: &ast::PolyTraitRef,
ty: &ast::Ty,
) -> Option<ast::WhereBoundPredicate> {
use rustc_span::DUMMY_SP;
let modified_segments = {
let mut segments = path.segments.clone();
let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
let mut segments = ThinVec::from(preceding);

let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
id: DUMMY_NODE_ID,
ident: last.ident,
gen_args: None,
kind: ast::AssocConstraintKind::Equality {
term: ast::Term::Ty(ast::ptr::P(ast::Ty {
kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
id: DUMMY_NODE_ID,
span: DUMMY_SP,
tokens: None,
})),
},
span: DUMMY_SP,
});

match second_last.args.as_deref_mut() {
Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
args.push(added_constraint);
}
Some(_) => return None,
None => {
second_last.args =
Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
args: ThinVec::from([added_constraint]),
span: DUMMY_SP,
})));
}
}

segments.push(second_last.clone());
segments
};

let new_where_bound_predicate = ast::WhereBoundPredicate {
span: DUMMY_SP,
bound_generic_params: ThinVec::new(),
bounded_ty: ast::ptr::P(ty.clone()),
bounds: vec![ast::GenericBound::Trait(
ast::PolyTraitRef {
bound_generic_params: ThinVec::new(),
trait_ref: ast::TraitRef {
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
ref_id: DUMMY_NODE_ID,
},
span: DUMMY_SP,
},
ast::TraitBoundModifier::None,
)],
};

Some(new_where_bound_predicate)
}

/// Report lifetime/lifetime shadowing as an error.
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = struct_span_err!(
Expand Down
7 changes: 7 additions & 0 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ changelog-seen = 2
# target when running tests, otherwise this can be omitted.
#nodejs = "node"

# The npm executable to use. Note that this is used for rustdoc-gui tests,
# otherwise this can be omitted.
#
# Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or
# error will be emitted.
#npm = "npm"

# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
#
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,8 @@ pub(crate) mod builtin {
///
/// A compile time error is never emitted when using this macro regardless
/// of whether the environment variable is present or not.
/// To emit a compile error if the environment variable is not present,
/// use the [`env!`] macro instead.
///
/// # Examples
///
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustdoc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](write-documentation/what-to-include.md)
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
- [Re-exports](write-documentation/re-exports.md)
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
- [Documentation tests](write-documentation/documentation-tests.md)
- [Rustdoc-specific lints](lints.md)
Expand Down
Loading

0 comments on commit 331249a

Please sign in to comment.