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:
bors 2022-04-17 00:44:53 +00:00
commit 2c28b0eaf9
12 changed files with 187 additions and 102 deletions

View File

@ -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() {

View File

@ -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 {

View File

@ -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"

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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() {}

View File

@ -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`.

View File

@ -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

View File

@ -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`
}

View File

@ -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