Auto merge of #115354 - matthiaskrgr:rollup-4cotcxz, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #111580 (Don't ICE on layout computation failure)
 - #114923 (doc: update lld-flavor ref)
 - #115174 (tests: add test for #67992)
 - #115187 (Add new interface to smir)
 - #115300 (Tweaks and improvements on SMIR around generics_of and predicates_of)
 - #115340 (some more is_zst that should be is_1zst)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-08-29 19:24:47 +00:00
commit 83995f320c
21 changed files with 205 additions and 119 deletions

View File

@ -4335,8 +4335,11 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_driver",
"rustc_hir",
"rustc_interface",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
"scoped-tls",

View File

@ -480,7 +480,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
self.0.sess.span_fatal(span, err.to_string())
} else {
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
self.0.sess.span_fatal(span, format!("failed to get layout for `{}`: {}", ty, err))
}
}
}

View File

@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::{
BaseTypeMethods,
MiscMethods,
};
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_data_structures::base_n;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::span_bug;
@ -479,7 +480,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
self.sess().emit_fatal(respan(span, err.into_diagnostic()))
} else {
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
self.tcx.sess.emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
}
}
}

View File

@ -10,6 +10,7 @@ use crate::value::Value;
use cstr::cstr;
use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::base_n;
use rustc_data_structures::fx::FxHashMap;
@ -1000,7 +1001,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
self.sess().emit_fatal(Spanned { span, node: err.into_diagnostic() })
} else {
span_bug!(span, "failed to get layout for `{ty}`: {err:?}")
self.tcx.sess.emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
}
}
}

View File

@ -35,6 +35,8 @@ codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib
codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error}
codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error}
codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err}
codegen_ssa_failed_to_write = failed to write {$path}: {$error}
codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced

View File

@ -7,6 +7,7 @@ use rustc_errors::{
IntoDiagnosticArg,
};
use rustc_macros::Diagnostic;
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
use rustc_type_ir::FloatTy;
@ -1030,6 +1031,15 @@ pub struct TargetFeatureSafeTrait {
pub def: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_failed_to_get_layout)]
pub struct FailedToGetLayout<'tcx> {
#[primary_span]
pub span: Span,
pub ty: Ty<'tcx>,
pub err: LayoutError<'tcx>,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_error_creating_remark_dir)]
pub struct ErrorCreatingRemarkDir {

View File

@ -195,8 +195,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
let ty_b = field.ty(tcx, args_b);
if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
if layout.is_zst() && layout.align.abi.bytes() == 1 {
// ignore ZST fields with alignment of 1 byte
if layout.is_1zst() {
// ignore 1-ZST fields
return false;
}
}

View File

@ -804,7 +804,7 @@ pub(crate) fn nonnull_optimization_guaranteed<'tcx>(
tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed)
}
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// `repr(transparent)` structs can have a single non-1-ZST field, this function returns that
/// field.
pub fn transparent_newtype_field<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
@ -813,8 +813,8 @@ pub fn transparent_newtype_field<'a, 'tcx>(
let param_env = tcx.param_env(variant.def_id);
variant.fields.iter().find(|field| {
let field_ty = tcx.type_of(field.did).instantiate_identity();
let is_zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_zst());
!is_zst
let is_1zst = tcx.layout_of(param_env.and(field_ty)).is_ok_and(|layout| layout.is_1zst());
!is_1zst
})
}

View File

@ -4,7 +4,9 @@ use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
use rustc_error_messages::DiagnosticMessage;
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_errors::{
DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
@ -265,6 +267,12 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
}
}
impl<'tcx> IntoDiagnosticArg for LayoutError<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.to_string().into_diagnostic_arg()
}
}
#[derive(Clone, Copy)]
pub struct LayoutCx<'tcx, C> {
pub tcx: C,

View File

