Skip to content

Commit 2c28b0e

Browse files
committed
Auto merge of rust-lang#96134 - Dylan-DPC:rollup-ejug3yq, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - rust-lang#95346 (Stablize `const_extern_fn` for "Rust" and "C") - rust-lang#95933 (htmldocck: Compare HTML tree instead of plain text html) - rust-lang#96105 (Make the debug output for `TargetSelection` less verbose) - rust-lang#96112 (Strict provenance lint diagnostics improvements) - rust-lang#96119 (update Miri) - rust-lang#96124 (to_digit tweak) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 563ef23 + b47265e commit 2c28b0e

File tree

12 files changed

+185
-100
lines changed

12 files changed

+185
-100
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+20-17
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,22 @@ struct PostExpansionVisitor<'a> {
5858
}
5959

6060
impl<'a> PostExpansionVisitor<'a> {
61-
fn check_abi(&self, abi: ast::StrLit) {
61+
fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
6262
let ast::StrLit { symbol_unescaped, span, .. } = abi;
6363

64+
if let ast::Const::Yes(_) = constness {
65+
match symbol_unescaped.as_str() {
66+
// Stable
67+
"Rust" | "C" => {}
68+
abi => gate_feature_post!(
69+
&self,
70+
const_extern_fn,
71+
span,
72+
&format!("`{}` as a `const fn` ABI is unstable", abi)
73+
),
74+
}
75+
}
76+
6477
match symbol_unescaped.as_str() {
6578
// Stable
6679
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
@@ -261,9 +274,9 @@ impl<'a> PostExpansionVisitor<'a> {
261274
}
262275
}
263276

264-
fn check_extern(&self, ext: ast::Extern) {
277+
fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
265278
if let ast::Extern::Explicit(abi) = ext {
266-
self.check_abi(abi);
279+
self.check_abi(abi, constness);
267280
}
268281
}
269282

@@ -437,7 +450,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
437450
match i.kind {
438451
ast::ItemKind::ForeignMod(ref foreign_module) => {
439452
if let Some(abi) = foreign_module.abi {
440-
self.check_abi(abi);
453+
self.check_abi(abi, ast::Const::No);
441454
}
442455
}
443456

@@ -560,7 +573,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
560573
fn visit_ty(&mut self, ty: &'a ast::Ty) {
561574
match ty.kind {
562575
ast::TyKind::BareFn(ref bare_fn_ty) => {
563-
self.check_extern(bare_fn_ty.ext);
576+
// Function pointers cannot be `const`
577+
self.check_extern(bare_fn_ty.ext, ast::Const::No);
564578
}
565579
ast::TyKind::Never => {
566580
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -660,18 +674,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
660674
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
661675
if let Some(header) = fn_kind.header() {
662676
// Stability of const fn methods are covered in `visit_assoc_item` below.
663-
self.check_extern(header.ext);
664-
665-
if let (ast::Const::Yes(_), ast::Extern::Implicit)
666-
| (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
667-
{
668-
gate_feature_post!(
669-
&self,
670-
const_extern_fn,
671-
span,
672-
"`const extern fn` definitions are unstable"
673-
);
674-
}
677+
self.check_extern(header.ext, header.constness);
675678
}
676679

677680
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {

compiler/rustc_parse/src/parser/ty.rs

+3
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ impl<'a> Parser<'a> {
523523
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
524524
let whole_span = lo.to(self.prev_token.span);
525525
if let ast::Const::Yes(span) = constness {
526+
// If we ever start to allow `const fn()`, then update
527+
// feature gating for `#![feature(const_extern_fn)]` to
528+
// cover it.
526529
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
527530
}
528531
if let ast::Async::Yes { span, .. } = asyncness {

compiler/rustc_typeck/src/check/cast.rs

+29-20
Original file line numberDiff line numberDiff line change
@@ -993,20 +993,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
993993
));
994994

995995
let msg = "use `.addr()` to obtain the address of a pointer";
996-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
997-
let scalar_cast = match t_c {
998-
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
999-
_ => format!(" as {}", self.cast_ty),
1000-
};
996+
997+
let expr_prec = self.expr.precedence().order();
998+
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
999+
1000+
let scalar_cast = match t_c {
1001+
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
1002+
_ => format!(" as {}", self.cast_ty),
1003+
};
1004+
1005+
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
1006+
1007+
if needs_parens {
1008+
let suggestions = vec![
1009+
(self.expr_span.shrink_to_lo(), String::from("(")),
1010+
(cast_span, format!(").addr(){scalar_cast}")),
1011+
];
1012+
1013+
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
1014+
} else {
10011015
err.span_suggestion(
1002-
self.span,
1016+
cast_span,
10031017
msg,
1004-
format!("({snippet}).addr(){scalar_cast}"),
1005-
Applicability::MaybeIncorrect
1018+
format!(".addr(){scalar_cast}"),
1019+
Applicability::MaybeIncorrect,
10061020
);
1007-
} else {
1008-
err.help(msg);
10091021
}
1022+
10101023
err.help(
10111024
"if you can't comply with strict provenance and need to expose the pointer \
10121025
provenance you can use `.expose_addr()` instead"
@@ -1028,16 +1041,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10281041
self.expr_ty, self.cast_ty
10291042
));
10301043
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
1031-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
1032-
err.span_suggestion(
1033-
self.span,
1034-
msg,
1035-
format!("(...).with_addr({snippet})"),
1036-
Applicability::HasPlaceholders,
1037-
);
1038-
} else {
1039-
err.help(msg);
1040-
}
1044+
let suggestions = vec![
1045+
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
1046+
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
1047+
];
1048+
1049+
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
10411050
err.help(
10421051
"if you can't comply with strict provenance and don't have a pointer with \
10431052
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"

library/core/src/char/methods.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,10 @@ impl char {
343343
without modifying the original"]
344344
#[inline]
345345
pub const fn to_digit(self, radix: u32) -> Option<u32> {
346-
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
347346
// If not a digit, a number greater than radix will be created.
348347
let mut digit = (self as u32).wrapping_sub('0' as u32);
349348
if radix > 10 {
349+
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
350350
if digit < 10 {
351351
return Some(digit);
352352
}

src/bootstrap/config.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl FromStr for LlvmLibunwind {
221221
}
222222
}
223223

224-
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
224+
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
225225
pub struct TargetSelection {
226226
pub triple: Interned<String>,
227227
file: Option<Interned<String>>,
@@ -276,6 +276,12 @@ impl fmt::Display for TargetSelection {
276276
}
277277
}
278278

279+
impl fmt::Debug for TargetSelection {
280+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281+
write!(f, "{}", self)
282+
}
283+
}
284+
279285
impl PartialEq<&str> for TargetSelection {
280286
fn eq(&self, other: &&str) -> bool {
281287
self.triple == *other

src/etc/htmldocck.py

+66-4
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ def flatten(node):
285285
return ''.join(acc)
286286

287287

288+
def make_xml(text):
289+
xml = ET.XML('<xml>%s</xml>' % text)
290+
return xml
291+
292+
288293
def normalize_xpath(path):
289294
path = path.replace("{{channel}}", channel)
290295
if path.startswith('//'):
@@ -401,7 +406,7 @@ def get_tree_count(tree, path):
401406
return len(tree.findall(path))
402407

403408

404-
def check_snapshot(snapshot_name, tree, normalize_to_text):
409+
def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
405410
assert rust_test_path.endswith('.rs')
406411
snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
407412
try:
@@ -414,11 +419,15 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
414419
raise FailedCheck('No saved snapshot value')
415420

416421
if not normalize_to_text:
417-
actual_str = ET.tostring(tree).decode('utf-8')
422+
actual_str = ET.tostring(actual_tree).decode('utf-8')
418423
else:
419-
actual_str = flatten(tree)
424+
actual_str = flatten(actual_tree)
425+
426+
if not expected_str \
427+
or (not normalize_to_text and
428+
not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
429+
or (normalize_to_text and actual_str != expected_str):
420430

421-
if expected_str != actual_str:
422431
if bless:
423432
with open(snapshot_path, 'w') as snapshot_file:
424433
snapshot_file.write(actual_str)
@@ -430,6 +439,59 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
430439
print()
431440
raise FailedCheck('Actual snapshot value is different than expected')
432441

442+
443+
# Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
444+
def compare_tree(x1, x2, reporter=None):
445+
if x1.tag != x2.tag:
446+
if reporter:
447+
reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
448+
return False
449+
for name, value in x1.attrib.items():
450+
if x2.attrib.get(name) != value:
451+
if reporter:
452+
reporter('Attributes do not match: %s=%r, %s=%r'
453+
% (name, value, name, x2.attrib.get(name)))
454+
return False
455+
for name in x2.attrib:
456+
if name not in x1.attrib:
457+
if reporter:
458+
reporter('x2 has an attribute x1 is missing: %s'
459+
% name)
460+
return False
461+
if not text_compare(x1.text, x2.text):
462+
if reporter:
463+
reporter('text: %r != %r' % (x1.text, x2.text))
464+
return False
465+
if not text_compare(x1.tail, x2.tail):
466+
if reporter:
467+
reporter('tail: %r != %r' % (x1.tail, x2.tail))
468+
return False
469+
cl1 = list(x1)
470+
cl2 = list(x2)
471+
if len(cl1) != len(cl2):
472+
if reporter:
473+
reporter('children length differs, %i != %i'
474+
% (len(cl1), len(cl2)))
475+
return False
476+
i = 0
477+
for c1, c2 in zip(cl1, cl2):
478+
i += 1
479+
if not compare_tree(c1, c2, reporter=reporter):
480+
if reporter:
481+
reporter('children %i do not match: %s'
482+
% (i, c1.tag))
483+
return False
484+
return True
485+
486+
487+
def text_compare(t1, t2):
488+
if not t1 and not t2:
489+
return True
490+
if t1 == '*' or t2 == '*':
491+
return True
492+
return (t1 or '').strip() == (t2 or '').strip()
493+
494+
433495
def stderr(*args):
434496
if sys.version_info.major < 3:
435497
file = codecs.getwriter('utf-8')(sys.stderr)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
// Check that `const extern fn` and `const unsafe extern fn` are feature-gated.
1+
// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
2+
// for certain ABIs.
23

3-
const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable
4-
const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable
5-
const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable
6-
const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable
7-
const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable
8-
const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable
4+
const extern fn foo1() {}
5+
const extern "C" fn foo2() {}
6+
const extern "Rust" fn foo3() {}
7+
const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
8+
const unsafe extern fn bar1() {}
9+
const unsafe extern "C" fn bar2() {}
10+
const unsafe extern "Rust" fn bar3() {}
11+
const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
912

1013
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,21 @@
1-
error[E0658]: `const extern fn` definitions are unstable
2-
--> $DIR/feature-gate-const_extern_fn.rs:3:1
1+
error[E0658]: `cdecl` as a `const fn` ABI is unstable
2+
--> $DIR/feature-gate-const_extern_fn.rs:7:14
33
|
4-
LL | const extern fn foo1() {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | const extern "cdecl" fn foo4() {}
5+
| ^^^^^^^
66
|
77
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
88
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
99

10-
error[E0658]: `const extern fn` definitions are unstable
11-
--> $DIR/feature-gate-const_extern_fn.rs:4:1
10+
error[E0658]: `cdecl` as a `const fn` ABI is unstable
11+
--> $DIR/feature-gate-const_extern_fn.rs:11:21
1212
|
13-
LL | const extern "C" fn foo2() {}
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
LL | const unsafe extern "cdecl" fn bar4() {}
14+
| ^^^^^^^
1515
|
1616
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
1717
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
1818

19-
error[E0658]: `const extern fn` definitions are unstable
20-
--> $DIR/feature-gate-const_extern_fn.rs:5:1
21-
|
22-
LL | const extern "Rust" fn foo3() {}
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24-
|
25-
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
26-
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
27-
28-
error[E0658]: `const extern fn` definitions are unstable
29-
--> $DIR/feature-gate-const_extern_fn.rs:6:1
30-
|
31-
LL | const unsafe extern fn bar1() {}
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33-
|
34-
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
35-
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
36-
37-
error[E0658]: `const extern fn` definitions are unstable
38-
--> $DIR/feature-gate-const_extern_fn.rs:7:1
39-
|
40-
LL | const unsafe extern "C" fn bar2() {}
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42-
|
43-
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
44-
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
45-
46-
error[E0658]: `const extern fn` definitions are unstable
47-
--> $DIR/feature-gate-const_extern_fn.rs:8:1
48-
|
49-
LL | const unsafe extern "Rust" fn bar3() {}
50-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51-
|
52-
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
53-
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
54-
55-
error: aborting due to 6 previous errors
19+
error: aborting due to 2 previous errors
5620

5721
For more information about this error, try `rustc --explain E0658`.

src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | #![deny(fuzzy_provenance_casts)]
1313
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
1414
|
1515
LL | let dangling = (...).with_addr(16_usize);
16-
| ~~~~~~~~~~~~~~~~~~~~~~~~~
16+
| ++++++++++++++++ ~
1717

1818
error: aborting due to previous error
1919

src/test/ui/lint/lint-strict-provenance-lossy-casts.rs

+7
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,11 @@ fn main() {
88

99
let addr_32bit = &x as *const u8 as u32;
1010
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
11+
12+
// don't add unnecessary parens in the suggestion
13+
let ptr = &x as *const u8;
14+
let ptr_addr = ptr as usize;
15+
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
16+
let ptr_addr_32bit = ptr as u32;
17+
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
1118
}

0 commit comments

Comments
 (0)