mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #92434 - matthiaskrgr:rollup-m8wuq0v, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #91519 (ast: Avoid aborts on fatal errors thrown from mutable AST visitor) - #92414 (Fix spacing of pretty printed const item without body) - #92423 (Add UI test for #92292) - #92427 (Use `UnsafeCell::get_mut()` in `core::lazy::OnceCell::get_mut()`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b60e32c828
@ -14,13 +14,14 @@ use crate::tokenstream::*;
|
||||
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
use smallvec::{smallvec, Array, SmallVec};
|
||||
use std::ops::DerefMut;
|
||||
use std::{panic, process, ptr};
|
||||
use std::{panic, ptr};
|
||||
|
||||
pub trait ExpectOne<A: Array> {
|
||||
fn expect_one(self, err: &'static str) -> A::Item;
|
||||
@ -283,23 +284,21 @@ pub trait MutVisitor: Sized {
|
||||
|
||||
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
||||
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
|
||||
/// method. Abort the program if the closure panics.
|
||||
///
|
||||
/// FIXME: Abort on panic means that any fatal error inside `visit_clobber` will abort the compiler.
|
||||
/// Instead of aborting on catching a panic we need to reset the visited node to some valid but
|
||||
/// possibly meaningless value and rethrow the panic.
|
||||
/// method.
|
||||
//
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
pub fn visit_clobber<T, F>(t: &mut T, f: F)
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
pub fn visit_clobber<T: DummyAstNode>(t: &mut T, f: impl FnOnce(T) -> T) {
|
||||
unsafe {
|
||||
// Safe because `t` is used in a read-only fashion by `read()` before
|
||||
// being overwritten by `write()`.
|
||||
let old_t = ptr::read(t);
|
||||
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
|
||||
.unwrap_or_else(|_| process::abort());
|
||||
let new_t =
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))).unwrap_or_else(|err| {
|
||||
// Set `t` to some valid but possible meaningless value,
|
||||
// and pass the fatal error further.
|
||||
ptr::write(t, T::dummy());
|
||||
panic::resume_unwind(err);
|
||||
});
|
||||
ptr::write(t, new_t);
|
||||
}
|
||||
}
|
||||
@ -1454,3 +1453,108 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
|
||||
}
|
||||
vis.visit_span(&mut visibility.span);
|
||||
}
|
||||
|
||||
/// Some value for the AST node that is valid but possibly meaningless.
|
||||
pub trait DummyAstNode {
|
||||
fn dummy() -> Self;
|
||||
}
|
||||
|
||||
impl<T> DummyAstNode for Option<T> {
|
||||
fn dummy() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
|
||||
fn dummy() -> Self {
|
||||
P(DummyAstNode::dummy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DummyAstNode for ThinVec<T> {
|
||||
fn dummy() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Item {
|
||||
fn dummy() -> Self {
|
||||
Item {
|
||||
attrs: Default::default(),
|
||||
id: DUMMY_NODE_ID,
|
||||
span: Default::default(),
|
||||
vis: Visibility {
|
||||
kind: VisibilityKind::Public,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
},
|
||||
ident: Ident::empty(),
|
||||
kind: ItemKind::ExternCrate(None),
|
||||
tokens: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Expr {
|
||||
fn dummy() -> Self {
|
||||
Expr {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: ExprKind::Err,
|
||||
span: Default::default(),
|
||||
attrs: Default::default(),
|
||||
tokens: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Ty {
|
||||
fn dummy() -> Self {
|
||||
Ty {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: TyKind::Err,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Pat {
|
||||
fn dummy() -> Self {
|
||||
Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: PatKind::Wild,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Stmt {
|
||||
fn dummy() -> Self {
|
||||
Stmt { id: DUMMY_NODE_ID, kind: StmtKind::Empty, span: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Block {
|
||||
fn dummy() -> Self {
|
||||
Block {
|
||||
stmts: Default::default(),
|
||||
id: DUMMY_NODE_ID,
|
||||
rules: BlockCheckMode::Default,
|
||||
span: Default::default(),
|
||||
tokens: Default::default(),
|
||||
could_be_bare_literal: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyAstNode for Crate {
|
||||
fn dummy() -> Self {
|
||||
Crate {
|
||||
attrs: Default::default(),
|
||||
items: Default::default(),
|
||||
span: Default::default(),
|
||||
is_placeholder: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1116,7 +1116,9 @@ impl<'a> State<'a> {
|
||||
self.print_ident(ident);
|
||||
self.word_space(":");
|
||||
self.print_type(ty);
|
||||
self.space();
|
||||
if body.is_some() {
|
||||
self.space();
|
||||
}
|
||||
self.end(); // end the head-ibox
|
||||
if let Some(body) = body {
|
||||
self.word_space("=");
|
||||
|
@ -1160,13 +1160,18 @@ macro_rules! assign_id {
|
||||
|
||||
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
fn visit_crate(&mut self, krate: &mut ast::Crate) {
|
||||
let span = krate.span;
|
||||
let empty_crate =
|
||||
|| ast::Crate { attrs: Vec::new(), items: Vec::new(), span, is_placeholder: None };
|
||||
let mut fold_crate = |krate: ast::Crate| {
|
||||
visit_clobber(krate, |krate| {
|
||||
let span = krate.span;
|
||||
let mut krate = match self.configure(krate) {
|
||||
Some(krate) => krate,
|
||||
None => return empty_crate(),
|
||||
None => {
|
||||
return ast::Crate {
|
||||
attrs: Vec::new(),
|
||||
items: Vec::new(),
|
||||
span,
|
||||
is_placeholder: None,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(attr) = self.take_first_attr(&mut krate) {
|
||||
@ -1177,10 +1182,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
|
||||
noop_visit_crate(&mut krate, self);
|
||||
krate
|
||||
};
|
||||
|
||||
// Cannot use `visit_clobber` here, see the FIXME on it.
|
||||
*krate = fold_crate(mem::replace(krate, empty_crate()));
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
|
@ -102,8 +102,7 @@ impl<T> OnceCell<T> {
|
||||
/// Returns `None` if the cell is empty.
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||
// SAFETY: Safe because we have unique access
|
||||
unsafe { &mut *self.inner.get() }.as_mut()
|
||||
self.inner.get_mut().as_mut()
|
||||
}
|
||||
|
||||
/// Sets the contents of the cell to `value`.
|
||||
|
@ -6,42 +6,42 @@ fn main() {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern "C" {
|
||||
static X: u8 ;
|
||||
static X: u8;
|
||||
type X;
|
||||
fn foo();
|
||||
pub static X: u8 ;
|
||||
pub static X: u8;
|
||||
pub type X;
|
||||
pub fn foo();
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
trait T {
|
||||
const X: u8 ;
|
||||
const X: u8;
|
||||
type X;
|
||||
fn foo();
|
||||
default const X: u8 ;
|
||||
default const X: u8;
|
||||
default type X;
|
||||
default fn foo();
|
||||
pub const X: u8 ;
|
||||
pub const X: u8;
|
||||
pub type X;
|
||||
pub fn foo();
|
||||
pub default const X: u8 ;
|
||||
pub default const X: u8;
|
||||
pub default type X;
|
||||
pub default fn foo();
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
impl T for S {
|
||||
const X: u8 ;
|
||||
const X: u8;
|
||||
type X;
|
||||
fn foo();
|
||||
default const X: u8 ;
|
||||
default const X: u8;
|
||||
default type X;
|
||||
default fn foo();
|
||||
pub const X: u8 ;
|
||||
pub const X: u8;
|
||||
pub type X;
|
||||
pub fn foo();
|
||||
pub default const X: u8 ;
|
||||
pub default const X: u8;
|
||||
pub default type X;
|
||||
pub default fn foo();
|
||||
}
|
||||
|
@ -382,13 +382,13 @@ fn test_item() {
|
||||
stringify_item!(
|
||||
static S: ();
|
||||
),
|
||||
"static S: () ;", // FIXME
|
||||
"static S: ();",
|
||||
);
|
||||
assert_eq!(
|
||||
stringify_item!(
|
||||
static mut S: ();
|
||||
),
|
||||
"static mut S: () ;",
|
||||
"static mut S: ();",
|
||||
);
|
||||
|
||||
// ItemKind::Const
|
||||
@ -402,7 +402,7 @@ fn test_item() {
|
||||
stringify_item!(
|
||||
const S: ();
|
||||
),
|
||||
"const S: () ;", // FIXME
|
||||
"const S: ();",
|
||||
);
|
||||
|
||||
// ItemKind::Fn
|
||||
|
32
src/test/ui/traits/issue-92292.rs
Normal file
32
src/test/ui/traits/issue-92292.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// check-pass
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct MyGenericType<T> {
|
||||
_marker: PhantomData<*const T>,
|
||||
}
|
||||
|
||||
pub struct MyNonGenericType;
|
||||
|
||||
impl<T> From<MyGenericType<T>> for MyNonGenericType {
|
||||
fn from(_: MyGenericType<T>) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MyTrait {
|
||||
const MY_CONSTANT: i32;
|
||||
}
|
||||
|
||||
impl<T> MyTrait for MyGenericType<T>
|
||||
where
|
||||
Self: Into<MyNonGenericType>,
|
||||
{
|
||||
const MY_CONSTANT: i32 = 1;
|
||||
}
|
||||
|
||||
impl<T> MyGenericType<T> {
|
||||
const MY_OTHER_CONSTANT: i32 = <MyGenericType<T> as MyTrait>::MY_CONSTANT;
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user