Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 289b2b8

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

File tree

17 files changed

+153
-67
lines changed

17 files changed

+153
-67
lines changed

‎compiler/rustc_lint/src/types.rs‎

Lines changed: 40 additions & 38 deletions
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‎

Lines changed: 4 additions & 0 deletions
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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 30 additions & 1 deletion
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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 5 additions & 1 deletion
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, mutval: *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‎

Lines changed: 5 additions & 1 deletion
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‎

Lines changed: 3 additions & 0 deletions
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‎

Lines changed: 9 additions & 2 deletions
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‎

Lines changed: 30 additions & 14 deletions
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(

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /