From 3e72a015662edc61bc33c1461f4392b469086433 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Mon, 28 Nov 2022 08:11:19 +0100 Subject: [PATCH 01/10] Run Windows-only tests only on Windows This removes the need to maintain a list of all other OSs which ignore the tests. --- src/test/codegen/dllimports/main.rs | 14 +------------- src/test/codegen/panic-abort-windows.rs | 13 +------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/test/codegen/dllimports/main.rs b/src/test/codegen/dllimports/main.rs index bb3134e81c930..f7978749a9173 100644 --- a/src/test/codegen/dllimports/main.rs +++ b/src/test/codegen/dllimports/main.rs @@ -1,17 +1,5 @@ // This test is for *-windows-msvc only. -// ignore-android -// ignore-dragonfly -// ignore-emscripten -// ignore-freebsd -// ignore-gnu -// ignore-haiku -// ignore-ios -// ignore-linux -// ignore-macos -// ignore-netbsd -// ignore-openbsd -// ignore-solaris -// ignore-sgx no dynamic linking +// only-windows // aux-build:dummy.rs // aux-build:wrapper.rs diff --git a/src/test/codegen/panic-abort-windows.rs b/src/test/codegen/panic-abort-windows.rs index 9ee4bfc471168..d22df6200afae 100644 --- a/src/test/codegen/panic-abort-windows.rs +++ b/src/test/codegen/panic-abort-windows.rs @@ -1,16 +1,5 @@ // This test is for *-windows-msvc only. -// ignore-android -// ignore-dragonfly -// ignore-emscripten -// ignore-freebsd -// ignore-haiku -// ignore-ios -// ignore-linux -// ignore-macos -// ignore-netbsd -// ignore-openbsd -// ignore-solaris -// ignore-sgx +// only-windows // compile-flags: -C no-prepopulate-passes -C panic=abort -O From a98254179b312f3d03c7ef57c53cdc590fc5c0b2 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sun, 27 Nov 2022 02:32:48 -0800 Subject: [PATCH 02/10] Support arbitrary `let` statements in custom mir --- library/core/src/intrinsics/mir.rs | 143 +++++++++++++++++- ...rbitrary_let.arbitrary_let.built.after.mir | 22 +++ .../mir-opt/building/custom/arbitrary_let.rs | 28 ++++ 3 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir create mode 100644 src/test/mir-opt/building/custom/arbitrary_let.rs diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 1bacdc39148a1..6e3cf974119bf 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -90,10 +90,14 @@ pub macro mir { ( $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* - $entry_block:block + { + $($entry:tt)* + } $( - $block_name:ident = $block:block + $block_name:ident = { + $($block:tt)* + } )* ) => {{ // First, we declare all basic blocks. @@ -109,11 +113,22 @@ pub macro mir { let $local_decl $(: $local_decl_ty)? ; )* + ::core::intrinsics::mir::__internal_extract_let!($($entry)*); + $( + ::core::intrinsics::mir::__internal_extract_let!($($block)*); + )* + { // Finally, the contents of the basic blocks - $entry_block; + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($entry)* } + }); $( - $block; + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($block)* } + }); )* RET @@ -121,3 +136,123 @@ pub macro mir { } }} } + +/// Helper macro that extracts the `let` declarations out of a bunch of statements. +/// +/// This macro is written using the "statement muncher" strategy. Each invocation parses the first +/// statement out of the input, does the appropriate thing with it, and then recursively calls the +/// same macro on the remainder of the input. +#[doc(hidden)] +pub macro __internal_extract_let { + // If it's a `let` like statement, keep the `let` + ( + let $var:ident $(: $ty:ty)? = $expr:expr; $($rest:tt)* + ) => { + let $var $(: $ty)?; + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, + // Otherwise, output nothing + ( + $stmt:stmt; $($rest:tt)* + ) => { + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, + ( + $expr:expr + ) => {} +} + +/// Helper macro that removes the `let` declarations from a bunch of statements. +/// +/// Because expression position macros cannot expand to statements + expressions, we need to be +/// slightly creative here. The general strategy is also statement munching as above, but the output +/// of the macro is "stored" in the subsequent macro invocation. Easiest understood via example: +/// ```text +/// invoke!( +/// { +/// { +/// x = 5; +/// } +/// { +/// let d = e; +/// Call() +/// } +/// } +/// ) +/// ``` +/// becomes +/// ```text +/// invoke!( +/// { +/// { +/// x = 5; +/// d = e; +/// } +/// { +/// Call() +/// } +/// } +/// ) +/// ``` +#[doc(hidden)] +pub macro __internal_remove_let { + // If it's a `let` like statement, remove the `let` + ( + { + { + $($already_parsed:tt)* + } + { + let $var:ident $(: $ty:ty)? = $expr:expr; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $var = $expr; + } + { + $($rest)* + } + } + )}, + // Otherwise, keep going + ( + { + { + $($already_parsed:tt)* + } + { + $stmt:stmt; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $stmt; + } + { + $($rest)* + } + } + )}, + ( + { + { + $($already_parsed:tt)* + } + { + $expr:expr + } + } + ) => { + { + $($already_parsed)* + $expr + } + }, +} diff --git a/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir b/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir new file mode 100644 index 0000000000000..d8cef6244f408 --- /dev/null +++ b/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir @@ -0,0 +1,22 @@ +// MIR for `arbitrary_let` after built + +fn arbitrary_let(_1: i32) -> i32 { + let mut _0: i32; // return place in scope 0 at $DIR/arbitrary_let.rs:+0:29: +0:32 + let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _2 = _1; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + goto -> bb2; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + } + + bb1: { + _0 = _3; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + return; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + } + + bb2: { + _3 = _2; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + goto -> bb1; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + } +} diff --git a/src/test/mir-opt/building/custom/arbitrary_let.rs b/src/test/mir-opt/building/custom/arbitrary_let.rs new file mode 100644 index 0000000000000..776df3151ffd7 --- /dev/null +++ b/src/test/mir-opt/building/custom/arbitrary_let.rs @@ -0,0 +1,28 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; +use core::ptr::{addr_of, addr_of_mut}; + +// EMIT_MIR arbitrary_let.arbitrary_let.built.after.mir +#[custom_mir(dialect = "built")] +fn arbitrary_let(x: i32) -> i32 { + mir!( + { + let y = x; + Goto(second) + } + third = { + RET = z; + Return() + } + second = { + let z = y; + Goto(third) + } + ) +} + +fn main() { + assert_eq!(arbitrary_let(5), 5); +} From 757810031764e4a0fce2a21eb5c8ba208ff7f6c1 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sun, 27 Nov 2022 18:48:04 -0800 Subject: [PATCH 03/10] Support most constant kinds in custom mir --- .../rustc_mir_build/src/build/custom/parse.rs | 13 +- .../src/build/custom/parse/instruction.rs | 24 ++- .../src/build/expr/as_constant.rs | 137 +++++++++--------- library/core/src/intrinsics/mir.rs | 29 ++++ .../custom/consts.consts.built.after.mir | 22 +++ src/test/mir-opt/building/custom/consts.rs | 23 +++ 6 files changed, 170 insertions(+), 78 deletions(-) create mode 100644 src/test/mir-opt/building/custom/consts.consts.built.after.mir create mode 100644 src/test/mir-opt/building/custom/consts.rs diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 52cb0a4826d07..b2c5aead430da 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -23,6 +23,7 @@ macro_rules! parse_by_kind { ( $self:ident, $expr_id:expr, + $expr_name:pat, $expected:literal, $( @call($name:literal, $args:ident) => $call_expr:expr, @@ -33,6 +34,8 @@ macro_rules! parse_by_kind { ) => {{ let expr_id = $self.preparse($expr_id); let expr = &$self.thir[expr_id]; + debug!("Trying to parse {:?} as {}", expr.kind, $expected); + let $expr_name = expr; match &expr.kind { $( ExprKind::Call { ty, fun: _, args: $args, .. } if { @@ -137,10 +140,10 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { /// This allows us to easily parse the basic blocks declarations, local declarations, and /// basic block definitions in order. pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> { - let body = parse_by_kind!(self, expr_id, "whole body", + let body = parse_by_kind!(self, expr_id, _, "whole body", ExprKind::Block { block } => self.thir[*block].expr.unwrap(), ); - let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls", + let (block_decls, rest) = parse_by_kind!(self, body, _, "body with block decls", ExprKind::Block { block } => { let block = &self.thir[*block]; (&block.stmts, block.expr.unwrap()) @@ -148,7 +151,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); self.parse_block_decls(block_decls.iter().copied())?; - let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls", + let (local_decls, rest) = parse_by_kind!(self, rest, _, "body with local decls", ExprKind::Block { block } => { let block = &self.thir[*block]; (&block.stmts, block.expr.unwrap()) @@ -156,7 +159,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); self.parse_local_decls(local_decls.iter().copied())?; - let block_defs = parse_by_kind!(self, rest, "body with block defs", + let block_defs = parse_by_kind!(self, rest, _, "body with block defs", ExprKind::Block { block } => &self.thir[*block].stmts, ); for (i, block_def) in block_defs.iter().enumerate() { @@ -223,7 +226,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } fn parse_block_def(&self, expr_id: ExprId) -> PResult> { - let block = parse_by_kind!(self, expr_id, "basic block", + let block = parse_by_kind!(self, expr_id, _, "basic block", ExprKind::Block { block } => &self.thir[*block], ); diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 6d6176584f5f4..cd809807a1267 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -4,7 +4,7 @@ use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, "statement", + parse_by_kind!(self, expr_id, _, "statement", @call("mir_retag", args) => { Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) }, @@ -20,7 +20,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, "terminator", + parse_by_kind!(self, expr_id, _, "terminator", @call("mir_return", _args) => { Ok(TerminatorKind::Return) }, @@ -31,7 +31,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, "rvalue", + parse_by_kind!(self, expr_id, _, "rvalue", ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), @@ -43,14 +43,24 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } fn parse_operand(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, "operand", + parse_by_kind!(self, expr_id, expr, "operand", @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), + ExprKind::Literal { .. } + | ExprKind::NamedConst { .. } + | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } + | ExprKind::ConstParam { .. } + | ExprKind::ConstBlock { .. } => { + Ok(Operand::Constant(Box::new( + crate::build::expr::as_constant::as_constant_inner(expr, |_| None, self.tcx) + ))) + }, _ => self.parse_place(expr_id).map(Operand::Copy), ) } fn parse_place(&self, expr_id: ExprId) -> PResult> { - parse_by_kind!(self, expr_id, "place", + parse_by_kind!(self, expr_id, _, "place", ExprKind::Deref { arg } => Ok( self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx) ), @@ -59,13 +69,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } fn parse_local(&self, expr_id: ExprId) -> PResult { - parse_by_kind!(self, expr_id, "local", + parse_by_kind!(self, expr_id, _, "local", ExprKind::VarRef { id } => Ok(self.local_map[id]), ) } fn parse_block(&self, expr_id: ExprId) -> PResult { - parse_by_kind!(self, expr_id, "basic block", + parse_by_kind!(self, expr_id, _, "basic block", ExprKind::VarRef { id } => Ok(self.block_map[id]), ) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 32c0207cb680c..717c62315745b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -8,7 +8,9 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::mir::*; use rustc_middle::thir::*; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt}; +use rustc_middle::ty::{ + self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex, +}; use rustc_span::DUMMY_SP; use rustc_target::abi::Size; @@ -19,84 +21,87 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let this = self; let tcx = this.tcx; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; - match *kind { + match kind { ExprKind::Scope { region_scope: _, lint_level: _, value } => { - this.as_constant(&this.thir[value]) - } - ExprKind::Literal { lit, neg } => { - let literal = - match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { - Ok(c) => c, - Err(LitToConstError::Reported(guar)) => { - ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar)) - } - Err(LitToConstError::TypeError) => { - bug!("encountered type error in `lit_to_mir_constant") - } - }; - - Constant { span, user_ty: None, literal } + this.as_constant(&this.thir[*value]) } - ExprKind::NonHirLiteral { lit, ref user_ty } => { - let user_ty = user_ty.as_ref().map(|user_ty| { - this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { + _ => as_constant_inner( + expr, + |user_ty| { + Some(this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span, user_ty: user_ty.clone(), inferred_ty: ty, - }) - }); - let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); + })) + }, + tcx, + ), + } + } +} - Constant { span, user_ty: user_ty, literal } - } - ExprKind::ZstLiteral { ref user_ty } => { - let user_ty = user_ty.as_ref().map(|user_ty| { - this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span, - user_ty: user_ty.clone(), - inferred_ty: ty, - }) - }); - let literal = ConstantKind::Val(ConstValue::ZeroSized, ty); +pub fn as_constant_inner<'tcx>( + expr: &Expr<'tcx>, + push_cuta: impl FnMut(&Box>) -> Option, + tcx: TyCtxt<'tcx>, +) -> Constant<'tcx> { + let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; + match *kind { + ExprKind::Literal { lit, neg } => { + let literal = + match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { + Ok(c) => c, + Err(LitToConstError::Reported(guar)) => { + ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar)) + } + Err(LitToConstError::TypeError) => { + bug!("encountered type error in `lit_to_mir_constant") + } + }; - Constant { span, user_ty: user_ty, literal } - } - ExprKind::NamedConst { def_id, substs, ref user_ty } => { - let user_ty = user_ty.as_ref().map(|user_ty| { - this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span, - user_ty: user_ty.clone(), - inferred_ty: ty, - }) - }); + Constant { span, user_ty: None, literal } + } + ExprKind::NonHirLiteral { lit, ref user_ty } => { + let user_ty = user_ty.as_ref().map(push_cuta).flatten(); - let uneval = - mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); - let literal = ConstantKind::Unevaluated(uneval, ty); + let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); - Constant { user_ty, span, literal } - } - ExprKind::ConstParam { param, def_id: _ } => { - let const_param = tcx.mk_const(param, expr.ty); - let literal = ConstantKind::Ty(const_param); + Constant { span, user_ty: user_ty, literal } + } + ExprKind::ZstLiteral { ref user_ty } => { + let user_ty = user_ty.as_ref().map(push_cuta).flatten(); - Constant { user_ty: None, span, literal } - } - ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = - mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); - let literal = ConstantKind::Unevaluated(uneval, ty); + let literal = ConstantKind::Val(ConstValue::ZeroSized, ty); - Constant { user_ty: None, span, literal } - } - ExprKind::StaticRef { alloc_id, ty, .. } => { - let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); - let literal = ConstantKind::Val(const_val, ty); + Constant { span, user_ty: user_ty, literal } + } + ExprKind::NamedConst { def_id, substs, ref user_ty } => { + let user_ty = user_ty.as_ref().map(push_cuta).flatten(); - Constant { span, user_ty: None, literal } - } - _ => span_bug!(span, "expression is not a valid constant {:?}", kind), + let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); + let literal = ConstantKind::Unevaluated(uneval, ty); + + Constant { user_ty, span, literal } + } + ExprKind::ConstParam { param, def_id: _ } => { + let const_param = tcx.mk_const(ty::ConstKind::Param(param), expr.ty); + let literal = ConstantKind::Ty(const_param); + + Constant { user_ty: None, span, literal } + } + ExprKind::ConstBlock { did: def_id, substs } => { + let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); + let literal = ConstantKind::Unevaluated(uneval, ty); + + Constant { user_ty: None, span, literal } + } + ExprKind::StaticRef { alloc_id, ty, .. } => { + let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); + let literal = ConstantKind::Val(const_val, ty); + + Constant { span, user_ty: None, literal } } + _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 6e3cf974119bf..18011aa5e98a1 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -151,6 +151,13 @@ pub macro __internal_extract_let { let $var $(: $ty)?; ::core::intrinsics::mir::__internal_extract_let!($($rest)*); }, + // Due to #86730, we have to handle const blocks separately + ( + let $var:ident $(: $ty:ty)? = const $block:block; $($rest:tt)* + ) => { + let $var $(: $ty)?; + ::core::intrinsics::mir::__internal_extract_let!($($rest)*); + }, // Otherwise, output nothing ( $stmt:stmt; $($rest:tt)* @@ -218,6 +225,28 @@ pub macro __internal_remove_let { } } )}, + // Due to #86730 , we have to handle const blocks separately + ( + { + { + $($already_parsed:tt)* + } + { + let $var:ident $(: $ty:ty)? = const $block:block; + $($rest:tt)* + } + } + ) => { ::core::intrinsics::mir::__internal_remove_let!( + { + { + $($already_parsed)* + $var = const $block; + } + { + $($rest)* + } + } + )}, // Otherwise, keep going ( { diff --git a/src/test/mir-opt/building/custom/consts.consts.built.after.mir b/src/test/mir-opt/building/custom/consts.consts.built.after.mir new file mode 100644 index 0000000000000..e384cdeb465b9 --- /dev/null +++ b/src/test/mir-opt/building/custom/consts.consts.built.after.mir @@ -0,0 +1,22 @@ +// MIR for `consts` after built + +fn consts() -> () { + let mut _0: (); // return place in scope 0 at $DIR/consts.rs:10:27: 10:27 + let mut _1: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _2: i8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _3: u32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _4: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _5: fn() {consts::<10>}; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _1 = const 5_u8; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + _2 = const _; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + _3 = const C; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + _4 = const _; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + _5 = consts::<10>; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + // mir::Constant + // + span: $DIR/consts.rs:16:18: 16:30 + // + literal: Const { ty: fn() {consts::<10>}, val: Value() } + return; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + } +} diff --git a/src/test/mir-opt/building/custom/consts.rs b/src/test/mir-opt/building/custom/consts.rs new file mode 100644 index 0000000000000..98b087f1e585a --- /dev/null +++ b/src/test/mir-opt/building/custom/consts.rs @@ -0,0 +1,23 @@ +#![feature(custom_mir, core_intrinsics, inline_const)] + +extern crate core; +use core::intrinsics::mir::*; + +const D: i32 = 5; + +// EMIT_MIR consts.consts.built.after.mir +#[custom_mir(dialect = "built")] +fn consts() { + mir!({ + let _a = 5_u8; + let _b = const { 5_i8 }; + let _c = C; + let _d = D; + let _e = consts::<10>; + Return() + }) +} + +fn main() { + consts::<5>(); +} From 52ce1f7697924685ca7abf09be540bb21df46104 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sun, 27 Nov 2022 19:25:55 -0800 Subject: [PATCH 04/10] Support statics in custom mir --- .../src/build/custom/parse/instruction.rs | 23 ++++++++++++++++ library/core/src/intrinsics/mir.rs | 2 ++ src/test/mir-opt/building/custom/consts.rs | 13 +++++++++ .../custom/consts.statics.built.after.mir | 27 +++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/mir-opt/building/custom/consts.statics.built.after.mir diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index cd809807a1267..03206af33bfb5 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -1,3 +1,4 @@ +use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::{mir::*, thir::*, ty}; use super::{parse_by_kind, PResult, ParseCtxt}; @@ -45,6 +46,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), + @call("mir_static", args) => self.parse_static(args[0]), + @call("mir_static_mut", args) => self.parse_static(args[0]), ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } @@ -79,4 +82,24 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::VarRef { id } => Ok(self.block_map[id]), ) } + + fn parse_static(&self, expr_id: ExprId) -> PResult> { + let expr_id = parse_by_kind!(self, expr_id, _, "static", + ExprKind::Deref { arg } => *arg, + ); + + parse_by_kind!(self, expr_id, expr, "static", + ExprKind::StaticRef { alloc_id, ty, .. } => { + let const_val = + ConstValue::Scalar(Scalar::from_pointer((*alloc_id).into(), &self.tcx)); + let literal = ConstantKind::Val(const_val, *ty); + + Ok(Operand::Constant(Box::new(Constant { + span: expr.span, + user_ty: None, + literal + }))) + }, + ) + } } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 18011aa5e98a1..8ba1c122884ca 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -80,6 +80,8 @@ define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_retag", fn Retag(place: T)); define!("mir_retag_raw", fn RetagRaw(place: T)); define!("mir_move", fn Move(place: T) -> T); +define!("mir_static", fn Static(s: T) -> &'static T); +define!("mir_static_mut", fn StaticMut(s: T) -> *mut T); /// Convenience macro for generating custom MIR. /// diff --git a/src/test/mir-opt/building/custom/consts.rs b/src/test/mir-opt/building/custom/consts.rs index 98b087f1e585a..ff4fe1a93246e 100644 --- a/src/test/mir-opt/building/custom/consts.rs +++ b/src/test/mir-opt/building/custom/consts.rs @@ -18,6 +18,19 @@ fn consts() { }) } +static S: i32 = 5; +static mut T: i32 = 10; +// EMIT_MIR consts.statics.built.after.mir +#[custom_mir(dialect = "built")] +fn statics() { + mir!({ + let _a: &i32 = Static(S); + let _b: *mut i32 = StaticMut(T); + Return() + }) +} + fn main() { consts::<5>(); + statics(); } diff --git a/src/test/mir-opt/building/custom/consts.statics.built.after.mir b/src/test/mir-opt/building/custom/consts.statics.built.after.mir new file mode 100644 index 0000000000000..a193af729d565 --- /dev/null +++ b/src/test/mir-opt/building/custom/consts.statics.built.after.mir @@ -0,0 +1,27 @@ +// MIR for `statics` after built + +fn statics() -> () { + let mut _0: (); // return place in scope 0 at $DIR/consts.rs:25:14: 25:14 + let mut _1: &i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _1 = const {alloc1: &i32}; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + // mir::Constant + // + span: $DIR/consts.rs:27:31: 27:32 + // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } + _2 = const {alloc2: *mut i32}; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + // mir::Constant + // + span: $DIR/consts.rs:28:38: 28:39 + // + literal: Const { ty: *mut i32, val: Value(Scalar(alloc2)) } + return; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + } +} + +alloc2 (static: T, size: 4, align: 4) { + 0a 00 00 00 │ .... +} + +alloc1 (static: S, size: 4, align: 4) { + 05 00 00 00 │ .... +} From 5a34dbf193ac8cfb7dbe53b354614f2622f5682c Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sun, 27 Nov 2022 21:23:39 -0800 Subject: [PATCH 05/10] Improve spans in custom mir --- compiler/rustc_mir_build/src/build/custom/mod.rs | 4 ++-- compiler/rustc_mir_build/src/build/custom/parse.rs | 12 ++++++++++-- compiler/rustc_mir_build/src/build/mod.rs | 2 +- .../arbitrary_let.arbitrary_let.built.after.mir | 12 ++++++------ .../building/custom/consts.consts.built.after.mir | 14 +++++++------- .../building/custom/consts.statics.built.after.mir | 8 ++++---- .../custom/references.immut_ref.built.after.mir | 10 +++++----- .../custom/references.mut_ref.built.after.mir | 10 +++++----- .../custom/simple_assign.simple.built.after.mir | 10 +++++----- .../simple_assign.simple_ref.built.after.mir | 4 ++-- 10 files changed, 47 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 68d8766c90734..2412824efeb75 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -74,7 +74,7 @@ pub(super) fn build_custom_mir<'tcx>( let mut pctxt = ParseCtxt { tcx, thir, - source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + source_scope: OUTERMOST_SOURCE_SCOPE, body: &mut body, local_map: FxHashMap::default(), block_map: FxHashMap::default(), @@ -128,7 +128,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { struct ParseCtxt<'tcx, 'body> { tcx: TyCtxt<'tcx>, thir: &'body Thir<'tcx>, - source_info: SourceInfo, + source_scope: SourceScope, body: &'body mut Body<'tcx>, local_map: FxHashMap, diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index b2c5aead430da..d72770e70c7ec 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -233,15 +233,23 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let mut data = BasicBlockData::new(None); for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; + let span = self.thir[stmt].span; let statement = self.parse_statement(stmt)?; - data.statements.push(Statement { source_info: self.source_info, kind: statement }); + data.statements.push(Statement { + source_info: SourceInfo { span, scope: self.source_scope }, + kind: statement, + }); } let Some(trailing) = block.expr else { return Err(self.expr_error(expr_id, "terminator")) }; + let span = self.thir[trailing].span; let terminator = self.parse_terminator(trailing)?; - data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator }); + data.terminator = Some(Terminator { + source_info: SourceInfo { span, scope: self.source_scope }, + kind: terminator, + }); Ok(data) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0b76122913ebe..b456e2aa37a27 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -492,7 +492,7 @@ fn construct_fn<'tcx>( arguments, return_ty, return_ty_span, - span, + span_with_body, custom_mir_attr, ); } diff --git a/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir b/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir index d8cef6244f408..20dd251e7e308 100644 --- a/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir +++ b/src/test/mir-opt/building/custom/arbitrary_let.arbitrary_let.built.after.mir @@ -6,17 +6,17 @@ fn arbitrary_let(_1: i32) -> i32 { let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _2 = _1; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 - goto -> bb2; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + _2 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + goto -> bb2; // scope 0 at $DIR/arbitrary_let.rs:+4:13: +4:25 } bb1: { - _0 = _3; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 - return; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + _0 = _3; // scope 0 at $DIR/arbitrary_let.rs:+7:13: +7:20 + return; // scope 0 at $DIR/arbitrary_let.rs:+8:13: +8:21 } bb2: { - _3 = _2; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 - goto -> bb1; // scope 0 at $DIR/arbitrary_let.rs:+0:1: +0:32 + _3 = _2; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + goto -> bb1; // scope 0 at $DIR/arbitrary_let.rs:+12:13: +12:24 } } diff --git a/src/test/mir-opt/building/custom/consts.consts.built.after.mir b/src/test/mir-opt/building/custom/consts.consts.built.after.mir index e384cdeb465b9..ba753cfc20ca2 100644 --- a/src/test/mir-opt/building/custom/consts.consts.built.after.mir +++ b/src/test/mir-opt/building/custom/consts.consts.built.after.mir @@ -1,7 +1,7 @@ // MIR for `consts` after built fn consts() -> () { - let mut _0: (); // return place in scope 0 at $DIR/consts.rs:10:27: 10:27 + let mut _0: (); // return place in scope 0 at $DIR/consts.rs:+0:27: +0:27 let mut _1: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL let mut _2: i8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL let mut _3: u32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL @@ -9,14 +9,14 @@ fn consts() -> () { let mut _5: fn() {consts::<10>}; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _1 = const 5_u8; // scope 0 at $DIR/consts.rs:+0:1: +0:26 - _2 = const _; // scope 0 at $DIR/consts.rs:+0:1: +0:26 - _3 = const C; // scope 0 at $DIR/consts.rs:+0:1: +0:26 - _4 = const _; // scope 0 at $DIR/consts.rs:+0:1: +0:26 - _5 = consts::<10>; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + _1 = const 5_u8; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + _2 = const _; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + _3 = const C; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + _4 = const _; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + _5 = consts::<10>; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL // mir::Constant // + span: $DIR/consts.rs:16:18: 16:30 // + literal: Const { ty: fn() {consts::<10>}, val: Value() } - return; // scope 0 at $DIR/consts.rs:+0:1: +0:26 + return; // scope 0 at $DIR/consts.rs:+7:9: +7:17 } } diff --git a/src/test/mir-opt/building/custom/consts.statics.built.after.mir b/src/test/mir-opt/building/custom/consts.statics.built.after.mir index a193af729d565..ee768e263ecdf 100644 --- a/src/test/mir-opt/building/custom/consts.statics.built.after.mir +++ b/src/test/mir-opt/building/custom/consts.statics.built.after.mir @@ -1,20 +1,20 @@ // MIR for `statics` after built fn statics() -> () { - let mut _0: (); // return place in scope 0 at $DIR/consts.rs:25:14: 25:14 + let mut _0: (); // return place in scope 0 at $DIR/consts.rs:+0:14: +0:14 let mut _1: &i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _1 = const {alloc1: &i32}; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + _1 = const {alloc1: &i32}; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL // mir::Constant // + span: $DIR/consts.rs:27:31: 27:32 // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _2 = const {alloc2: *mut i32}; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + _2 = const {alloc2: *mut i32}; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL // mir::Constant // + span: $DIR/consts.rs:28:38: 28:39 // + literal: Const { ty: *mut i32, val: Value(Scalar(alloc2)) } - return; // scope 0 at $DIR/consts.rs:+0:1: +0:13 + return; // scope 0 at $DIR/consts.rs:+4:9: +4:17 } } diff --git a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir index 4a5ddde4081e2..4d38d45c0f479 100644 --- a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir +++ b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir @@ -5,10 +5,10 @@ fn immut_ref(_1: &i32) -> &i32 { let mut _2: *const i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:34 - Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:34 - _0 = &(*_2); // scope 0 at $DIR/references.rs:+0:1: +0:34 - Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:34 - return; // scope 0 at $DIR/references.rs:+0:1: +0:34 + _2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+5:13: +5:29 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+6:13: +6:24 + _0 = &(*_2); // scope 0 at $DIR/references.rs:+7:13: +7:23 + Retag(_0); // scope 0 at $DIR/references.rs:+8:13: +8:23 + return; // scope 0 at $DIR/references.rs:+9:13: +9:21 } } diff --git a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir index ec8509f69d14e..01bc8a9cd3580 100644 --- a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir +++ b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir @@ -5,10 +5,10 @@ fn mut_ref(_1: &mut i32) -> &mut i32 { let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:40 - Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:40 - _0 = &mut (*_2); // scope 0 at $DIR/references.rs:+0:1: +0:40 - Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:40 - return; // scope 0 at $DIR/references.rs:+0:1: +0:40 + _2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+5:13: +5:33 + Retag([raw] _2); // scope 0 at $DIR/references.rs:+6:13: +6:24 + _0 = &mut (*_2); // scope 0 at $DIR/references.rs:+7:13: +7:26 + Retag(_0); // scope 0 at $DIR/references.rs:+8:13: +8:23 + return; // scope 0 at $DIR/references.rs:+9:13: +9:21 } } diff --git a/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir index a5a2834c2e1bf..d7560fde69c95 100644 --- a/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir +++ b/src/test/mir-opt/building/custom/simple_assign.simple.built.after.mir @@ -6,13 +6,13 @@ fn simple(_1: i32) -> i32 { let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL bb0: { - _2 = _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 - goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + _2 = _1; // scope 0 at $DIR/simple_assign.rs:+6:13: +6:22 + goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+7:13: +7:23 } bb1: { - _3 = move _2; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 - _0 = _3; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 - return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29 + _3 = move _2; // scope 0 at $DIR/simple_assign.rs:+11:13: +11:32 + _0 = _3; // scope 0 at $DIR/simple_assign.rs:+12:13: +12:24 + return; // scope 0 at $DIR/simple_assign.rs:+13:13: +13:21 } } diff --git a/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir index 6c90f0130a2e6..2b0e8f1047b53 100644 --- a/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir +++ b/src/test/mir-opt/building/custom/simple_assign.simple_ref.built.after.mir @@ -4,7 +4,7 @@ fn simple_ref(_1: &mut i32) -> &mut i32 { let mut _0: &mut i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43 bb0: { - _0 = move _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 - return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43 + _0 = move _1; // scope 0 at $DIR/simple_assign.rs:+2:9: +2:22 + return; // scope 0 at $DIR/simple_assign.rs:+3:9: +3:17 } } From 97f0c58b37ba7e1bd32ddf1c4558884302f68194 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 30 Nov 2022 13:31:11 +0900 Subject: [PATCH 06/10] report literal errors when `token_lit` has errors --- compiler/rustc_expand/src/base.rs | 6 +++++- src/test/ui/macros/issue-105011.rs | 3 +++ src/test/ui/macros/issue-105011.stderr | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/macros/issue-105011.rs create mode 100644 src/test/ui/macros/issue-105011.stderr diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 8955abebf1e0f..fc74182b87256 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -16,6 +16,7 @@ use rustc_errors::{ use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics}; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; +use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; @@ -1245,7 +1246,10 @@ pub fn expr_to_spanned_string<'a>( Some((err, true)) } Ok(ast::LitKind::Err) => None, - Err(_) => None, + Err(err) => { + report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span); + None + } _ => Some((cx.struct_span_err(expr.span, err_msg), false)), }, ast::ExprKind::Err => None, diff --git a/src/test/ui/macros/issue-105011.rs b/src/test/ui/macros/issue-105011.rs new file mode 100644 index 0000000000000..da12c381464e1 --- /dev/null +++ b/src/test/ui/macros/issue-105011.rs @@ -0,0 +1,3 @@ +fn main() { + println!(""y); //~ ERROR suffixes on string literals are invalid +} diff --git a/src/test/ui/macros/issue-105011.stderr b/src/test/ui/macros/issue-105011.stderr new file mode 100644 index 0000000000000..e898af7faa30a --- /dev/null +++ b/src/test/ui/macros/issue-105011.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/issue-105011.rs:2:14 + | +LL | println!(""y); + | ^^^ invalid suffix `y` + +error: aborting due to previous error + From 02eaecc767b5f8deb1f1e3ddc7c0a793b6e7ff2d Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 30 Nov 2022 13:31:35 +0900 Subject: [PATCH 07/10] avoid an unnecessary `&str` to `String` conversion --- compiler/rustc_session/src/errors.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 2f7055e3cc5e8..9aa8a06c6d36e 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -197,12 +197,12 @@ pub enum UnleashedFeatureHelp { #[derive(Diagnostic)] #[diag(session_invalid_literal_suffix)] -pub(crate) struct InvalidLiteralSuffix { +pub(crate) struct InvalidLiteralSuffix<'a> { #[primary_span] #[label] pub span: Span, // FIXME(#100717) - pub kind: String, + pub kind: &'a str, pub suffix: Symbol, } @@ -311,11 +311,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: LitError::LexerError => {} LitError::InvalidSuffix => { if let Some(suffix) = suffix { - sess.emit_err(InvalidLiteralSuffix { - span, - kind: format!("{}", kind.descr()), - suffix, - }); + sess.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }); } } LitError::InvalidIntSuffix => { From 2405e607696698e5d9cf0d2eec46bd3fbc339e5b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 30 Nov 2022 09:00:02 -0700 Subject: [PATCH 08/10] rustdoc: remove redundant CSS `div.desc { display: block }` DIV tags have block display by default. It is from when this rule used to target a SPAN tag, but became redundant in 4bd6748bb9b73c210558498070ae0b7ed8193ddf. --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index de882e66f43de..85bd73db52472 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -896,7 +896,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - display: block; } .search-results a:hover, From 56126fb149ea810db234e210893833e97a5c8e36 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 30 Nov 2022 19:13:09 +0330 Subject: [PATCH 09/10] Extract llvm datalayout parsing out of spec module --- compiler/rustc_abi/src/lib.rs | 96 +++++++++++++++++++++++++++ compiler/rustc_target/src/spec/mod.rs | 92 +------------------------ 2 files changed, 98 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4f4a4bf314f14..85693259cd015 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -211,6 +211,102 @@ pub enum TargetDataLayoutErrors<'a> { } impl TargetDataLayout { + /// Parse data layout from an [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout) + /// + /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be + /// determined from llvm string. + pub fn parse_from_llvm_datalayout_string<'a>( + input: &'a str, + ) -> Result> { + // Parse an address space index from a string. + let parse_address_space = |s: &'a str, cause: &'a str| { + s.parse::().map(AddressSpace).map_err(|err| { + TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err } + }) + }; + + // Parse a bit count from a string. + let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| { + s.parse::().map_err(|err| TargetDataLayoutErrors::InvalidBits { + kind, + bit: s, + cause, + err, + }) + }; + + // Parse a size string. + let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); + + // Parse an alignment string. + let align = |s: &[&'a str], cause: &'a str| { + if s.is_empty() { + return Err(TargetDataLayoutErrors::MissingAlignment { cause }); + } + let align_from_bits = |bits| { + Align::from_bits(bits) + .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) + }; + let abi = parse_bits(s[0], "alignment", cause)?; + let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; + Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? }) + }; + + let mut dl = TargetDataLayout::default(); + let mut i128_align_src = 64; + for spec in input.split('-') { + let spec_parts = spec.split(':').collect::>(); + + match &*spec_parts { + ["e"] => dl.endian = Endian::Little, + ["E"] => dl.endian = Endian::Big, + [p] if p.starts_with('P') => { + dl.instruction_address_space = parse_address_space(&p[1..], "P")? + } + ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, + ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?, + ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?, + [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { + dl.pointer_size = size(s, p)?; + dl.pointer_align = align(a, p)?; + } + [s, ref a @ ..] if s.starts_with('i') => { + let Ok(bits) = s[1..].parse::() else { + size(&s[1..], "i")?; // For the user error. + continue; + }; + let a = align(a, s)?; + match bits { + 1 => dl.i1_align = a, + 8 => dl.i8_align = a, + 16 => dl.i16_align = a, + 32 => dl.i32_align = a, + 64 => dl.i64_align = a, + _ => {} + } + if bits >= i128_align_src && bits <= 128 { + // Default alignment for i128 is decided by taking the alignment of + // largest-sized i{64..=128}. + i128_align_src = bits; + dl.i128_align = a; + } + } + [s, ref a @ ..] if s.starts_with('v') => { + let v_size = size(&s[1..], "v")?; + let a = align(a, s)?; + if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { + v.1 = a; + continue; + } + // No existing entry, add a new one. + dl.vector_align.push((v_size, a)); + } + _ => {} // Ignore everything else. + } + } + Ok(dl) + } + /// Returns exclusive upper bound on object size. /// /// The theoretical maximum object size is defined as the maximum positive `isize` value. diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0f8cfd7f5385c..78315afa75956 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -35,10 +35,7 @@ //! to the list specified by the target, rather than replace. use crate::abi::call::Conv; -use crate::abi::{ - AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size, TargetDataLayout, - TargetDataLayoutErrors, -}; +use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors}; use crate::json::{Json, ToJson}; use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; @@ -1322,92 +1319,7 @@ pub struct Target { impl Target { pub fn parse_data_layout<'a>(&'a self) -> Result> { - // Parse an address space index from a string. - let parse_address_space = |s: &'a str, cause: &'a str| { - s.parse::().map(AddressSpace).map_err(|err| { - TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err } - }) - }; - - // Parse a bit count from a string. - let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| { - s.parse::().map_err(|err| TargetDataLayoutErrors::InvalidBits { - kind, - bit: s, - cause, - err, - }) - }; - - // Parse a size string. - let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); - - // Parse an alignment string. - let align = |s: &[&'a str], cause: &'a str| { - if s.is_empty() { - return Err(TargetDataLayoutErrors::MissingAlignment { cause }); - } - let align_from_bits = |bits| { - Align::from_bits(bits) - .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) - }; - let abi = parse_bits(s[0], "alignment", cause)?; - let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?; - Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? }) - }; - - let mut dl = TargetDataLayout::default(); - let mut i128_align_src = 64; - for spec in self.data_layout.split('-') { - let spec_parts = spec.split(':').collect::>(); - - match &*spec_parts { - ["e"] => dl.endian = Endian::Little, - ["E"] => dl.endian = Endian::Big, - [p] if p.starts_with('P') => { - dl.instruction_address_space = parse_address_space(&p[1..], "P")? - } - ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, - ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?, - ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?, - [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { - dl.pointer_size = size(s, p)?; - dl.pointer_align = align(a, p)?; - } - [s, ref a @ ..] if s.starts_with('i') => { - let Ok(bits) = s[1..].parse::() else { - size(&s[1..], "i")?; // For the user error. - continue; - }; - let a = align(a, s)?; - match bits { - 1 => dl.i1_align = a, - 8 => dl.i8_align = a, - 16 => dl.i16_align = a, - 32 => dl.i32_align = a, - 64 => dl.i64_align = a, - _ => {} - } - if bits >= i128_align_src && bits <= 128 { - // Default alignment for i128 is decided by taking the alignment of - // largest-sized i{64..=128}. - i128_align_src = bits; - dl.i128_align = a; - } - } - [s, ref a @ ..] if s.starts_with('v') => { - let v_size = size(&s[1..], "v")?; - let a = align(a, s)?; - if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { - v.1 = a; - continue; - } - // No existing entry, add a new one. - dl.vector_align.push((v_size, a)); - } - _ => {} // Ignore everything else. - } - } + let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?; // Perform consistency checks against the Target information. if dl.endian != self.endian { From ab264ae61217df6a2b66c8f2bbff294b793a1f94 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 30 Nov 2022 21:17:00 +0000 Subject: [PATCH 10/10] Fix ICE from #105101 --- .../src/deriving/default.rs | 2 +- src/test/ui/deriving/issue-105101.rs | 9 ++++++ src/test/ui/deriving/issue-105101.stderr | 29 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/deriving/issue-105101.rs create mode 100644 src/test/ui/deriving/issue-105101.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 93f297ad88b5f..bd5c6e42a19f3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -146,7 +146,7 @@ fn extract_default_variant<'a>( let suggestion = default_variants .iter() .filter_map(|v| { - if v.ident == variant.ident { + if v.span == variant.span { None } else { Some((cx.sess.find_by_name(&v.attrs, kw::Default)?.span, String::new())) diff --git a/src/test/ui/deriving/issue-105101.rs b/src/test/ui/deriving/issue-105101.rs new file mode 100644 index 0000000000000..1a377feb91948 --- /dev/null +++ b/src/test/ui/deriving/issue-105101.rs @@ -0,0 +1,9 @@ +// compile-flags: --crate-type=lib + +#[derive(Default)] //~ ERROR multiple declared defaults +enum E { + #[default] + A, + #[default] + A, //~ ERROR defined multiple times +} diff --git a/src/test/ui/deriving/issue-105101.stderr b/src/test/ui/deriving/issue-105101.stderr new file mode 100644 index 0000000000000..0f6f67043f32f --- /dev/null +++ b/src/test/ui/deriving/issue-105101.stderr @@ -0,0 +1,29 @@ +error: multiple declared defaults + --> $DIR/issue-105101.rs:3:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | A, + | - first default +LL | #[default] +LL | A, + | - additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-105101.rs:8:5 + | +LL | A, + | - previous definition of the type `A` here +LL | #[default] +LL | A, + | ^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this enum + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`.