@ -9,6 +9,9 @@ rustc_hir = { path = "../rustc_hir", optional = true }
rustc_middle = { path = "../rustc_middle", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
rustc_target = { path = "../rustc_target", optional = true }
rustc_driver = { path = "../rustc_driver", optional = true }
rustc_interface = { path = "../rustc_interface", optional = true}
rustc_session = {path = "../rustc_session", optional = true}
tracing = "0.1"
scoped-tls = "1.0"
@ -18,4 +21,7 @@ default = [
"rustc_middle",
"rustc_span",
"rustc_target",
"rustc_driver",
"rustc_interface",
"rustc_session",
]

View File

@ -4,13 +4,18 @@
//! until stable MIR is complete.
use std::fmt::Debug;
use std::ops::Index;
use std::string::ToString;
use crate::rustc_internal;
use crate::{
rustc_smir::Tables,
stable_mir::{self, with},
};
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_interface::{interface, Queries};
use rustc_middle::ty::TyCtxt;
use rustc_session::EarlyErrorHandler;
pub use rustc_span::def_id::{CrateNum, DefId};
fn with_tables<R>(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R {
@ -20,7 +25,7 @@ fn with_tables<R>(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R {
}
pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId {
with_tables(|t| t.item_def_id(item))
with_tables(|t| t[item.0])
}
pub fn crate_item(did: DefId) -> stable_mir::CrateItem {
@ -67,23 +72,16 @@ pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef {
with_tables(|t| t.impl_def(did))
}
impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
type Output = DefId;
#[inline(always)]
fn index(&self, index: stable_mir::DefId) -> &Self::Output {
&self.def_ids[index.0]
}
}
impl<'tcx> Tables<'tcx> {
pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
self.def_ids[item.0]
}
pub fn trait_def_id(&self, trait_def: &stable_mir::ty::TraitDef) -> DefId {
self.def_ids[trait_def.0]
}
pub fn impl_trait_def_id(&self, impl_def: &stable_mir::ty::ImplDef) -> DefId {
self.def_ids[impl_def.0]
}
pub fn generic_def_id(&self, generic_def: &stable_mir::ty::GenericDef) -> DefId {
self.def_ids[generic_def.0]
}
pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
stable_mir::CrateItem(self.create_def_id(did))
}
@ -140,12 +138,12 @@ impl<'tcx> Tables<'tcx> {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {
if d == did {
return i;
return stable_mir::DefId(i);
}
}
let id = self.def_ids.len();
self.def_ids.push(did);
id
stable_mir::DefId(id)
}
}
@ -163,3 +161,40 @@ pub type Opaque = impl Debug + ToString + Clone;
pub(crate) fn opaque<T: Debug>(value: &T) -> Opaque {
format!("{value:?}")
}
pub struct StableMir {
args: Vec<String>,
callback: fn(TyCtxt<'_>),
}
impl StableMir {
/// Creates a new `StableMir` instance, with given test_function and arguments.
pub fn new(args: Vec<String>, callback: fn(TyCtxt<'_>)) -> Self {
StableMir { args, callback }
}
/// Runs the compiler against given target and tests it with `test_function`
pub fn run(&mut self) {
rustc_driver::catch_fatal_errors(|| {
RunCompiler::new(&self.args.clone(), self).run().unwrap();
})
.unwrap();
}
}
impl Callbacks for StableMir {
/// Called after analysis. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_analysis<'tcx>(
&mut self,
_handler: &EarlyErrorHandler,
_compiler: &interface::Compiler,
queries: &'tcx Queries<'tcx>,
) -> Compilation {
queries.global_ctxt().unwrap().enter(|tcx| {
rustc_internal::run(tcx, || (self.callback)(tcx));
});
// No need to keep going.
Compilation::Stop
}
}

View File

@ -10,8 +10,8 @@
use crate::rustc_internal::{self, opaque};
use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
use crate::stable_mir::ty::{
allocation_filter, new_allocation, Const, FloatTy, GenericDef, GenericParamDef, IntTy,
Movability, RigidTy, TyKind, UintTy,
allocation_filter, new_allocation, Const, FloatTy, GenericParamDef, IntTy, Movability, RigidTy,
TyKind, UintTy,
};
use crate::stable_mir::{self, Context};
use rustc_hir as hir;
@ -54,7 +54,7 @@ impl<'tcx> Context for Tables<'tcx> {
}
fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
let def_id = self.trait_def_id(trait_def);
let def_id = self[trait_def.0];
let trait_def = self.tcx.trait_def(def_id);
trait_def.stable(self)
}
@ -68,13 +68,13 @@ impl<'tcx> Context for Tables<'tcx> {
}
fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
let def_id = self.impl_trait_def_id(impl_def);
let def_id = self[impl_def.0];
let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
impl_trait.stable(self)
}
fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
let def_id = self.item_def_id(item);
let def_id = self[item.0];
let mir = self.tcx.optimized_mir(def_id);
stable_mir::mir::Body {
blocks: mir
@ -102,19 +102,16 @@ impl<'tcx> Context for Tables<'tcx> {
ty.stable(self)
}
fn generics_of(&mut self, generic_def: &GenericDef) -> stable_mir::ty::Generics {
let def_id = self.generic_def_id(generic_def);
let generic_def = self.tcx.generics_of(def_id);
generic_def.stable(self)
fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
let def_id = self[def_id];
let generics = self.tcx.generics_of(def_id);
generics.stable(self)
}
fn predicates_of(
&mut self,
trait_def: &stable_mir::ty::TraitDef,
) -> stable_mir::GenericPredicates {
let trait_def_id = self.trait_def_id(trait_def);
let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(trait_def_id);
stable_mir::GenericPredicates {
fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
let def_id = self[def_id];
let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id);
stable_mir::ty::GenericPredicates {
parent: parent.map(|did| self.trait_def(did)),
predicates: predicates
.iter()

View File

@ -13,11 +13,10 @@
use std::cell::Cell;
use crate::rustc_smir::Tables;
use self::ty::{
GenericDef, Generics, ImplDef, ImplTrait, PredicateKind, Span, TraitDecl, TraitDef, Ty, TyKind,
GenericPredicates, Generics, ImplDef, ImplTrait, Span, TraitDecl, TraitDef, Ty, TyKind,
};
use crate::rustc_smir::Tables;
pub mod mir;
pub mod ty;
@ -29,7 +28,8 @@ pub type Symbol = String;
pub type CrateNum = usize;
/// A unique identification number for each item accessible for the current compilation unit.
pub type DefId = usize;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct DefId(pub(crate) usize);
/// A list of crate items.
pub type CrateItems = Vec<CrateItem>;
@ -40,12 +40,6 @@ pub type TraitDecls = Vec<TraitDef>;
/// A list of impl trait decls.
pub type ImplTraitDecls = Vec<ImplDef>;
/// A list of predicates.
pub struct GenericPredicates {
pub parent: Option<TraitDef>,
pub predicates: Vec<(PredicateKind, Span)>,
}
/// Holds information about a crate.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Crate {
@ -109,14 +103,6 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
with(|cx| cx.trait_impl(trait_impl))
}
pub fn generics_of(generic_def: &GenericDef) -> Generics {
with(|cx| cx.generics_of(generic_def))
}
pub fn predicates_of(trait_def: &TraitDef) -> GenericPredicates {
with(|cx| cx.predicates_of(trait_def))
}
pub trait Context {
fn entry_fn(&mut self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
@ -126,8 +112,8 @@ pub trait Context {
fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&mut self) -> ImplTraitDecls;
fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&mut self, generic_def: &GenericDef) -> Generics;
fn predicates_of(&mut self, trait_def: &TraitDef) -> GenericPredicates;
fn generics_of(&mut self, def_id: DefId) -> Generics;
fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
/// Retrieve a list of all external crates.

View File

@ -120,27 +120,9 @@ pub struct GenericDef(pub(crate) DefId);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ConstDef(pub(crate) DefId);
impl TraitDef {
pub fn trait_decl(&self) -> TraitDecl {
with(|cx| cx.trait_decl(self))
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ImplDef(pub(crate) DefId);
impl ImplDef {
pub fn trait_impl(&self) -> ImplTrait {
with(|cx| cx.trait_impl(self))
}
}
impl GenericDef {
pub fn generics_of(&self) -> Generics {
with(|tcx| tcx.generics_of(self))
}
}
#[derive(Clone, Debug)]
pub struct GenericArgs(pub Vec<GenericArgKind>);
@ -463,6 +445,16 @@ pub struct TraitDecl {
pub deny_explicit_impl: bool,
}
impl TraitDecl {
pub fn generics_of(&self) -> Generics {
with(|cx| cx.generics_of(self.def_id.0))
}
pub fn predicates_of(&self) -> GenericPredicates {
with(|cx| cx.predicates_of(self.def_id.0))
}
}
pub type ImplTrait = EarlyBinder<TraitRef>;
#[derive(Clone, Debug)]
@ -499,8 +491,8 @@ pub struct GenericParamDef {
}
pub struct GenericPredicates {
pub parent: Option<DefId>,
pub predicates: Vec<PredicateKind>,
pub parent: Option<TraitDef>,
pub predicates: Vec<(PredicateKind, Span)>,
}
#[derive(Clone, Debug)]

View File

@ -592,13 +592,13 @@ fn make_thin_self_ptr<'tcx>(
for i in 0..fat_pointer_layout.fields.count() {
let field_layout = fat_pointer_layout.field(cx, i);
if !field_layout.is_zst() {
if !field_layout.is_1zst() {
fat_pointer_layout = field_layout;
continue 'descend_newtypes;
}
}
bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
bug!("receiver has no non-1-ZST fields {:?}", fat_pointer_layout);
}
fat_pointer_layout.ty

View File

@ -192,7 +192,7 @@ fn layout_of_uncached<'tcx>(
let metadata_layout = cx.layout_of(metadata_ty)?;
// If the metadata is a 1-zst, then the pointer is thin.
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
if metadata_layout.is_1zst() {
return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
}

View File

@ -263,7 +263,7 @@ flavor. Valid options are:
* `lld-link`: use the LLVM `lld` executable with the [`-flavor link`
flag][lld-flavor] for Microsoft's `link.exe`.
[lld-flavor]: https://lld.llvm.org/Driver.html
[lld-flavor]: https://releases.llvm.org/12.0.0/tools/lld/docs/Driver.html
## linker-plugin-lto

View File

@ -0,0 +1,31 @@
// compile-flags:-g
// === GDB TESTS ===================================================================================
// gdb-command:run
// gdb-command:print a
// gdb-check:$1 = regression_bad_location_list_67992::Foo {x: [0 <repeats 1024 times>]}
// === LLDB TESTS ==================================================================================
// lldb-command:run
// lldb-command:print a
// lldbg-check:(regression_bad_location_list_67992::Foo) $0 = [...]
// lldbr-check:(regression_bad_location_list_67992::Foo) a = [...]
const ARRAY_SIZE: usize = 1024;
struct Foo {
x: [u64; ARRAY_SIZE],
}
fn foo(a: Foo, i: usize) -> u64 {
a.x[i] // #break
}
fn main() {
println!("Hello, world!");
println!("{}", foo(Foo { x: [0; ARRAY_SIZE] }, 42));
}

View File

@ -9,18 +9,12 @@
#![feature(rustc_private)]
#![feature(assert_matches)]
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_smir;
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_hir::def::DefKind;
use rustc_interface::{interface, Queries};
use rustc_middle::ty::TyCtxt;
use rustc_session::EarlyErrorHandler;
use rustc_smir::{rustc_internal, stable_mir};
use std::assert_matches::assert_matches;
use std::io::Write;
@ -130,8 +124,8 @@ fn get_item<'a>(
/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// It will invoke the compiler using a custom Callback implementation, which will
/// invoke Stable MIR APIs after the compiler has finished its analysis.
/// Then it will create a `StableMir` using custom arguments and then
/// it will run the compiler.
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
@ -142,29 +136,7 @@ fn main() {
CRATE_NAME.to_string(),
path.to_string(),
];
rustc_driver::catch_fatal_errors(|| {
RunCompiler::new(&args, &mut SMirCalls {}).run().unwrap();
})
.unwrap();
}
struct SMirCalls {}
impl Callbacks for SMirCalls {
/// Called after analysis. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_analysis<'tcx>(
&mut self,
_handler: &EarlyErrorHandler,
_compiler: &interface::Compiler,
queries: &'tcx Queries<'tcx>,
) -> Compilation {
queries.global_ctxt().unwrap().enter(|tcx| {
rustc_smir::rustc_internal::run(tcx, || test_stable_mir(tcx));
});
// No need to keep going.
Compilation::Stop
}
rustc_internal::StableMir::new(args, test_stable_mir).run();
}
fn generate_input(path: &str) -> std::io::Result<()> {

View File

@ -0,0 +1,31 @@
// build-fail
//~^ ERROR: a cycle occurred during layout computation
//~| ERROR: cycle detected when computing layout of
// Issue #111176 -- ensure that we do not emit ICE on layout cycles
use std::mem;
pub struct S<T: Tr> {
pub f: <T as Tr>::I,
}
pub trait Tr {
type I: Tr;
}
impl<T: Tr> Tr for S<T> {
type I = S<S<T>>;
}
impl Tr for () {
type I = ();
}
fn foo<T: Tr>() -> usize {
mem::size_of::<S<T>>()
}
fn main() {
println!("{}", foo::<S<()>>());
}

View File

@ -0,0 +1,11 @@
error[E0391]: cycle detected when computing layout of `S<S<()>>`
|
= note: ...which requires computing layout of `<S<()> as Tr>::I`...
= note: ...which again requires computing layout of `S<S<()>>`, completing the cycle
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: failed to get layout for S<S<()>>: a cycle occurred during layout computation
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0391`.