Skip to content

Commit 289b2b8

Browse files
committed
Auto merge of rust-lang#103398 - Dylan-DPC:rollup-cj6w00o, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#102602 (Slightly tweak comments wrt `lint_overflowing_range_endpoint`) - rust-lang#103190 (rustdoc: render bounds of cross-crate GAT params) - rust-lang#103224 (Allow semicolon after closure within parentheses in macros) - rust-lang#103280 ((rust-lang#102929) Implement `String::leak` (attempt 2)) - rust-lang#103329 (Add a forgotten check for NonNull::new_unchecked's precondition) - rust-lang#103346 (Adjust argument type for mutable with_metadata_of (rust-lang#75091)) - rust-lang#103360 (Reduce false positives in msys2 detection) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents f8c86c8 + b453694 commit 289b2b8

17 files changed

+153
-67
lines changed

compiler/rustc_lint/src/types.rs

+40-38
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ impl TypeLimits {
116116
}
117117
}
118118

119-
/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint.
120-
/// Returns `true` iff the lint was overridden.
119+
/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
120+
/// Returns `true` iff the lint was emitted.
121121
fn lint_overflowing_range_endpoint<'tcx>(
122122
cx: &LateContext<'tcx>,
123123
lit: &hir::Lit,
@@ -140,44 +140,46 @@ fn lint_overflowing_range_endpoint<'tcx>(
140140
return false;
141141
}
142142

143-
let mut overwritten = false;
144143
// We can suggest using an inclusive range
145144
// (`..=`) instead only if it is the `end` that is
146145
// overflowing and only by 1.
147-
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max
148-
&& let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span)
149-
{
150-
cx.struct_span_lint(
151-
OVERFLOWING_LITERALS,
152-
struct_expr.span,
153-
fluent::lint::range_endpoint_out_of_range,
154-
|lint| {
155-
use ast::{LitIntType, LitKind};
156-
157-
lint.set_arg("ty", ty);
158-
159-
// We need to preserve the literal's suffix,
160-
// as it may determine typing information.
161-
let suffix = match lit.node {
162-
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
163-
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
164-
LitKind::Int(_, LitIntType::Unsuffixed) => "",
165-
_ => bug!(),
166-
};
167-
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
168-
lint.span_suggestion(
169-
struct_expr.span,
170-
fluent::lint::suggestion,
171-
suggestion,
172-
Applicability::MachineApplicable,
173-
);
174-
overwritten = true;
146+
if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) {
147+
return false;
148+
};
149+
let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
175150

176-
lint
177-
},
178-
);
179-
}
180-
overwritten
151+
cx.struct_span_lint(
152+
OVERFLOWING_LITERALS,
153+
struct_expr.span,
154+
fluent::lint::range_endpoint_out_of_range,
155+
|lint| {
156+
use ast::{LitIntType, LitKind};
157+
158+
lint.set_arg("ty", ty);
159+
160+
// We need to preserve the literal's suffix,
161+
// as it may determine typing information.
162+
let suffix = match lit.node {
163+
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
164+
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
165+
LitKind::Int(_, LitIntType::Unsuffixed) => "",
166+
_ => bug!(),
167+
};
168+
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
169+
lint.span_suggestion(
170+
struct_expr.span,
171+
fluent::lint::suggestion,
172+
suggestion,
173+
Applicability::MachineApplicable,
174+
);
175+
176+
lint
177+
},
178+
);
179+
180+
// We've just emitted a lint, special cased for `(...)..MAX+1` ranges,
181+
// return `true` so the callers don't also emit a lint
182+
true
181183
}
182184

183185
// For `isize` & `usize`, be conservative with the warnings, so that the
@@ -358,7 +360,7 @@ fn lint_int_literal<'tcx>(
358360
}
359361

360362
if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
361-
// The overflowing literal lint was overridden.
363+
// The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
362364
return;
363365
}
364366

