Skip to content

Commit

Permalink
Auto merge of rust-lang#96134 - Dylan-DPC:rollup-ejug3yq, r=Dylan-DPC
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Apr 17, 2022
2 parents 563ef23 + b47265e commit 2c28b0e
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 100 deletions.
37 changes: 20 additions & 17 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
}

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

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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() {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
49 changes: 29 additions & 20 deletions compiler/rustc_typeck/src/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};

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.span_suggestion(
self.span,
cast_span,
msg,
format!("({snippet}).addr(){scalar_cast}"),
Applicability::MaybeIncorrect
format!(".addr(){scalar_cast}"),
Applicability::MaybeIncorrect,
);
} else {
err.help(msg);
}

err.help(
"if you can't comply with strict provenance and need to expose the pointer \
provenance you can use `.expose_addr()` instead"
Expand All @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
8 changes: 7 additions & 1 deletion src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>,
Expand Down Expand Up @@ -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
Expand Down
70 changes: 66 additions & 4 deletions src/etc/htmldocck.py
Original file line number Diff line number Diff line change
Expand Up @@ -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('//'):
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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)
Expand Down
17 changes: 10 additions & 7 deletions src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

7 changes: 7 additions & 0 deletions src/test/ui/lint/lint-strict-provenance-lossy-casts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
}
Loading

0 comments on commit 2c28b0e

Please sign in to comment.