Skip to content

Commit 4a71a05

Browse files
committed
Auto merge of rust-lang#114569 - matthiaskrgr:rollup-p8tcxtz, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#98935 (Implement `Option::take_if`) - rust-lang#114093 (Add regression test for `echo 'mod unknown;' | rustc -`) - rust-lang#114229 (Nest tests/codegen/sanitizer*.rs tests in sanitizer dir) - rust-lang#114230 (Nest other codegen test topics) - rust-lang#114362 (string.rs: remove "Basic usage" text) - rust-lang#114365 (str.rs: remove "Basic usage" text) - rust-lang#114382 (Add a new `compare_bytes` intrinsic instead of calling `memcmp` directly) - rust-lang#114549 (Style fix and refactor on resolve diagnostics) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9fca8e7 + d804b74 commit 4a71a05

File tree

86 files changed

+439
-393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+439
-393
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,20 @@ fn codegen_regular_intrinsic_call<'tcx>(
11551155
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
11561156
}
11571157

1158+
sym::compare_bytes => {
1159+
intrinsic_args!(fx, args => (lhs_ptr, rhs_ptr, bytes_val); intrinsic);
1160+
let lhs_ptr = lhs_ptr.load_scalar(fx);
1161+
let rhs_ptr = rhs_ptr.load_scalar(fx);
1162+
let bytes_val = bytes_val.load_scalar(fx);
1163+
1164+
let params = vec![AbiParam::new(fx.pointer_type); 3];
1165+
let returns = vec![AbiParam::new(types::I32)];
1166+
let args = &[lhs_ptr, rhs_ptr, bytes_val];
1167+
// Here we assume that the `memcmp` provided by the target is a NOP for size 0.
1168+
let cmp = fx.lib_call("memcmp", params, returns, args)[0];
1169+
ret.write_cvalue(fx, CValue::by_val(cmp, ret.layout()));
1170+
}
1171+
11581172
sym::const_allocate => {
11591173
intrinsic_args!(fx, args => (_size, _align); intrinsic);
11601174

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,21 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
302302
}
303303
}
304304

305+
sym::compare_bytes => {
306+
let a = args[0].immediate();
307+
let b = args[1].immediate();
308+
let n = args[2].immediate();
309+
310+
let void_ptr_type = self.context.new_type::<*const ()>();
311+
let a_ptr = self.bitcast(a, void_ptr_type);
312+
let b_ptr = self.bitcast(b, void_ptr_type);
313+
314+
// Here we assume that the `memcmp` provided by the target is a NOP for size 0.
315+
let builtin = self.context.get_builtin_function("memcmp");
316+
let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
317+
self.sext(cmp, self.type_ix(32))
318+
}
319+
305320
sym::black_box => {
306321
args[0].val.store(self, result);
307322

compiler/rustc_codegen_llvm/src/context.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,8 @@ impl<'ll> CodegenCx<'ll, '_> {
891891
ifn!("llvm.prefetch", fn(ptr, t_i32, t_i32, t_i32) -> void);
892892

893893
// This isn't an "LLVM intrinsic", but LLVM's optimization passes
894-
// recognize it like one and we assume it exists in `core::slice::cmp`
894+
// recognize it like one (including turning it into `bcmp` sometimes)
895+
// and we use it to implement intrinsics like `raw_eq` and `compare_bytes`
895896
match self.sess().target.arch.as_ref() {
896897
"avr" | "msp430" => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i16),
897898
_ => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i32),

compiler/rustc_codegen_llvm/src/intrinsic.rs

+10
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,16 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
329329
}
330330
}
331331