@@ -427,7 +429,7 @@ fn lint_uint_literal<'tcx>(
427429
}
428430
}
429431
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
430-
// The overflowing literal lint was overridden.
432+
// The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
431433
return;
432434
}
433435
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {

compiler/rustc_parse/src/parser/expr.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,10 @@ impl<'a> Parser<'a> {
20512051

20522052
if self.token.kind == TokenKind::Semi
20532053
&& matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
2054+
// HACK: This is needed so we can detect whether we're inside a macro,
2055+
// where regular assumptions about what tokens can follow other tokens
2056+
// don't necessarily apply.
2057+
&& self.subparser_name.is_none()
20542058
{
20552059
// It is likely that the closure body is a block but where the
20562060
// braces have been removed. We will recover and eat the next

library/alloc/src/rc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1386,7 +1386,7 @@ impl<T: ?Sized> Rc<T> {
13861386
Self::allocate_for_layout(
13871387
Layout::for_value(&*ptr),
13881388
|layout| Global.allocate(layout),
1389-
|mem| mem.with_metadata_of(ptr as *mut RcBox<T>),
1389+
|mem| mem.with_metadata_of(ptr as *const RcBox<T>),
13901390
)
13911391
}
13921392
}

library/alloc/src/string.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use core::str::Utf8Chunks;
6767
use crate::borrow::{Cow, ToOwned};
6868
use crate::boxed::Box;
6969
use crate::collections::TryReserveError;
70-
use crate::str::{self, Chars, Utf8Error};
70+
use crate::str::{self, from_utf8_unchecked_mut, Chars, Utf8Error};
7171
#[cfg(not(no_global_oom_handling))]
7272
use crate::str::{from_boxed_utf8_unchecked, FromStr};
7373
use crate::vec::Vec;
@@ -1849,6 +1849,35 @@ impl String {
18491849
let slice = self.vec.into_boxed_slice();
18501850
unsafe { from_boxed_utf8_unchecked(slice) }
18511851
}
1852+
1853+
/// Consumes and leaks the `String`, returning a mutable reference to the contents,
1854+
/// `&'a mut str`.
1855+
///
1856+
/// This is mainly useful for data that lives for the remainder of
1857+
/// the program's life. Dropping the returned reference will cause a memory
1858+
/// leak.
1859+
///
1860+
/// It does not reallocate or shrink the `String`,
1861+
/// so the leaked allocation may include unused capacity that is not part
1862+
/// of the returned slice.
1863+
///
1864+
/// # Examples
1865+
///
1866+
/// Simple usage:
1867+
///
1868+
/// ```
1869+
/// #![feature(string_leak)]
1870+
///
1871+
/// let x = String::from("bucket");
1872+
/// let static_ref: &'static mut str = x.leak();
1873+
/// assert_eq!(static_ref, "bucket");
1874+
/// ```
1875+
#[unstable(feature = "string_leak", issue = "102929")]
1876+
#[inline]
1877+
pub fn leak(self) -> &'static mut str {
1878+
let slice = self.vec.leak();
1879+
unsafe { from_utf8_unchecked_mut(slice) }
1880+
}
18521881
}
18531882

18541883
impl FromUtf8Error {

library/alloc/src/sync.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ impl<T: ?Sized> Arc<T> {
12041204
Self::allocate_for_layout(
12051205
Layout::for_value(&*ptr),
12061206
|layout| Global.allocate(layout),
1207-
|mem| mem.with_metadata_of(ptr as *mut ArcInner<T>),
1207+
|mem| mem.with_metadata_of(ptr as *const ArcInner<T>),
12081208
)
12091209
}
12101210
}

