Auto merge of #96134 - Dylan-DPC:rollup-ejug3yq, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #95346 (Stablize `const_extern_fn` for "Rust" and "C") - #95933 (htmldocck: Compare HTML tree instead of plain text html) - #96105 (Make the debug output for `TargetSelection` less verbose) - #96112 (Strict provenance lint diagnostics improvements) - #96119 (update Miri) - #96124 (to_digit tweak) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2c28b0eaf9
@ -58,9 +58,22 @@ struct PostExpansionVisitor<'a> {
|
||||
}
|
||||
|
||||
impl<'a> PostExpansionVisitor<'a> {
|
||||
fn check_abi(&self, abi: ast::StrLit) {
|
||||
fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||
let ast::StrLit { symbol_unescaped, span, .. } = abi;
|
||||
|
||||
if let ast::Const::Yes(_) = constness {
|
||||
match symbol_unescaped.as_str() {
|
||||
// Stable
|
||||
"Rust" | "C" => {}
|
||||
abi => gate_feature_post!(
|
||||
&self,
|
||||
const_extern_fn,
|
||||
span,
|
||||
&format!("`{}` as a `const fn` ABI is unstable", abi)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
match symbol_unescaped.as_str() {
|
||||
// Stable
|
||||
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
|
||||
@ -261,9 +274,9 @@ impl<'a> PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_extern(&self, ext: ast::Extern) {
|
||||
fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
|
||||
if let ast::Extern::Explicit(abi) = ext {
|
||||
self.check_abi(abi);
|
||||
self.check_abi(abi, constness);
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,7 +450,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
match i.kind {
|
||||
ast::ItemKind::ForeignMod(ref foreign_module) => {
|
||||
if let Some(abi) = foreign_module.abi {
|
||||
self.check_abi(abi);
|
||||
self.check_abi(abi, ast::Const::No);
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,7 +573,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||
match ty.kind {
|
||||
ast::TyKind::BareFn(ref bare_fn_ty) => {
|
||||
self.check_extern(bare_fn_ty.ext);
|
||||
// Function pointers cannot be `const`
|
||||
self.check_extern(bare_fn_ty.ext, ast::Const::No);
|
||||
}
|
||||
ast::TyKind::Never => {
|
||||
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
@ -660,18 +674,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||
if let Some(header) = fn_kind.header() {
|
||||
// Stability of const fn methods are covered in `visit_assoc_item` below.
|
||||
self.check_extern(header.ext);
|
||||
|
||||
if let (ast::Const::Yes(_), ast::Extern::Implicit)
|
||||
| (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
|
||||
{
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
const_extern_fn,
|
||||
span,
|
||||
"`const extern fn` definitions are unstable"
|
||||
);
|
||||
}
|
||||
self.check_extern(header.ext, header.constness);
|
||||
}
|
||||
|
||||
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
|
||||
|
@ -523,6 +523,9 @@ impl<'a> Parser<'a> {
|
||||
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
|
||||
let whole_span = lo.to(self.prev_token.span);
|
||||
if let ast::Const::Yes(span) = constness {
|
||||
// If we ever start to allow `const fn()`, then update
|
||||
// feature gating for `#![feature(const_extern_fn)]` to
|
||||
// cover it.
|
||||
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = asyncness {
|
||||
|
@ -993,20 +993,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
));
|
||||
|
||||
let msg = "use `.addr()` to obtain the address of a pointer";
|
||||
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
|
||||
let scalar_cast = match t_c {
|
||||
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
|
||||
_ => format!(" as {}", self.cast_ty),
|
||||
};
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
msg,
|
||||
format!("({snippet}).addr(){scalar_cast}"),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
|
||||
let expr_prec = self.expr.precedence().order();
|
||||
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
|
||||
|
||||
let scalar_cast = match t_c {
|
||||
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
|
||||
_ => format!(" as {}", self.cast_ty),
|
||||
};
|
||||
|
||||
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
||||
|
||||
if needs_parens {
|
||||
let suggestions = vec![
|
||||
(self.expr_span.shrink_to_lo(), String::from("(")),
|
||||
(cast_span, format!(").addr(){scalar_cast}")),
|
||||
];
|
||||
|
||||
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||
} else {
|
||||
err.help(msg);
|
||||
err.span_suggestion(
|
||||
cast_span,
|
||||
msg,
|
||||
format!(".addr(){scalar_cast}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
err.help(
|
||||
"if you can't comply with strict provenance and need to expose the pointer \
|
||||
provenance you can use `.expose_addr()` instead"
|
||||
@ -1028,16 +1041,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
self.expr_ty, self.cast_ty
|
||||
));
|
||||
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
|
||||
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
msg,
|
||||
format!("(...).with_addr({snippet})"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
} else {
|
||||
err.help(msg);
|
||||
}
|
||||
let suggestions = vec![
|
||||
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
|
||||
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
|
||||
];
|
||||
|
||||
err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
|
||||
err.help(
|
||||
"if you can't comply with strict provenance and don't have a pointer with \
|
||||
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
|
||||
|
@ -343,10 +343,10 @@ impl char {
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn to_digit(self, radix: u32) -> Option<u32> {
|
||||
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
|
||||
// If not a digit, a number greater than radix will be created.
|
||||
let mut digit = (self as u32).wrapping_sub('0' as u32);
|
||||
if radix > 10 {
|
||||
assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
|
||||
if digit < 10 {
|
||||
return Some(digit);
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ impl FromStr for LlvmLibunwind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct TargetSelection {
|
||||
pub triple: Interned<String>,
|
||||
file: Option<Interned<String>>,
|
||||
@ -276,6 +276,12 @@ impl fmt::Display for TargetSelection {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TargetSelection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&str> for TargetSelection {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
self.triple == *other
|
||||
|
@ -285,6 +285,11 @@ def flatten(node):
|
||||
return ''.join(acc)
|
||||
|
||||
|
||||
def make_xml(text):
|
||||
xml = ET.XML('<xml>%s</xml>' % text)
|
||||
return xml
|
||||
|
||||
|
||||
def normalize_xpath(path):
|
||||
path = path.replace("{{channel}}", channel)
|
||||
if path.startswith('//'):
|
||||
@ -401,7 +406,7 @@ def get_tree_count(tree, path):
|
||||
return len(tree.findall(path))
|
||||
|
||||
|
||||
def check_snapshot(snapshot_name, tree, normalize_to_text):
|
||||
def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
|
||||
assert rust_test_path.endswith('.rs')
|
||||
snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
|
||||
try:
|
||||
@ -414,11 +419,15 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
|
||||
raise FailedCheck('No saved snapshot value')
|
||||
|
||||
if not normalize_to_text:
|
||||
actual_str = ET.tostring(tree).decode('utf-8')
|
||||
actual_str = ET.tostring(actual_tree).decode('utf-8')
|
||||
else:
|
||||
actual_str = flatten(tree)
|
||||
actual_str = flatten(actual_tree)
|
||||
|
||||
if not expected_str \
|
||||
or (not normalize_to_text and
|
||||
not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
|
||||
or (normalize_to_text and actual_str != expected_str):
|
||||
|
||||
if expected_str != actual_str:
|
||||
if bless:
|
||||
with open(snapshot_path, 'w') as snapshot_file:
|
||||
snapshot_file.write(actual_str)
|
||||
@ -430,6 +439,59 @@ def check_snapshot(snapshot_name, tree, normalize_to_text):
|
||||
print()
|
||||
raise FailedCheck('Actual snapshot value is different than expected')
|
||||
|
||||
|
||||
# Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
|
||||
def compare_tree(x1, x2, reporter=None):
|
||||
if x1.tag != x2.tag:
|
||||
if reporter:
|
||||
reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
|
||||
return False
|
||||
for name, value in x1.attrib.items():
|
||||
if x2.attrib.get(name) != value:
|
||||
if reporter:
|
||||
reporter('Attributes do not match: %s=%r, %s=%r'
|
||||
% (name, value, name, x2.attrib.get(name)))
|
||||
return False
|
||||
for name in x2.attrib:
|
||||
if name not in x1.attrib:
|
||||
if reporter:
|
||||
reporter('x2 has an attribute x1 is missing: %s'
|
||||
% name)
|
||||
return False
|
||||
if not text_compare(x1.text, x2.text):
|
||||
if reporter:
|
||||
reporter('text: %r != %r' % (x1.text, x2.text))
|
||||
return False
|
||||
if not text_compare(x1.tail, x2.tail):
|
||||
if reporter:
|
||||
reporter('tail: %r != %r' % (x1.tail, x2.tail))
|
||||
return False
|
||||
cl1 = list(x1)
|
||||
cl2 = list(x2)
|
||||
if len(cl1) != len(cl2):
|
||||
if reporter:
|
||||
reporter('children length differs, %i != %i'
|
||||
% (len(cl1), len(cl2)))
|
||||
return False
|
||||
i = 0
|
||||
for c1, c2 in zip(cl1, cl2):
|
||||
i += 1
|
||||
if not compare_tree(c1, c2, reporter=reporter):
|
||||
if reporter:
|
||||
reporter('children %i do not match: %s'
|
||||
% (i, c1.tag))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def text_compare(t1, t2):
|
||||
if not t1 and not t2:
|
||||
return True
|
||||
if t1 == '*' or t2 == '*':
|
||||
return True
|
||||
return (t1 or '').strip() == (t2 or '').strip()
|
||||
|
||||
|
||||
def stderr(*args):
|
||||
if sys.version_info.major < 3:
|
||||
file = codecs.getwriter('utf-8')(sys.stderr)
|
||||
|
@ -1,10 +1,13 @@
|
||||
// Check that `const extern fn` and `const unsafe extern fn` are feature-gated.
|
||||
// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
|
||||
// for certain ABIs.
|
||||
|
||||
const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable
|
||||
const extern fn foo1() {}
|
||||
const extern "C" fn foo2() {}
|
||||
const extern "Rust" fn foo3() {}
|
||||
const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
|
||||
const unsafe extern fn bar1() {}
|
||||
const unsafe extern "C" fn bar2() {}
|
||||
const unsafe extern "Rust" fn bar3() {}
|
||||
const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,57 +1,21 @@
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:3:1
|
||||
error[E0658]: `cdecl` as a `const fn` ABI is unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:7:14
|
||||
|
|
||||
LL | const extern fn foo1() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | const extern "cdecl" fn foo4() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:4:1
|
||||
error[E0658]: `cdecl` as a `const fn` ABI is unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:11:21
|
||||
|
|
||||
LL | const extern "C" fn foo2() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | const unsafe extern "cdecl" fn bar4() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:5:1
|
||||
|
|
||||
LL | const extern "Rust" fn foo3() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:6:1
|
||||
|
|
||||
LL | const unsafe extern fn bar1() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:7:1
|
||||
|
|
||||
LL | const unsafe extern "C" fn bar2() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const extern fn` definitions are unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:8:1
|
||||
|
|
||||
LL | const unsafe extern "Rust" fn bar3() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -13,7 +13,7 @@ LL | #![deny(fuzzy_provenance_casts)]
|
||||
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
|
||||
|
|
||||
LL | let dangling = (...).with_addr(16_usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| ++++++++++++++++ ~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,4 +8,11 @@ fn main() {
|
||||
|
||||
let addr_32bit = &x as *const u8 as u32;
|
||||
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
|
||||
|
||||
// don't add unnecessary parens in the suggestion
|
||||
let ptr = &x as *const u8;
|
||||
let ptr_addr = ptr as usize;
|
||||
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
|
||||
let ptr_addr_32bit = ptr as u32;
|
||||
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
|
||||
--> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
|
||||
|
|
||||
LL | let addr: usize = &x as *const u8 as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
|
||||
@ -10,14 +10,42 @@ note: the lint level is defined here
|
||||
LL | #![deny(lossy_provenance_casts)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
|
||||
help: use `.addr()` to obtain the address of a pointer
|
||||
|
|
||||
LL | let addr: usize = (&x as *const u8).addr();
|
||||
| + ~~~~~~~~
|
||||
|
||||
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
|
||||
--> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
|
||||
|
|
||||
LL | let addr_32bit = &x as *const u8 as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
|
||||
help: use `.addr()` to obtain the address of a pointer
|
||||
|
|
||||
LL | let addr_32bit = (&x as *const u8).addr() as u32;
|
||||
| + ~~~~~~~~~~~~~~~
|
||||
|
||||
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
|
||||
--> $DIR/lint-strict-provenance-lossy-casts.rs:14:20
|
||||
|
|
||||
LL | let ptr_addr = ptr as usize;
|
||||
| ^^^---------
|
||||
| |
|
||||
| help: use `.addr()` to obtain the address of a pointer: `.addr()`
|
||||
|
|
||||
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
|
||||
--> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
|
||||
|
|
||||
LL | let ptr_addr_32bit = ptr as u32;
|
||||
| ^^^-------
|
||||
| |
|
||||
| help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
|
||||
|
|
||||
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c568f32f165d86aba51ec544756c3c833acbabd7
|
||||
Subproject commit 1ef91e122775060acb1fbda2c9a366891af3ea89
|
Loading…
x
Reference in New Issue
Block a user