Skip to content

Commit

Permalink
Auto merge of rust-lang#95889 - Dylan-DPC:rollup-1cmywu4, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - rust-lang#95566 (Avoid duplication of doc comments in `std::char` constants and functions)
 - rust-lang#95784 (Suggest replacing `typeof(...)` with an actual type)
 - rust-lang#95807 (Suggest adding a local for vector to fix borrowck errors)
 - rust-lang#95849 (Check for git submodules in non-git source tree.)
 - rust-lang#95852 (Fix missing space in lossy provenance cast lint)
 - rust-lang#95857 (Allow multiple derefs to be splitted in deref_separator)
 - rust-lang#95868 (rustdoc: Reduce allocations in a `html::markdown` function)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 10, 2022
2 parents 027a232 + fcfecab commit 1f7fb64
Show file tree
Hide file tree
Showing 22 changed files with 333 additions and 235 deletions.
40 changes: 31 additions & 9 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -785,13 +785,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
issued_borrow: &BorrowData<'tcx>,
explanation: BorrowExplanation,
) {
let used_in_call =
matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _));
let used_in_call = matches!(
explanation,
BorrowExplanation::UsedLater(LaterUseKind::Call | LaterUseKind::Other, _call_span, _)
);
if !used_in_call {
debug!("not later used in call");
return;
}

let use_span =
if let BorrowExplanation::UsedLater(LaterUseKind::Other, use_span, _) = explanation {
Some(use_span)
} else {
None
};

let outer_call_loc =
if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location {
loc
Expand Down Expand Up @@ -835,7 +844,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc);

let inner_call_span = inner_call_term.source_info.span;
let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span;
let outer_call_span = match use_span {
Some(span) => span,
None => outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span,
};
if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) {
// FIXME: This stops the suggestion in some cases where it should be emitted.
// Fix the spans for those cases so it's emitted correctly.
Expand All @@ -845,8 +857,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
return;
}
err.span_help(inner_call_span, "try adding a local storing this argument...");
err.span_help(outer_call_span, "...and then using that local as the argument to this call");
err.span_help(
inner_call_span,
&format!(
"try adding a local storing this{}...",
if use_span.is_some() { "" } else { " argument" }
),
);
err.span_help(
outer_call_span,
&format!(
"...and then using that local {}",
if use_span.is_some() { "here" } else { "as the argument to this call" }
),
);
}