332+
sym::compare_bytes => {
333+
// Here we assume that the `memcmp` provided by the target is a NOP for size 0.
334+
let cmp = self.call_intrinsic(
335+
"memcmp",
336+
&[args[0].immediate(), args[1].immediate(), args[2].immediate()],
337+
);
338+
// Some targets have `memcmp` returning `i16`, but the intrinsic is always `i32`.
339+
self.sext(cmp, self.type_ix(32))
340+
}
341+
332342
sym::black_box => {
333343
args[0].val.store(self, result);
334344
let result_val_span = [result.llval];

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+22
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
261261
sym::write_bytes => {
262262
self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?;
263263
}
264+
sym::compare_bytes => {
265+
let result = self.compare_bytes_intrinsic(&args[0], &args[1], &args[2])?;
266+
self.write_scalar(result, dest)?;
267+
}
264268
sym::arith_offset => {
265269
let ptr = self.read_pointer(&args[0])?;
266270
let offset_count = self.read_target_isize(&args[1])?;
@@ -643,6 +647,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
643647
self.write_bytes_ptr(dst, bytes)
644648
}
645649

650+
pub(crate) fn compare_bytes_intrinsic(
651+
&mut self,
652+
left: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
653+
right: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
654+
byte_count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
655+
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
656+
let left = self.read_pointer(left)?;
657+
let right = self.read_pointer(right)?;
658+
let n = Size::from_bytes(self.read_target_usize(byte_count)?);
659+
660+
let left_bytes = self.read_bytes_ptr_strip_provenance(left, n)?;
661+
let right_bytes = self.read_bytes_ptr_strip_provenance(right, n)?;
662+
663+
// `Ordering`'s discriminants are -1/0/+1, so casting does the right thing.
664+
let result = Ord::cmp(left_bytes, right_bytes) as i32;
665+
Ok(Scalar::from_i32(result))
666+
}
667+
646668
pub(crate) fn raw_eq_intrinsic(
647669
&mut self,
648670
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+4
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
273273
],
274274
Ty::new_unit(tcx),
275275
),
276+
sym::compare_bytes => {
277+
let byte_ptr = Ty::new_imm_ptr(tcx, tcx.types.u8);
278+
(0, vec![byte_ptr, byte_ptr, tcx.types.usize], tcx.types.i32)
279+
}
276280
sym::write_bytes | sym::volatile_set_memory => (
277281
1,
278282
vec![

compiler/rustc_resolve/src/late/diagnostics.rs

+35-38
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
555555
}
556556
})
557557
.collect::<Vec<_>>();
558-
let crate_def_id = CRATE_DEF_ID.to_def_id();
559558
// Try to filter out intrinsics candidates, as long as we have
560559
// some other candidates to suggest.
561560
let intrinsic_candidates: Vec<_> = candidates
@@ -566,8 +565,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
566565
.collect();
567566
if candidates.is_empty() {
568567
// Put them back if we have no more candidates to suggest...
569-
candidates.extend(intrinsic_candidates);
568+
candidates = intrinsic_candidates;
570569
}
570+
let crate_def_id = CRATE_DEF_ID.to_def_id();
571571
if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
572572
let mut enum_candidates: Vec<_> = self
573573
.r
@@ -1180,37 +1180,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
11801180
/// return the span of whole call and the span for all arguments expect the first one (`self`).
11811181
fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option<Span>)> {
11821182
let mut has_self_arg = None;
1183-
if let PathSource::Expr(Some(parent)) = source {
1184-
match &parent.kind {
1185-
ExprKind::Call(_, args) if !args.is_empty() => {
1186-
let mut expr_kind = &args[0].kind;
1187-
loop {
1188-
match expr_kind {
1189-
ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
1190-
if arg_name.segments[0].ident.name == kw::SelfLower {
1191-
let call_span = parent.span;
1192-
let tail_args_span = if args.len() > 1 {
1193-
Some(Span::new(
1194-
args[1].span.lo(),
1195-
args.last().unwrap().span.hi(),
1196-
call_span.ctxt(),
1197-
None,
1198-
))
1199-
} else {
1200-
None
1201-
};
1202-
has_self_arg = Some((call_span, tail_args_span));
1203-
}
1204-
break;
1183+
if let PathSource::Expr(Some(parent)) = source
1184+
&& let ExprKind::Call(_, args) = &parent.kind
1185+
&& !args.is_empty() {
1186+
let mut expr_kind = &args[0].kind;
1187+
loop {
1188+
match expr_kind {
1189+
ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
1190+
if arg_name.segments[0].ident.name == kw::SelfLower {
1191+
let call_span = parent.span;
1192+
let tail_args_span = if args.len() > 1 {
1193+
Some(Span::new(
1194+
args[1].span.lo(),
1195+
args.last().unwrap().span.hi(),
1196+
call_span.ctxt(),
1197+
None,
1198+
))
1199+
} else {
1200+
None
1201+
};
1202+
has_self_arg = Some((call_span, tail_args_span));
12051203
}
1206-
ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
1207-
_ => break,
1204+
break;
12081205
}
1206+
ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
1207+
_ => break,
12091208
}
12101209
}
1211-
_ => (),
1212-
}
1213-
};
1210+
}
12141211
has_self_arg
12151212
}
12161213

@@ -1220,15 +1217,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
12201217
// where a brace being opened means a block is being started. Look
12211218
// ahead for the next text to see if `span` is followed by a `{`.
12221219
let sm = self.r.tcx.sess.source_map();
1223-
let sp = sm.span_look_ahead(span, None, Some(50));
1224-
let followed_by_brace = matches!(sm.span_to_snippet(sp), Ok(ref snippet) if snippet == "{");
1225-
// In case this could be a struct literal that needs to be surrounded
1226-
// by parentheses, find the appropriate span.
1227-
let closing_span = sm.span_look_ahead(span, Some("}"), Some(50));
1228-
let closing_brace: Option<Span> = sm
1229-
.span_to_snippet(closing_span)
1230-
.map_or(None, |s| if s == "}" { Some(span.to(closing_span)) } else { None });
1231-
(followed_by_brace, closing_brace)
1220+
if let Some(followed_brace_span) = sm.span_look_ahead(span, "{", Some(50)) {
1221+
// In case this could be a struct literal that needs to be surrounded
1222+
// by parentheses, find the appropriate span.
1223+
let close_brace_span = sm.span_look_ahead(followed_brace_span, "}", Some(50));
1224+
let closing_brace = close_brace_span.map(|sp| span.to(sp));
1225+
(true, closing_brace)
1226+
} else {
1227+
(false, None)
1228+
}
12321229
}
12331230

12341231
/// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`

compiler/rustc_span/src/source_map.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -973,24 +973,21 @@ impl SourceMap {
973973
Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
974974
}
975975

976-
/// Returns a new span to check next none-whitespace character or some specified expected character
977-
/// If `expect` is none, the first span of non-whitespace character is returned.
978-
/// If `expect` presented, the first span of the character `expect` is returned
979-
/// Otherwise, the span reached to limit is returned.
980-
pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
976+
/// Check whether span is followed by some specified expected string in limit scope
977+
pub fn span_look_ahead(&self, span: Span, expect: &str, limit: Option<usize>) -> Option<Span> {
981978
let mut sp = span;
982979
for _ in 0..limit.unwrap_or(100_usize) {
983980
sp = self.next_point(sp);
984981
if let Ok(ref snippet) = self.span_to_snippet(sp) {
985-
if expect.is_some_and(|es| snippet == es) {
986-
break;
982+
if snippet == expect {
983+
return Some(sp);
987984
}
988-
if expect.is_none() && snippet.chars().any(|c| !c.is_whitespace()) {
985+
if snippet.chars().any(|c| !c.is_whitespace()) {
989986
break;
990987
}
991988
}
992989
}
993-
sp
990+
None
994991
}
995992

996993
/// Finds the width of the character, either before or after the end of provided span,

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ symbols! {
498498
cold,
499499
collapse_debuginfo,
500500
column,
501+
compare_bytes,
501502
compare_exchange,
502503
compare_exchange_weak,
503504
compile_error,

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -1429,20 +1429,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
14291429

14301430
// Issue #109436, we need to add parentheses properly for method calls
14311431
// for example, `foo.into()` should be `(&foo).into()`
1432-
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(
1433-
self.tcx.sess.source_map().span_look_ahead(span, Some("."), Some(50)),
1434-
) {
1435-
if snippet == "." {
1436-
err.multipart_suggestion_verbose(
1437-
sugg_msg,
1438-
vec![
1439-
(span.shrink_to_lo(), format!("({sugg_prefix}")),
1440-
(span.shrink_to_hi(), ")".to_string()),
1441-
],
1442-
Applicability::MaybeIncorrect,
1443-
);
1444-
return true;
1445-
}
1432+
if let Some(_) =
1433+
self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50))
1434+
{
1435+
err.multipart_suggestion_verbose(
1436+
sugg_msg,
1437+
vec![
1438+
(span.shrink_to_lo(), format!("({sugg_prefix}")),
1439+
(span.shrink_to_hi(), ")".to_string()),
1440+
],
1441+
Applicability::MaybeIncorrect,
1442+
);
1443+
return true;
14461444
}
14471445

14481446
// Issue #104961, we need to add parentheses properly for compound expressions

library/alloc/src/str.rs

-6
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@ impl str {
223223
///
224224
/// # Examples
225225
///
226-
/// Basic usage:
227-
///
228226
/// ```
229227
/// let s = "this is a string";
230228
/// let boxed_str = s.to_owned().into_boxed_str();
@@ -487,8 +485,6 @@ impl str {
487485
///
488486
/// # Examples
489487
///
490-
/// Basic usage:
491-
///
492488
/// ```
493489
/// let string = String::from("birthday gift");
494490
/// let boxed_str = string.clone().into_boxed_str();
@@ -602,8 +598,6 @@ impl str {
602598
///
603599
/// # Examples
604600
///
605-
/// Basic usage:
606-
///
607601
/// ```
608602
/// let smile_utf8 = Box::new([226, 152, 186]);
609603
/// let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) };

0 commit comments

Comments
 (0)