Skip to content

Commit

Permalink
Auto merge of rust-lang#118003 - matthiaskrgr:rollup-80t3uky, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 3 pull requests

Successful merges:

 - rust-lang#115476 (document ABI compatibility)
 - rust-lang#117688 (Misc changes to StableMIR required to Kani use case.)
 - rust-lang#117998 (On resolve error of `[rest..]`, suggest `[rest @ ..]`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 17, 2023
2 parents 00bfd6b + 488c2aa commit ee5ef3a
Show file tree
Hide file tree
Showing 21 changed files with 784 additions and 80 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_resolve/src/late.rs
Expand Up @@ -603,6 +603,8 @@ struct DiagnosticMetadata<'ast> {
/// Only used for better errors on `let <pat>: <expr, not type>;`.
current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,

current_pat: Option<&'ast Pat>,

/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
in_if_condition: Option<&'ast Expr>,

Expand Down Expand Up @@ -703,6 +705,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
fn visit_expr(&mut self, expr: &'ast Expr) {
self.resolve_expr(expr, None);
}
fn visit_pat(&mut self, p: &'ast Pat) {
let prev = self.diagnostic_metadata.current_pat;
self.diagnostic_metadata.current_pat = Some(p);
visit::walk_pat(self, p);
self.diagnostic_metadata.current_pat = prev;
}
fn visit_local(&mut self, local: &'ast Local) {
let local_spans = match local.pat.kind {
// We check for this to avoid tuple struct fields.
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Expand Up @@ -431,6 +431,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
code,
);

self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);

if let Some((span, label)) = base_error.span_label {
Expand Down Expand Up @@ -1063,6 +1064,32 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
true
}

fn suggest_at_operator_in_slice_pat_with_range(
&mut self,
err: &mut Diagnostic,
path: &[Segment],
) {
if let Some(pat) = self.diagnostic_metadata.current_pat
&& let ast::PatKind::Range(Some(start), None, range) = &pat.kind
&& let ExprKind::Path(None, range_path) = &start.kind
&& let [segment] = &range_path.segments[..]
&& let [s] = path
&& segment.ident == s.ident
{
// We've encountered `[first, rest..]` where the user might have meant
// `[first, rest @ ..]` (#88404).
err.span_suggestion_verbose(
segment.ident.span.between(range.span),
format!(
"if you meant to collect the rest of the slice in `{}`, use the at operator",
segment.ident,
),
" @ ",
Applicability::MaybeIncorrect,
);
}
}

fn suggest_swapping_misplaced_self_ty_and_trait(
&mut self,
err: &mut Diagnostic,
Expand Down
136 changes: 132 additions & 4 deletions compiler/rustc_smir/src/rustc_internal/internal.rs
Expand Up @@ -6,11 +6,23 @@
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
use crate::rustc_smir::Tables;
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
use stable_mir::ty::{Const, GenericArgKind, GenericArgs, Region, Ty};
use stable_mir::DefId;
use rustc_span::Symbol;
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
use stable_mir::ty::{
Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, GenericArgKind,
GenericArgs, Region, TraitRef, Ty,
};
use stable_mir::{AllocId, CrateItem, DefId};

use super::RustcInternal;

impl<'tcx> RustcInternal<'tcx> for CrateItem {
type T = rustc_span::def_id::DefId;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
self.0.internal(tables)
}
}

impl<'tcx> RustcInternal<'tcx> for DefId {
type T = rustc_span::def_id::DefId;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
Expand Down Expand Up @@ -38,8 +50,9 @@ impl<'tcx> RustcInternal<'tcx> for GenericArgKind {

impl<'tcx> RustcInternal<'tcx> for Region {
type T = rustc_ty::Region<'tcx>;
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
todo!()
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
// Cannot recover region. Use erased instead.
tables.tcx.lifetimes.re_erased
}
}

Expand All @@ -65,3 +78,118 @@ impl<'tcx> RustcInternal<'tcx> for Const {
tables.constants[self.id]
}
}

impl<'tcx> RustcInternal<'tcx> for MonoItem {
type T = rustc_middle::mir::mono::MonoItem<'tcx>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
use rustc_middle::mir::mono as rustc_mono;
match self {
MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables)),
MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables)),
MonoItem::GlobalAsm(_) => {
unimplemented!()
}
}
}
}

impl<'tcx> RustcInternal<'tcx> for Instance {
type T = rustc_ty::Instance<'tcx>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.instances[self.def]
}
}

impl<'tcx> RustcInternal<'tcx> for StaticDef {
type T = rustc_span::def_id::DefId;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
self.0.internal(tables)
}
}

#[allow(rustc::usage_of_qualified_ty)]
impl<'tcx, T> RustcInternal<'tcx> for Binder<T>
where
T: RustcInternal<'tcx>,
T::T: rustc_ty::TypeVisitable<rustc_ty::TyCtxt<'tcx>>,
{
type T = rustc_ty::Binder<'tcx, T::T>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
rustc_ty::Binder::bind_with_vars(
self.value.internal(tables),
tables.tcx.mk_bound_variable_kinds_from_iter(
self.bound_vars.iter().map(|bound| bound.internal(tables)),
),
)
}
}

impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
type T = rustc_ty::BoundVariableKind;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self {
BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind {
BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon,
BoundTyKind::Param(def, symbol) => {
rustc_ty::BoundTyKind::Param(def.0.internal(tables), Symbol::intern(&symbol))
}
}),
BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind {
BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::BrAnon,
BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed(
def.0.internal(tables),
Symbol::intern(&symbol),
),
BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv,
}),
BoundVariableKind::Const => rustc_ty::BoundVariableKind::Const,
}
}
}

impl<'tcx> RustcInternal<'tcx> for TraitRef {
type T = rustc_ty::TraitRef<'tcx>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
rustc_ty::TraitRef::new(
tables.tcx,
self.def_id.0.internal(tables),
self.args().internal(tables),
)
}
}

impl<'tcx> RustcInternal<'tcx> for AllocId {
type T = rustc_middle::mir::interpret::AllocId;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.alloc_ids[*self]
}
}

impl<'tcx> RustcInternal<'tcx> for ClosureKind {
type T = rustc_ty::ClosureKind;

fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
match self {
ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut,
ClosureKind::FnOnce => rustc_ty::ClosureKind::FnOnce,
}
}
}

impl<'tcx, T> RustcInternal<'tcx> for &T
where
T: RustcInternal<'tcx>,
{
type T = T::T;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
(*self).internal(tables)
}
}
24 changes: 15 additions & 9 deletions compiler/rustc_smir/src/rustc_internal/mod.rs
Expand Up @@ -13,6 +13,7 @@ use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use scoped_tls::scoped_thread_local;
use stable_mir::ty::IndexedVal;
use stable_mir::Error;
use std::cell::Cell;
use std::cell::RefCell;
use std::fmt::Debug;
Expand All @@ -21,11 +22,11 @@ use std::ops::Index;

mod internal;

pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
with_tables(|tables| item.stable(tables))
}

pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T {
with_tables(|tables| item.internal(tables))
}

Expand Down Expand Up @@ -144,12 +145,13 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
// datastructures and stable MIR datastructures
scoped_thread_local! (static TLV: Cell<*const ()>);

pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) {
pub(crate) fn init<'tcx, F, T>(tables: &TablesWrapper<'tcx>, f: F) -> T
where
F: FnOnce() -> T,
{
assert!(!TLV.is_set());
let ptr = tables as *const _ as *const ();
TLV.set(&Cell::new(ptr), || {
f();
});
TLV.set(&Cell::new(ptr), || f())
}

/// Loads the current context and calls a function with it.
Expand All @@ -165,7 +167,10 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R
})
}

pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
where
F: FnOnce() -> T,
{
let tables = TablesWrapper(RefCell::new(Tables {
tcx,
def_ids: IndexMap::default(),
Expand All @@ -175,7 +180,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
instances: IndexMap::default(),
constants: IndexMap::default(),
}));
stable_mir::run(&tables, || init(&tables, f));
stable_mir::run(&tables, || init(&tables, f))
}

#[macro_export]
Expand Down Expand Up @@ -241,7 +246,8 @@ macro_rules! run {
queries.global_ctxt().unwrap().enter(|tcx| {
rustc_internal::run(tcx, || {
self.result = Some((self.callback)(tcx));
});
})
.unwrap();
if self.result.as_ref().is_some_and(|val| val.is_continue()) {
Compilation::Continue
} else {
Expand Down
23 changes: 21 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/builder.rs
Expand Up @@ -19,10 +19,15 @@ impl<'tcx> BodyBuilder<'tcx> {
BodyBuilder { tcx, instance }
}

/// Build a stable monomorphic body for a given instance based on the MIR body.
///
/// Note that we skip instantiation for static and constants. Trying to do so can cause ICE.
///
/// We do monomorphize non-generic functions to eval unevaluated constants.
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
let mut body = self.tcx.instance_mir(self.instance.def).clone();
let generics = self.tcx.generics_of(self.instance.def_id());
if generics.requires_monomorphization(self.tcx) {
if self.tcx.def_kind(self.instance.def_id()).is_fn_like() || !self.instance.args.is_empty()
{
self.visit_body(&mut body);
}
body.stable(tables)
Expand All @@ -49,6 +54,20 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
*ty = self.monomorphize(*ty);
}

fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
let const_ = self.monomorphize(constant.const_);
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), None) {
Ok(v) => v,
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
unreachable!("Failed to evaluate instance constant: {:?}", const_)
}
};
let ty = constant.ty();
constant.const_ = mir::Const::Val(val, ty);
self.super_constant(constant, location);
}

fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
Expand Down

0 comments on commit ee5ef3a

Please sign in to comment.