fn suggest_split_at_mut_if_applicable(
Expand Down Expand Up @@ -1912,10 +1936,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
"cannot assign twice to immutable variable"
};
if span != assigned_span {
if !from_arg {
err.span_label(assigned_span, format!("first assignment to {}", place_description));
}
if span != assigned_span && !from_arg {
err.span_label(assigned_span, format!("first assignment to {}", place_description));
}
if let Some(decl) = local_decl
&& let Some(name) = local_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ typeck-functional-record-update-on-non-struct =
typeck-typeof-reserved-keyword-used =
`typeof` is a reserved keyword but unimplemented
.suggestion = consider replacing `typeof(...)` with an actual type
.label = reserved keyword
typeck-return-stmt-outside-of-fn-body =
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_mir_transform/src/deref_separator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
for (i, stmt) in data.statements.iter_mut().enumerate() {
match stmt.kind {
StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => {
let mut place_local = place.local;
let mut last_len = 0;
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
if p_elem == ProjectionElem::Deref && !p_ref.projection.is_empty() {
// The type that we are derefing.
Expand All @@ -23,15 +25,18 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
patch.add_statement(loc, StatementKind::StorageLive(temp));

// We are adding current p_ref's projections to our
// temp value.
let deref_place =
Place::from(p_ref.local).project_deeper(p_ref.projection, tcx);
// temp value, excluding projections we already covered.
let deref_place = Place::from(place_local)
.project_deeper(&p_ref.projection[last_len..], tcx);
patch.add_assign(
loc,
Place::from(temp),
Rvalue::Use(Operand::Move(deref_place)),
);

place_local = temp;
last_len = p_ref.projection.len();

// We are creating a place by using our temp value's location
// and copying derefed values which we need to create new statement.
let temp_place =
Expand All @@ -50,11 +55,6 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Since our job with the temp is done it should be gone
let loc = Location { block: block, statement_index: i + 1 };
patch.add_statement(loc, StatementKind::StorageDead(temp));

// As all projections are off the base projection, if there are
// multiple derefs in the middle of projection, it might cause
// unsoundness, to not let that happen we break the loop.
break;
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2460,8 +2460,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.normalize_ty(ast_ty.span, array_ty)
}
hir::TyKind::Typeof(ref e) => {
tcx.sess.emit_err(TypeofReservedKeywordUsed { span: ast_ty.span });
tcx.type_of(tcx.hir().local_def_id(e.hir_id))
let ty = tcx.type_of(tcx.hir().local_def_id(e.hir_id));
let span = ast_ty.span;
tcx.sess.emit_err(TypeofReservedKeywordUsed {
span,
ty,
opt_sugg: Some((span, Applicability::MachineApplicable))
.filter(|_| ty.is_suggestable()),
});

ty
}
hir::TyKind::Infer => {
// Infer also appears as the type of arguments or return
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.help(msg);
}
err.help(
"if you can't comply with strict provenance and need to expose the pointer\
"if you can't comply with strict provenance and need to expose the pointer \
provenance you can use `.expose_addr()` instead"
);

Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_typeck/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Errors emitted by typeck.
use rustc_errors::Applicability;
use rustc_macros::SessionDiagnostic;
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span, Symbol};

#[derive(SessionDiagnostic)]
Expand Down Expand Up @@ -127,10 +129,13 @@ pub struct FunctionalRecordUpdateOnNonStruct {

#[derive(SessionDiagnostic)]
#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
pub struct TypeofReservedKeywordUsed {
pub struct TypeofReservedKeywordUsed<'tcx> {
pub ty: Ty<'tcx>,
#[primary_span]
#[label]
pub span: Span,
#[suggestion_verbose(message = "suggestion", code = "{ty}")]
pub opt_sugg: Option<(Span, Applicability)>,
}

#[derive(SessionDiagnostic)]
Expand Down
139 changes: 7 additions & 132 deletions library/core/src/char/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,97 +6,22 @@ use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;

/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid [`char`]:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[doc(alias = "chr")]
/// Converts a `u32` to a `char`. See [`char::from_u32`].
#[must_use]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const fn from_u32(i: u32) -> Option<char> {
pub(super) const fn from_u32(i: u32) -> Option<char> {
// FIXME: once Result::ok is const fn, use it here
match char_try_from_u32(i) {
Ok(c) => Some(c),
Err(_) => None,
}
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
/// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`].
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
#[inline]
#[must_use]
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
// SAFETY: the caller must guarantee that `i` is a valid char value.
if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
}
Expand Down Expand Up @@ -317,60 +242,10 @@ impl fmt::Display for CharTryFromError {
}
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```should_panic
/// use std::char;
///
/// // this panics
/// let c = char::from_digit(1, 37);
/// ```
/// Converts a digit in the given radix to a `char`. See [`char::from_digit`].
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_char_convert", issue = "89259")]
pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
pub(super) const fn from_digit(num: u32, radix: u32) -> Option<char> {
if radix > 36 {
panic!("from_digit: radix is too high (maximum 36)");
}
Expand Down
49 changes: 2 additions & 47 deletions library/core/src/char/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,54 +30,9 @@ pub struct DecodeUtf16Error {
}

/// Creates an iterator over the UTF-16 encoded code points in `iter`,
/// returning unpaired surrogates as `Err`s.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char::decode_utf16;
///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
/// decode_utf16(v.iter().cloned())
/// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
/// .collect::<Vec<_>>(),
/// vec![
/// Ok('𝄞'),
/// Ok('m'), Ok('u'), Ok('s'),
/// Err(0xDD1E),
/// Ok('i'), Ok('c'),
/// Err(0xD834)
/// ]
/// );
/// ```
///
/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
///
/// ```
/// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
/// decode_utf16(v.iter().cloned())
/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
/// .collect::<String>(),
/// "𝄞mus�ic�"
/// );
/// ```
#[stable(feature = "decode_utf16", since = "1.9.0")]
/// returning unpaired surrogates as `Err`s. See [`char::decode_utf16`].
#[inline]
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
pub(super) fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
DecodeUtf16 { iter: iter.into_iter(), buf: None }
}

Expand Down
Loading

0 comments on commit 1f7fb64

Please sign in to comment.