library/core/src/ptr/mut_ptr.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,14 @@ impl<T: ?Sized> *mut T {
8080
#[unstable(feature = "set_ptr_value", issue = "75091")]
8181
#[must_use = "returns a new pointer rather than modifying its argument"]
8282
#[inline]
83-
pub fn with_metadata_of<U>(self, mut val: *mut U) -> *mut U
83+
pub fn with_metadata_of<U>(self, val: *const U) -> *mut U
8484
where
8585
U: ?Sized,
8686
{
87+
// Prepare in the type system that we will replace the pointer value with a mutable
88+
// pointer, taking the mutable provenance from the `self` pointer.
89+
let mut val = val as *mut U;
90+
// Pointer to the pointer value within the value.
8791
let target = &mut val as *mut *mut U as *mut *mut u8;
8892
// SAFETY: In case of a thin pointer, this operations is identical
8993
// to a simple assignment. In case of a fat pointer, with the current

library/core/src/ptr/non_null.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::cmp::Ordering;
22
use crate::convert::From;
33
use crate::fmt;
44
use crate::hash;
5+
use crate::intrinsics::assert_unsafe_precondition;
56
use crate::marker::Unsize;
67
use crate::mem::{self, MaybeUninit};
78
use crate::num::NonZeroUsize;
@@ -195,7 +196,10 @@ impl<T: ?Sized> NonNull<T> {
195196
#[inline]
196197
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
197198
// SAFETY: the caller must guarantee that `ptr` is non-null.
198-
unsafe { NonNull { pointer: ptr as _ } }
199+
unsafe {
200+
assert_unsafe_precondition!([T: ?Sized](ptr: *mut T) => !ptr.is_null());
201+
NonNull { pointer: ptr as _ }
202+
}
199203
}
200204

201205
/// Creates a new `NonNull` if `ptr` is non-null.

library/std/src/sys/windows/c.rs

+3
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ pub const FIONBIO: c_ulong = 0x8004667e;
129129

130130
pub const MAX_PATH: usize = 260;
131131

132+
pub const FILE_TYPE_PIPE: u32 = 3;
133+
132134
#[repr(C)]
133135
#[derive(Copy)]
134136
pub struct WIN32_FIND_DATAW {
@@ -1114,6 +1116,7 @@ extern "system" {
11141116
lpFileInformation: LPVOID,
11151117
dwBufferSize: DWORD,
11161118
) -> BOOL;
1119+
pub fn GetFileType(hfile: HANDLE) -> DWORD;
11171120
pub fn SleepConditionVariableSRW(
11181121
ConditionVariable: PCONDITION_VARIABLE,
11191122
SRWLock: PSRWLOCK,

library/std/src/sys/windows/io.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
120120
}
121121

122122
unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
123+
// Early return if the handle is not a pipe.
124+
if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
125+
return false;
126+
}
127+
123128
const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>();
124129
let mut name_info_bytes = Align8([0u8; SIZE]);
125130
let res = c::GetFileInformationByHandleEx(
@@ -137,11 +142,13 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
137142
let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>();
138143
let s = core::slice::from_raw_parts(name_ptr, name_len);
139144
let name = String::from_utf16_lossy(s);
145+
// Get the file name only.
146+
let name = name.rsplit('\\').next().unwrap_or(&name);
140147
// This checks whether 'pty' exists in the file name, which indicates that
141148
// a pseudo-terminal is attached. To mitigate against false positives
142149
// (e.g., an actual file name that contains 'pty'), we also require that
143-
// either the strings 'msys-' or 'cygwin-' are in the file name as well.)
144-
let is_msys = name.contains("msys-") || name.contains("cygwin-");
150+
// the file name begins with either the strings 'msys-' or 'cygwin-'.)
151+
let is_msys = name.starts_with("msys-") || name.starts_with("cygwin-");
145152
let is_pty = name.contains("-pty");
146153
is_msys && is_pty
147154
}

src/librustdoc/clean/mod.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -1201,21 +1201,19 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
12011201
}
12021202

12031203
if let ty::TraitContainer = assoc_item.container {
1204-
// FIXME(fmease): `tcx.explicit_item_bounds` does not contain the bounds of GATs,
1205-
// e.g. the bounds `Copy`, `Display` & (implicitly) `Sized` in
1206-
// `type Assoc<T: Copy> where T: Display`. This also means that we
1207-
// later incorrectly render `where T: ?Sized`.
1208-
//
1209-
// The result of `tcx.explicit_predicates_of` *does* contain them but
1210-
// it does not contain the other bounds / predicates we need.
1211-
// Either merge those two interned lists somehow or refactor
1212-
// `clean_ty_generics` to call `explicit_item_bounds` by itself.
12131204
let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
1214-
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
1215-
let mut generics =
1216-
clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates);
1217-
// Filter out the bounds that are (likely?) directly attached to the associated type,
1218-
// as opposed to being located in the where clause.
1205+
let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
1206+
let predicates =
1207+
tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied());
1208+
let mut generics = clean_ty_generics(
1209+
cx,
1210+
tcx.generics_of(assoc_item.def_id),
1211+
ty::GenericPredicates { parent: None, predicates },
1212+
);
1213+
// Move bounds that are (likely) directly attached to the associated type
1214+
// from the where clause to the associated type.
1215+
// There is no guarantee that this is what the user actually wrote but we have
1216+
// no way of knowing.
12191217
let mut bounds = generics
12201218
.where_predicates
12211219
.drain_filter(|pred| match *pred {
@@ -1273,6 +1271,24 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
12731271
}
12741272
None => bounds.push(GenericBound::maybe_sized(cx)),
12751273
}
1274+
// Move bounds that are (likely) directly attached to the parameters of the
1275+
// (generic) associated type from the where clause to the respective parameter.
1276+
// There is no guarantee that this is what the user actually wrote but we have
1277+
// no way of knowing.
1278+
let mut where_predicates = Vec::new();
1279+
for mut pred in generics.where_predicates {
1280+
if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
1281+
&& let Some(GenericParamDef {
1282+
kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
1283+
..
1284+
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1285+
{
1286+
param_bounds.extend(mem::take(bounds));
1287+
} else {
1288+
where_predicates.push(pred);
1289+
}
1290+
}
1291+
generics.where_predicates = where_predicates;
12761292

12771293
if tcx.impl_defaultness(assoc_item.def_id).has_value() {
12781294
AssocTypeItem(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h4 class="code-header">type <a href="#associatedtype.Out2" class="associatedtype">Out2</a>&lt;T&gt;: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = T&gt;</h4>

src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
// Regression test for issues #77763, #84579 and #102142.
22
#![crate_name = "main"]
33

4-
// aux-build:assoc_item_trait_bounds_with_bindings.rs
4+
// aux-build:assoc_item_trait_bounds.rs
55
// build-aux-docs
66
// ignore-cross-compile
7-
extern crate assoc_item_trait_bounds_with_bindings as aux;
8-
9-
// FIXME(fmease): Don't render an incorrect `T: ?Sized` where-clause for parameters
10-
// of GATs like `Main::Out{2,4}`. Add a snapshot test once it's fixed.
7+
extern crate assoc_item_trait_bounds as aux;
118

129
// @has main/trait.Main.html
1310
// @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support<Item = ()>'
@@ -24,11 +21,15 @@ extern crate assoc_item_trait_bounds_with_bindings as aux;
2421
// @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>"
2522
// @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>"
2623
// @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>"
24+
// @has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>"
2725
//
28-
// Snapshots: Check that we do not render any where-clauses for those associated types since all of
29-
// the trait bounds contained within were moved to the bounds of the respective item.
26+
// Snapshots:
27+
// Check that we don't render any where-clauses for the following associated types since
28+
// all corresponding projection equality predicates should have already been re-sugared
29+
// to associated type bindings:
3030
//
3131
// @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]'
32+
// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]'
3233
// @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]'
3334
//
3435
// @has - '//*[@id="tymethod.make"]' \

src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html

-1
This file was deleted.

src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub trait Main {
1515
type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>;
1616
type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>;
1717
type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>;
18+
type Out14<P: Copy + Eq, Q: ?Sized>;
1819

1920
fn make<F>(_: F, _: impl FnMut(&str) -> bool)
2021
where
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
// Checks that the fix in #103222 doesn't also disqualify semicolons after
4+
// closures within parentheses *in macros*, where they're totally allowed.
5+
6+
macro_rules! m {
7+
(($expr:expr ; )) => {
8+
$expr
9+
};
10+
}
11+
12+
fn main() {
13+
let x = m!(( ||() ; ));
14+
}

0 commit comments

Comments
 (0)