Auto merge of #140239 - matthiaskrgr:rollup-75felo8, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #134446 (Stabilize the `cell_update` feature)
 - #139307 (std: Add performance warnings to HashMap::get_disjoint_mut)
 - #139450 (Impl new API `std::os::unix::fs::mkfifo` under feature `unix_fifo`)
 - #139809 (Don't warn about `v128` in wasm ABI transition)
 - #139852 (StableMIR: Implement `CompilerInterface`)
 - #139945 (Extend HIR to track the source and syntax of a lifetime)
 - #140028 (`deref_patterns`: support string and byte string literals in explicit `deref!("...")` patterns)
 - #140181 (Remove `synstructure::Structure::underscore_const` calls.)
 - #140232 (Remove unnecessary clones)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-04-24 08:50:48 +00:00
68 changed files with 1254 additions and 443 deletions
+8 -3
View File
@@ -5,7 +5,7 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin};
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
@@ -1868,7 +1868,8 @@ pub(super) fn lower_generic_bound_predicate(
}
GenericParamKind::Lifetime => {
let lt_id = self.next_node_id();
let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
let lifetime =
self.new_named_lifetime(id, lt_id, ident, LifetimeSource::Other, ident.into());
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
bounds,
@@ -1901,7 +1902,11 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
}),
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
lifetime: self.lower_lifetime(lifetime),
lifetime: self.lower_lifetime(
lifetime,
LifetimeSource::Other,
lifetime.ident.into(),
),
bounds: self.lower_param_bounds(
bounds,
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+73 -48
View File
@@ -54,8 +54,8 @@
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::{
self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName,
TraitCandidate,
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource,
LifetimeSyntax, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@@ -1079,7 +1079,11 @@ fn lower_generic_arg(
itctx: ImplTraitContext,
) -> hir::GenericArg<'hir> {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(
lt,
LifetimeSource::Path { with_angle_brackets: true },
lt.ident.into(),
)),
ast::GenericArg::Type(ty) => {
// We cannot just match on `TyKind::Infer` as `(_)` is represented as
// `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`
@@ -1198,35 +1202,11 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Ref(region, mt) => {
let region = region.unwrap_or_else(|| {
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
self.resolver.get_lifetime_res(t.id)
{
debug_assert_eq!(start.plus(1), end);
start
} else {
self.next_node_id()
};
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
});
let lifetime = self.lower_lifetime(&region);
let lifetime = self.lower_ty_direct_lifetime(t, *region);
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
}
TyKind::PinnedRef(region, mt) => {
let region = region.unwrap_or_else(|| {
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
self.resolver.get_lifetime_res(t.id)
{
debug_assert_eq!(start.plus(1), end);
start
} else {
self.next_node_id()
};
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
});
let lifetime = self.lower_lifetime(&region);
let lifetime = self.lower_ty_direct_lifetime(t, *region);
let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
let span = self.lower_span(t.span);
let arg = hir::Ty { kind, span, hir_id: self.next_id() };
@@ -1302,7 +1282,11 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
}
GenericBound::Outlives(lifetime) => {
if lifetime_bound.is_none() {
lifetime_bound = Some(this.lower_lifetime(lifetime));
lifetime_bound = Some(this.lower_lifetime(
lifetime,
LifetimeSource::Other,
lifetime.ident.into(),
));
}
None
}
@@ -1393,6 +1377,31 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
}
fn lower_ty_direct_lifetime(
&mut self,
t: &Ty,
region: Option<Lifetime>,
) -> &'hir hir::Lifetime {
let (region, syntax) = match region {
Some(region) => (region, region.ident.into()),
None => {
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
self.resolver.get_lifetime_res(t.id)
{
debug_assert_eq!(start.plus(1), end);
start
} else {
self.next_node_id()
};
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };
(region, LifetimeSyntax::Hidden)
}
};
self.lower_lifetime(&region, LifetimeSource::Reference, syntax)
}
/// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =
/// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a
/// HIR type that references the TAIT.
@@ -1474,9 +1483,9 @@ fn lower_precise_capturing_args(
precise_capturing_args: &[PreciseCapturingArg],
) -> &'hir [hir::PreciseCapturingArg<'hir>] {
self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
PreciseCapturingArg::Lifetime(lt) => {
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
}
PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(
self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),
),
PreciseCapturingArg::Arg(path, id) => {
let [segment] = path.segments.as_slice() else {
panic!();
@@ -1739,9 +1748,11 @@ fn lower_param_bound(
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
GenericBound::Outlives(lifetime) => {
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
}
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
lifetime,
LifetimeSource::OutlivesBound,
lifetime.ident.into(),
)),
GenericBound::Use(args, span) => hir::GenericBound::Use(
self.lower_precise_capturing_args(args),
self.lower_span(*span),
@@ -1749,12 +1760,28 @@ fn lower_param_bound(
}
}
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
fn lower_lifetime(
&mut self,
l: &Lifetime,
source: LifetimeSource,
syntax: LifetimeSyntax,
) -> &'hir hir::Lifetime {
self.new_named_lifetime(l.id, l.id, l.ident, source, syntax)
}
fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
fn lower_lifetime_hidden_in_path(
&mut self,
id: NodeId,
span: Span,
with_angle_brackets: bool,
) -> &'hir hir::Lifetime {
self.new_named_lifetime(
id,
id,
Ident::new(kw::UnderscoreLifetime, span),
LifetimeSource::Path { with_angle_brackets },
LifetimeSyntax::Hidden,
)
}
#[instrument(level = "debug", skip(self))]
@@ -1763,7 +1790,8 @@ fn new_named_lifetime(
id: NodeId,
new_id: NodeId,
ident: Ident,
is_anon_in_path: IsAnonInPath,
source: LifetimeSource,
syntax: LifetimeSyntax,
) -> &'hir hir::Lifetime {
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
let res = match res {
@@ -1787,17 +1815,13 @@ fn new_named_lifetime(
}
};
#[cfg(debug_assertions)]
if is_anon_in_path == IsAnonInPath::Yes {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
}
debug!(?res);
self.arena.alloc(hir::Lifetime::new(
self.lower_node_id(new_id),
self.lower_ident(ident),
res,
is_anon_in_path,
source,
syntax,
))
}
@@ -2389,7 +2413,8 @@ fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
self.next_id(),
Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
hir::LifetimeKind::ImplicitObjectLifetimeDefault,
IsAnonInPath::No,
LifetimeSource::Other,
LifetimeSyntax::Hidden,
);
debug!("elided_dyn_bound: r={:?}", r);
self.arena.alloc(r)
+10 -7
View File
@@ -1,10 +1,9 @@
use std::sync::Arc;
use rustc_ast::{self as ast, *};
use rustc_hir as hir;
use rustc_hir::GenericArg;
use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, GenericArg};
use rustc_middle::{span_bug, ty};
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
@@ -433,23 +432,27 @@ fn maybe_insert_elided_lifetimes_in_path(
// Note: these spans are used for diagnostics when they can't be inferred.
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
let elided_lifetime_span = if generic_args.span.is_empty() {
let (elided_lifetime_span, with_angle_brackets) = if generic_args.span.is_empty() {
// If there are no brackets, use the identifier span.
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
// originating from macros, since the segment's span might be from a macro arg.
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
(segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span), false)
} else if generic_args.is_empty() {
// If there are brackets, but not generic arguments, then use the opening bracket
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
(generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)), true)
} else {
// Else use an empty span right after the opening bracket.
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
(generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(), true)
};
generic_args.args.insert_many(
0,
(start..end).map(|id| {
let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
let l = self.lower_lifetime_hidden_in_path(
id,
elided_lifetime_span,
with_angle_brackets,
);
GenericArg::Lifetime(l)
}),
);
@@ -799,7 +799,7 @@ fn print_mac_def(
has_bang,
Some(*ident),
macro_def.body.delim,
&macro_def.body.tokens.clone(),
&macro_def.body.tokens,
true,
sp,
);
@@ -1468,7 +1468,7 @@ fn print_mac(&mut self, m: &ast::MacCall) {
true,
None,
m.args.delim,
&m.args.tokens.clone(),
&m.args.tokens,
true,
m.span(),
);
+126 -33
View File
@@ -36,43 +36,110 @@
use crate::intravisit::{FnKind, VisitorExt};
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
pub enum IsAnonInPath {
No,
Yes,
pub enum LifetimeSource {
/// E.g. `&Type`, `&'_ Type`, `&'a Type`, `&mut Type`, `&'_ mut Type`, `&'a mut Type`
Reference,
/// E.g. `ContainsLifetime`, `ContainsLifetime<'_>`, `ContainsLifetime<'a>`
Path {
/// - true for `ContainsLifetime<'_>`, `ContainsLifetime<'a>`,
/// `ContainsLifetime<'_, T>`, `ContainsLifetime<'a, T>`
/// - false for `ContainsLifetime`
with_angle_brackets: bool,
},
/// E.g. `impl Trait + '_`, `impl Trait + 'a`
OutlivesBound,
/// E.g. `impl Trait + use<'_>`, `impl Trait + use<'a>`
PreciseCapturing,
/// Other usages which have not yet been categorized. Feel free to
/// add new sources that you find useful.
///
/// Some non-exhaustive examples:
/// - `where T: 'a`
/// - `fn(_: dyn Trait + 'a)`
Other,
}
/// A lifetime. The valid field combinations are non-obvious. The following
/// example shows some of them. See also the comments on `LifetimeKind`.
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
pub enum LifetimeSyntax {
/// E.g. `&Type`, `ContainsLifetime`
Hidden,
/// E.g. `&'_ Type`, `ContainsLifetime<'_>`, `impl Trait + '_`, `impl Trait + use<'_>`
Anonymous,
/// E.g. `&'a Type`, `ContainsLifetime<'a>`, `impl Trait + 'a`, `impl Trait + use<'a>`
Named,
}
impl From<Ident> for LifetimeSyntax {
fn from(ident: Ident) -> Self {
let name = ident.name;
if name == kw::Empty {
unreachable!("A lifetime name should never be empty");
} else if name == kw::UnderscoreLifetime {
LifetimeSyntax::Anonymous
} else {
debug_assert!(name.as_str().starts_with('\''));
LifetimeSyntax::Named
}
}
}
/// A lifetime. The valid field combinations are non-obvious and not all
/// combinations are possible. The following example shows some of
/// them. See also the comments on `LifetimeKind` and `LifetimeSource`.
///
/// ```
/// #[repr(C)]
/// struct S<'a>(&'a u32); // res=Param, name='a, IsAnonInPath::No
/// struct S<'a>(&'a u32); // res=Param, name='a, source=Reference, syntax=Named
/// unsafe extern "C" {
/// fn f1(s: S); // res=Param, name='_, IsAnonInPath::Yes
/// fn f2(s: S<'_>); // res=Param, name='_, IsAnonInPath::No
/// fn f3<'a>(s: S<'a>); // res=Param, name='a, IsAnonInPath::No
/// fn f1(s: S); // res=Param, name='_, source=Path, syntax=Hidden
/// fn f2(s: S<'_>); // res=Param, name='_, source=Path, syntax=Anonymous
/// fn f3<'a>(s: S<'a>); // res=Param, name='a, source=Path, syntax=Named
/// }
///
/// struct St<'a> { x: &'a u32 } // res=Param, name='a, IsAnonInPath::No
/// struct St<'a> { x: &'a u32 } // res=Param, name='a, source=Reference, syntax=Named
/// fn f() {
/// _ = St { x: &0 }; // res=Infer, name='_, IsAnonInPath::Yes
/// _ = St::<'_> { x: &0 }; // res=Infer, name='_, IsAnonInPath::No
/// _ = St { x: &0 }; // res=Infer, name='_, source=Path, syntax=Hidden
/// _ = St::<'_> { x: &0 }; // res=Infer, name='_, source=Path, syntax=Anonymous
/// }
///
/// struct Name<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No
/// const A: Name = Name("a"); // res=Static, name='_, IsAnonInPath::Yes
/// const B: &str = ""; // res=Static, name='_, IsAnonInPath::No
/// static C: &'_ str = ""; // res=Static, name='_, IsAnonInPath::No
/// static D: &'static str = ""; // res=Static, name='static, IsAnonInPath::No
/// struct Name<'a>(&'a str); // res=Param, name='a, source=Reference, syntax=Named
/// const A: Name = Name("a"); // res=Static, name='_, source=Path, syntax=Hidden
/// const B: &str = ""; // res=Static, name='_, source=Reference, syntax=Hidden
/// static C: &'_ str = ""; // res=Static, name='_, source=Reference, syntax=Anonymous
/// static D: &'static str = ""; // res=Static, name='static, source=Reference, syntax=Named
///
/// trait Tr {}
/// fn tr(_: Box<dyn Tr>) {} // res=ImplicitObjectLifetimeDefault, name='_, IsAnonInPath::No
/// fn tr(_: Box<dyn Tr>) {} // res=ImplicitObjectLifetimeDefault, name='_, source=Other, syntax=Hidden
///
/// fn capture_outlives<'a>() ->
/// impl FnOnce() + 'a // res=Param, ident='a, source=OutlivesBound, syntax=Named
/// {
/// || {}
/// }
///
/// fn capture_precise<'a>() ->
/// impl FnOnce() + use<'a> // res=Param, ident='a, source=PreciseCapturing, syntax=Named
/// {
/// || {}
/// }
///
/// // (commented out because these cases trigger errors)
/// // struct S1<'a>(&'a str); // res=Param, name='a, IsAnonInPath::No
/// // struct S2(S1); // res=Error, name='_, IsAnonInPath::Yes
/// // struct S3(S1<'_>); // res=Error, name='_, IsAnonInPath::No
/// // struct S4(S1<'a>); // res=Error, name='a, IsAnonInPath::No
/// // struct S1<'a>(&'a str); // res=Param, name='a, source=Reference, syntax=Named
/// // struct S2(S1); // res=Error, name='_, source=Path, syntax=Hidden
/// // struct S3(S1<'_>); // res=Error, name='_, source=Path, syntax=Anonymous
/// // struct S4(S1<'a>); // res=Error, name='a, source=Path, syntax=Named
/// ```
///
/// Some combinations that cannot occur are `LifetimeSyntax::Hidden` with
/// `LifetimeSource::OutlivesBound` or `LifetimeSource::PreciseCapturing`
/// — there's no way to "elide" these lifetimes.
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Lifetime {
#[stable_hasher(ignore)]
@@ -86,9 +153,13 @@ pub struct Lifetime {
/// Semantics of this lifetime.
pub kind: LifetimeKind,
/// Is the lifetime anonymous and in a path? Used only for error
/// suggestions. See `Lifetime::suggestion` for example use.
pub is_anon_in_path: IsAnonInPath,
/// The context in which the lifetime occurred. See `Lifetime::suggestion`
/// for example use.
pub source: LifetimeSource,
/// The syntax that the user used to declare this lifetime. See
/// `Lifetime::suggestion` for example use.
pub syntax: LifetimeSyntax,
}
#[derive(Debug, Copy, Clone, HashStable_Generic)]
@@ -185,9 +256,10 @@ pub fn new(
hir_id: HirId,
ident: Ident,
kind: LifetimeKind,
is_anon_in_path: IsAnonInPath,
source: LifetimeSource,
syntax: LifetimeSyntax,
) -> Lifetime {
let lifetime = Lifetime { hir_id, ident, kind, is_anon_in_path };
let lifetime = Lifetime { hir_id, ident, kind, source, syntax };
// Sanity check: elided lifetimes form a strict subset of anonymous lifetimes.
#[cfg(debug_assertions)]
@@ -209,23 +281,44 @@ pub fn is_anonymous(&self) -> bool {
self.ident.name == kw::UnderscoreLifetime
}
pub fn is_syntactically_hidden(&self) -> bool {
matches!(self.syntax, LifetimeSyntax::Hidden)
}
pub fn is_syntactically_anonymous(&self) -> bool {
matches!(self.syntax, LifetimeSyntax::Anonymous)
}
pub fn is_static(&self) -> bool {
self.kind == LifetimeKind::Static
}
pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
use LifetimeSource::*;
use LifetimeSyntax::*;
debug_assert!(new_lifetime.starts_with('\''));
match (self.is_anon_in_path, self.ident.span.is_empty()) {
match (self.syntax, self.source) {
// The user wrote `'a` or `'_`.
(Named | Anonymous, _) => (self.ident.span, format!("{new_lifetime}")),
// The user wrote `Path<T>`, and omitted the `'_,`.
(IsAnonInPath::Yes, true) => (self.ident.span, format!("{new_lifetime}, ")),
(Hidden, Path { with_angle_brackets: true }) => {
(self.ident.span, format!("{new_lifetime}, "))
}
// The user wrote `Path` and omitted the `<'_>`.
(IsAnonInPath::Yes, false) => {
(Hidden, Path { with_angle_brackets: false }) => {
(self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
}
// The user wrote `&type` or `&mut type`.
(IsAnonInPath::No, true) => (self.ident.span, format!("{new_lifetime} ")),
(Hidden, Reference) => (self.ident.span, format!("{new_lifetime} ")),
// The user wrote `'a` or `'_`.
(IsAnonInPath::No, false) => (self.ident.span, format!("{new_lifetime}")),
(Hidden, source) => {
unreachable!("can't suggest for a hidden lifetime of {source:?}")
}
}
}
}
+2 -1
View File
@@ -58,7 +58,8 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
kind: LifetimeKind::Static,
is_anon_in_path: IsAnonInPath::No,
source: LifetimeSource::Other,
syntax: LifetimeSyntax::Hidden,
}
},
syntax,
+39 -7
View File
@@ -759,22 +759,54 @@ fn check_pat_lit(
// Byte string patterns behave the same way as array patterns
// They can denote both statically and dynamically-sized byte arrays.
// Additionally, when `deref_patterns` is enabled, byte string literal patterns may have
// types `[u8]` or `[u8; N]`, in order to type, e.g., `deref!(b"..."): Vec<u8>`.
let mut pat_ty = ty;
if let hir::PatExprKind::Lit {
lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
} = lt.kind
{
let tcx = self.tcx;
let expected = self.structurally_resolve_type(span, expected);
if let ty::Ref(_, inner_ty, _) = *expected.kind()
&& self.try_structurally_resolve_type(span, inner_ty).is_slice()
{
let tcx = self.tcx;
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
pat_ty =
Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
match *expected.kind() {
// Allow `b"...": &[u8]`
ty::Ref(_, inner_ty, _)
if self.try_structurally_resolve_type(span, inner_ty).is_slice() =>
{
trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
pat_ty = Ty::new_imm_ref(
tcx,
tcx.lifetimes.re_static,
Ty::new_slice(tcx, tcx.types.u8),
);
}
// Allow `b"...": [u8; 3]` for `deref_patterns`
ty::Array(..) if tcx.features().deref_patterns() => {
pat_ty = match *ty.kind() {
ty::Ref(_, inner_ty, _) => inner_ty,
_ => span_bug!(span, "found byte string literal with non-ref type {ty:?}"),
}
}
// Allow `b"...": [u8]` for `deref_patterns`
ty::Slice(..) if tcx.features().deref_patterns() => {
pat_ty = Ty::new_slice(tcx, tcx.types.u8);
}
// Otherwise, `b"...": &[u8; 3]`
_ => {}
}
}
// When `deref_patterns` is enabled, in order to allow `deref!("..."): String`, we allow
// string literal patterns to have type `str`. This is accounted for when lowering to MIR.
if self.tcx.features().deref_patterns()
&& let hir::PatExprKind::Lit {
lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
} = lt.kind
&& self.try_structurally_resolve_type(span, expected).is_str()
{
pat_ty = self.tcx.types.str_;
}
if self.tcx.features().string_deref_patterns()
&& let hir::PatExprKind::Lit {
lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
+3 -6
View File
@@ -55,8 +55,7 @@
///
/// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
s.underscore_const(true);
pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
DiagnosticDerive::new(s).into_tokens()
}
@@ -102,8 +101,7 @@ pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
///
/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
s.underscore_const(true);
pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
LintDiagnosticDerive::new(s).into_tokens()
}
@@ -153,7 +151,6 @@ pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
///
/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
/// ```
pub(super) fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
s.underscore_const(true);
pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
SubdiagnosticDerive::new().into_tokens(s)
}
-2
View File
@@ -74,8 +74,6 @@ fn hash_stable_derive_with_mode(
HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
};
s.underscore_const(true);
// no_context impl is able to derive by-field, which is closer to a perfect derive.
s.add_bounds(match mode {
HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics,
-1
View File
@@ -4,7 +4,6 @@
pub(super) fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
s.add_bounds(synstructure::AddBounds::Generics);
s.bind_with(|_| synstructure::BindStyle::Move);
s.underscore_const(true);
let tcx: syn::Lifetime = parse_quote!('tcx);
let newtcx: syn::GenericParam = parse_quote!('__lifted);
+1 -11
View File
@@ -12,7 +12,6 @@ pub(super) fn type_decodable_derive(
let decoder_ty = quote! { __D };
s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx> });
s.add_bounds(synstructure::AddBounds::Fields);
s.underscore_const(true);
decodable_body(s, decoder_ty)
}
@@ -26,7 +25,6 @@ pub(super) fn meta_decodable_derive(
s.add_impl_generic(parse_quote! { '__a });
let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
s.add_bounds(synstructure::AddBounds::Generics);
s.underscore_const(true);
decodable_body(s, decoder_ty)
}
@@ -35,7 +33,6 @@ pub(super) fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro
let decoder_ty = quote! { __D };
s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_span::SpanDecoder });
s.add_bounds(synstructure::AddBounds::Generics);
s.underscore_const(true);
decodable_body(s, decoder_ty)
}
@@ -46,13 +43,12 @@ pub(super) fn decodable_nocontext_derive(
let decoder_ty = quote! { __D };
s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder });
s.add_bounds(synstructure::AddBounds::Fields);
s.underscore_const(true);
decodable_body(s, decoder_ty)
}
fn decodable_body(
mut s: synstructure::Structure<'_>,
s: synstructure::Structure<'_>,
decoder_ty: TokenStream,
) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
@@ -98,7 +94,6 @@ fn decodable_body(
}
}
};
s.underscore_const(true);
s.bound_impl(
quote!(::rustc_serialize::Decodable<#decoder_ty>),
@@ -133,7 +128,6 @@ pub(super) fn type_encodable_derive(
}
s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx> });
s.add_bounds(synstructure::AddBounds::Fields);
s.underscore_const(true);
encodable_body(s, encoder_ty, false)
}
@@ -147,7 +141,6 @@ pub(super) fn meta_encodable_derive(
s.add_impl_generic(parse_quote! { '__a });
let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
s.add_bounds(synstructure::AddBounds::Generics);
s.underscore_const(true);
encodable_body(s, encoder_ty, true)
}
@@ -156,7 +149,6 @@ pub(super) fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro
let encoder_ty = quote! { __E };
s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_span::SpanEncoder });
s.add_bounds(synstructure::AddBounds::Generics);
s.underscore_const(true);
encodable_body(s, encoder_ty, false)
}
@@ -167,7 +159,6 @@ pub(super) fn encodable_nocontext_derive(
let encoder_ty = quote! { __E };
s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder });
s.add_bounds(synstructure::AddBounds::Fields);
s.underscore_const(true);
encodable_body(s, encoder_ty, false)
}
@@ -181,7 +172,6 @@ fn encodable_body(
panic!("cannot derive on union")
}
s.underscore_const(true);
s.bind_with(|binding| {
// Handle the lack of a blanket reference impl.
if let syn::Type::Reference(_) = binding.ast().ty {
@@ -6,8 +6,6 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
panic!("cannot derive on union")
}
s.underscore_const(true);
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! { 'tcx });
}
@@ -8,8 +8,6 @@ pub(super) fn type_visitable_derive(
panic!("cannot derive on union")
}
s.underscore_const(true);
// ignore fields with #[type_visitable(ignore)]
s.filter(|bi| {
let mut ignored = false;
@@ -146,6 +146,29 @@ pub(super) fn perform_test(
let mut place = place;
let mut block = block;
match ty.kind() {
ty::Str => {
// String literal patterns may have type `str` if `deref_patterns` is
// enabled, in order to allow `deref!("..."): String`. In this case, `value`
// is of type `&str`, so we compare it to `&place`.
if !tcx.features().deref_patterns() {
span_bug!(
test.span,
"matching on `str` went through without enabling deref_patterns"
);
}
let re_erased = tcx.lifetimes.re_erased;
let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
let ref_place = self.temp(ref_str_ty, test.span);
// `let ref_place: &str = &place;`
self.cfg.push_assign(
block,
self.source_info(test.span),
ref_place,
Rvalue::Ref(re_erased, BorrowKind::Shared, place),
);
place = ref_place;
ty = ref_str_ty;
}
ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => {
if !tcx.features().string_deref_patterns() {
span_bug!(
+12 -2
View File
@@ -37,13 +37,23 @@ pub(crate) fn lit_to_const<'tcx>(
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
}
(ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
// String literal patterns may have type `str` if `deref_patterns` is enabled, in order
// to allow `deref!("..."): String`.
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
}
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Slice(_)) =>
if matches!(inner_ty.kind(), ty::Slice(_) | ty::Array(..)) =>
{
let bytes = data as &[u8];
ty::ValTree::from_raw_bytes(tcx, bytes)
}
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
(ast::LitKind::ByteStr(data, _), ty::Slice(_) | ty::Array(..))
if tcx.features().deref_patterns() =>
{
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
let bytes = data as &[u8];
ty::ValTree::from_raw_bytes(tcx, bytes)
}
@@ -280,6 +280,16 @@ fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
slice: None,
suffix: Box::new([]),
},
ty::Str => {
// String literal patterns may have type `str` if `deref_patterns` is enabled, in
// order to allow `deref!("..."): String`. Since we need a `&str` for the comparison
// when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
// This works because `str` and `&str` have the same valtree representation.
let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
PatKind::Constant {
value: mir::Const::Ty(ref_str_ty, ty::Const::new_value(tcx, cv, ref_str_ty)),
}
}
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// `&str` is represented as a valtree, let's keep using this
// optimization for now.
@@ -89,6 +89,12 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
return true;
}
// Both the old and the new ABIs treat vector types like `v128` the same
// way.
if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
return true;
}
// This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
if arg.layout.is_aggregate() {
let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+1 -2
View File
@@ -19,7 +19,6 @@
pub mod rustc_internal;
// Make this module private for now since external users should not call these directly.
mod rustc_smir;
pub mod rustc_smir;
pub mod stable_mir;
+20 -15
View File
@@ -18,9 +18,10 @@
use scoped_tls::scoped_thread_local;
use stable_mir::Error;
use stable_mir::abi::Layout;
use stable_mir::compiler_interface::SmirInterface;
use stable_mir::ty::IndexedVal;
use crate::rustc_smir::context::TablesWrapper;
use crate::rustc_smir::context::SmirCtxt;
use crate::rustc_smir::{Stable, Tables};
use crate::stable_mir;
@@ -196,12 +197,12 @@ 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, F, T>(tables: &TablesWrapper<'tcx>, f: F) -> T
pub(crate) fn init<'tcx, F, T>(cx: &SmirCtxt<'tcx>, f: F) -> T
where
F: FnOnce() -> T,
{
assert!(!TLV.is_set());
let ptr = tables as *const _ as *const ();
let ptr = cx as *const _ as *const ();
TLV.set(&Cell::new(ptr), || f())
}
@@ -212,8 +213,8 @@ pub(crate) fn with_tables<R>(f: impl for<'tcx> FnOnce(&mut Tables<'tcx>) -> R) -
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
let wrapper = ptr as *const TablesWrapper<'_>;
let mut tables = unsafe { (*wrapper).0.borrow_mut() };
let context = ptr as *const SmirCtxt<'_>;
let mut tables = unsafe { (*context).0.borrow_mut() };
f(&mut *tables)
})
}
@@ -222,7 +223,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
where
F: FnOnce() -> T,
{
let tables = TablesWrapper(RefCell::new(Tables {
let tables = SmirCtxt(RefCell::new(Tables {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
@@ -233,7 +234,12 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
mir_consts: IndexMap::default(),
layouts: IndexMap::default(),
}));
stable_mir::compiler_interface::run(&tables, || init(&tables, f))
let interface = SmirInterface { cx: tables };
// Pass the `SmirInterface` to compiler_interface::run
// and initialize the rustc-specific TLS with tables.
stable_mir::compiler_interface::run(&interface, || init(&interface.cx, f))
}
/// Instantiate and run the compiler with the provided arguments and callback.
@@ -256,7 +262,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
/// // Your code goes in here.
/// # ControlFlow::Continue(())
/// }
/// # let args = vec!["--verbose".to_string()];
/// # let args = &["--verbose".to_string()];
/// let result = run!(args, analyze_code);
/// # assert_eq!(result, Err(CompilerError::Skipped))
/// # }
@@ -278,7 +284,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
/// // Your code goes in here.
/// # ControlFlow::Continue(())
/// }
/// # let args = vec!["--verbose".to_string()];
/// # let args = &["--verbose".to_string()];
/// # let extra_args = vec![];
/// let result = run!(args, || analyze_code(extra_args));
/// # assert_eq!(result, Err(CompilerError::Skipped))
@@ -340,7 +346,6 @@ pub struct StableMir<B = (), C = (), F = fn($(optional!($with_tcx TyCtxt))?) ->
C: Send,
F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
{
args: Vec<String>,
callback: Option<F>,
result: Option<ControlFlow<B, C>>,
}
@@ -352,14 +357,14 @@ impl<B, C, F> StableMir<B, C, F>
F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
{
/// Creates a new `StableMir` instance, with given test_function and arguments.
pub fn new(args: Vec<String>, callback: F) -> Self {
StableMir { args, callback: Some(callback), result: None }
pub fn new(callback: F) -> Self {
StableMir { callback: Some(callback), result: None }
}
/// Runs the compiler against given target and tests it with `test_function`
pub fn run(&mut self) -> Result<C, CompilerError<B>> {
pub fn run(&mut self, args: &[String]) -> Result<C, CompilerError<B>> {
let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> {
run_compiler(&self.args.clone(), self);
run_compiler(&args, self);
Ok(())
});
match (compiler_result, self.result.take()) {
@@ -409,7 +414,7 @@ fn after_analysis<'tcx>(
}
}
StableMir::new($args, $callback).run()
StableMir::new($callback).run($args)
}};
}
+175 -94
View File
@@ -1,7 +1,4 @@
//! Implementation of `[stable_mir::compiler_interface::Context]` trait.
//!
//! This trait is currently the main interface between the Rust compiler,
//! and the `stable_mir` crate.
//! Implementation of StableMIR Context.
#![allow(rustc::usage_of_qualified_ty)]
@@ -20,7 +17,6 @@
use rustc_middle::{mir, ty};
use rustc_span::def_id::LOCAL_CRATE;
use stable_mir::abi::{FnAbi, Layout, LayoutShape};
use stable_mir::compiler_interface::Context;
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::{InstanceDef, StaticDef};
use stable_mir::mir::{BinOp, Body, Place, UnOp};
@@ -37,8 +33,14 @@
use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate};
use crate::stable_mir;
impl<'tcx> Context for TablesWrapper<'tcx> {
fn target_info(&self) -> MachineInfo {
/// Provides direct access to rustc's internal queries.
///
/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
/// this context to obtain rustc-level information.
pub struct SmirCtxt<'tcx>(pub RefCell<Tables<'tcx>>);
impl<'tcx> SmirCtxt<'tcx> {
pub fn target_info(&self) -> MachineInfo {
let mut tables = self.0.borrow_mut();
MachineInfo {
endian: tables.tcx.data_layout.endian.stable(&mut *tables),
@@ -48,31 +50,35 @@ fn target_info(&self) -> MachineInfo {
}
}
fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
pub fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
Some(tables.crate_item(tcx.entry_fn(())?.0))
}
fn all_local_items(&self) -> stable_mir::CrateItems {
/// Retrieve all items of the local crate that have a MIR associated with them.
pub fn all_local_items(&self) -> stable_mir::CrateItems {
let mut tables = self.0.borrow_mut();
tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
}
fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
/// Retrieve the body of a function.
/// This function will panic if the body is not available.
pub fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
let mut tables = self.0.borrow_mut();
let def_id = tables[item];
tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables)
}
fn has_body(&self, def: DefId) -> bool {
/// Check whether the body of a function is available.
pub fn has_body(&self, def: DefId) -> bool {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.internal(&mut *tables, tcx);
tables.item_has_body(def_id)
}
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
tcx.foreign_modules(crate_num.internal(&mut *tables, tcx))
@@ -81,21 +87,23 @@ fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignMod
.collect()
}
fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
/// Retrieve all functions defined in this crate.
pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let krate = crate_num.internal(&mut *tables, tcx);
filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id))
}
fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
/// Retrieve all static items defined in this crate.
pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let krate = crate_num.internal(&mut *tables, tcx);
filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id))
}
fn foreign_module(
pub fn foreign_module(
&self,
mod_def: stable_mir::ty::ForeignModuleDef,
) -> stable_mir::ty::ForeignModule {
@@ -105,7 +113,7 @@ fn foreign_module(
mod_def.stable(&mut *tables)
}
fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
pub fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
let mut tables = self.0.borrow_mut();
let def_id = tables[mod_def.def_id()];
tables
@@ -119,12 +127,12 @@ fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<Foreig
.collect()
}
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
pub fn all_trait_decls(&self) -> stable_mir::TraitDecls {
let mut tables = self.0.borrow_mut();
tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect()
}
fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
tcx.traits(crate_num.internal(&mut *tables, tcx))
@@ -133,14 +141,14 @@ fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
.collect()
}
fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
pub fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
let mut tables = self.0.borrow_mut();
let def_id = tables[trait_def.0];
let trait_def = tables.tcx.trait_def(def_id);
trait_def.stable(&mut *tables)
}
fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
pub fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
iter::once(LOCAL_CRATE)
@@ -150,7 +158,7 @@ fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
.collect()
}
fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
pub fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx))
@@ -159,21 +167,21 @@ fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
.collect()
}
fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
pub fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
let mut tables = self.0.borrow_mut();
let def_id = tables[impl_def.0];
let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
impl_trait.stable(&mut *tables)
}
fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
pub fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let generics = tables.tcx.generics_of(def_id);
generics.stable(&mut *tables)
}
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
pub fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
@@ -191,7 +199,7 @@ fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPre
}
}
fn explicit_predicates_of(
pub fn explicit_predicates_of(
&self,
def_id: stable_mir::DefId,
) -> stable_mir::ty::GenericPredicates {
@@ -212,17 +220,20 @@ fn explicit_predicates_of(
}
}
fn local_crate(&self) -> stable_mir::Crate {
/// Get information about the local crate.
pub fn local_crate(&self) -> stable_mir::Crate {
let tables = self.0.borrow();
smir_crate(tables.tcx, LOCAL_CRATE)
}
fn external_crates(&self) -> Vec<stable_mir::Crate> {
/// Retrieve a list of all external crates.
pub fn external_crates(&self) -> Vec<stable_mir::Crate> {
let tables = self.0.borrow();
tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
}
fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
/// Find a crate with the given name.
pub fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
let tables = self.0.borrow();
let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
.iter()
@@ -235,7 +246,8 @@ fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
crates
}
fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
/// Returns the name of given `DefId`.
pub fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
let tables = self.0.borrow();
if trimmed {
with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
@@ -244,7 +256,14 @@ fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
}
}
fn tool_attrs(
/// Return registered tool attributes with the given attribute name.
///
/// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool
/// attributes will simply return an empty list.
///
/// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
pub fn tool_attrs(
&self,
def_id: stable_mir::DefId,
attr: &[stable_mir::Symbol],
@@ -268,7 +287,11 @@ fn tool_attrs(
.collect()
}
fn all_tool_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
/// Get all tool attributes of a definition.
pub fn all_tool_attrs(
&self,
def_id: stable_mir::DefId,
) -> Vec<stable_mir::crate_def::Attribute> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let did = tables[def_id];
@@ -292,12 +315,14 @@ fn all_tool_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def
.collect()
}
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
/// Returns printable, human readable form of `Span`.
pub fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
let tables = self.0.borrow();
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
}
fn get_filename(&self, span: &Span) -> Filename {
/// Return filename from given `Span`, for diagnostic purposes.
pub fn get_filename(&self, span: &Span) -> Filename {
let tables = self.0.borrow();
tables
.tcx
@@ -308,23 +333,27 @@ fn get_filename(&self, span: &Span) -> Filename {
.to_string()
}
fn get_lines(&self, span: &Span) -> LineInfo {
/// Return lines corresponding to this `Span`.
pub fn get_lines(&self, span: &Span) -> LineInfo {
let tables = self.0.borrow();
let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
}
fn item_kind(&self, item: CrateItem) -> ItemKind {
/// Returns the `kind` of given `DefId`.
pub fn item_kind(&self, item: CrateItem) -> ItemKind {
let tables = self.0.borrow();
new_item_kind(tables.tcx.def_kind(tables[item.0]))
}
fn is_foreign_item(&self, item: DefId) -> bool {
/// Returns whether this is a foreign item.
pub fn is_foreign_item(&self, item: DefId) -> bool {
let tables = self.0.borrow();
tables.tcx.is_foreign_item(tables[item])
}
fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
/// Returns the kind of a given foreign item.
pub fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
let mut tables = self.0.borrow_mut();
let def_id = tables[def.def_id()];
let tcx = tables.tcx;
@@ -339,32 +368,37 @@ fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
}
}
fn adt_kind(&self, def: AdtDef) -> AdtKind {
/// Returns the kind of a given algebraic data type.
pub fn adt_kind(&self, def: AdtDef) -> AdtKind {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables)
}
fn adt_is_box(&self, def: AdtDef) -> bool {
/// Returns if the ADT is a box.
pub fn adt_is_box(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).is_box()
}
fn adt_is_simd(&self, def: AdtDef) -> bool {
/// Returns whether this ADT is simd.
pub fn adt_is_simd(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).repr().simd()
}
fn adt_is_cstr(&self, def: AdtDef) -> bool {
/// Returns whether this definition is a C string.
pub fn adt_is_cstr(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
tables.tcx.is_lang_item(def_id, LangItem::CStr)
}
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
/// Retrieve the function signature for the given generic arguments.
pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
@@ -373,7 +407,8 @@ fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
sig.stable(&mut *tables)
}
fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
/// Retrieve the intrinsic definition if the item corresponds one.
pub fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.internal(&mut *tables, tcx);
@@ -381,14 +416,16 @@ fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
intrinsic.map(|_| IntrinsicDef(def))
}
fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
/// Retrieve the plain function name of an intrinsic.
pub fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
tcx.intrinsic(def_id).unwrap().name.to_string()
}
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
/// Retrieve the closure signature for the given generic arguments.
pub fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let args_ref = args.internal(&mut *tables, tcx);
@@ -396,25 +433,28 @@ fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
sig.stable(&mut *tables)
}
fn adt_variants_len(&self, def: AdtDef) -> usize {
/// The number of variants in this ADT.
pub fn adt_variants_len(&self, def: AdtDef) -> usize {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).variants().len()
}
fn variant_name(&self, def: VariantDef) -> Symbol {
/// The name of a variant.
pub fn variant_name(&self, def: VariantDef) -> Symbol {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).name.to_string()
}
fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
pub fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect()
}
fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
/// Evaluate constant as a target usize.
pub fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let mir_const = cnst.internal(&mut *tables, tcx);
@@ -422,7 +462,7 @@ fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
.try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized())
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
}
fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
pub fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let mir_const = cnst.internal(&mut *tables, tcx);
@@ -431,7 +471,8 @@ fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
}
fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
/// Create a new zero-sized constant.
pub fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let ty_internal = ty.internal(&mut *tables, tcx);
@@ -456,7 +497,8 @@ fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
.stable(&mut *tables))
}
fn new_const_str(&self, value: &str) -> MirConst {
/// Create a new constant that represents the given string value.
pub fn new_const_str(&self, value: &str) -> MirConst {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let ty = ty::Ty::new_static_str(tcx);
@@ -467,12 +509,14 @@ fn new_const_str(&self, value: &str) -> MirConst {
mir::Const::from_value(val, ty).stable(&mut tables)
}
fn new_const_bool(&self, value: bool) -> MirConst {
/// Create a new constant that represents the given boolean value.
pub fn new_const_bool(&self, value: bool) -> MirConst {
let mut tables = self.0.borrow_mut();
mir::Const::from_bool(tables.tcx, value).stable(&mut tables)
}
fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
/// Create a new constant that represents the given value.
pub fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
@@ -487,7 +531,7 @@ fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, E
Ok(mir::Const::from_scalar(tcx, mir::interpret::Scalar::Int(scalar), ty)
.stable(&mut tables))
}
fn try_new_ty_const_uint(
pub fn try_new_ty_const_uint(
&self,
value: u128,
uint_ty: UintTy,
@@ -509,27 +553,35 @@ fn try_new_ty_const_uint(
.stable(&mut *tables))
}
fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
/// Create a new type from the given kind.
pub fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let internal_kind = kind.internal(&mut *tables, tcx);
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
}
fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
/// Create a new box type, `Box<T>`, for the given inner type `T`.
pub fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let inner = ty.internal(&mut *tables, tcx);
ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables)
}
fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
/// Returns the type of given crate item.
pub fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables)
}
fn def_ty_with_args(&self, item: stable_mir::DefId, args: &GenericArgs) -> stable_mir::ty::Ty {
/// Returns the type of given definition instantiated with the given arguments.
pub fn def_ty_with_args(
&self,
item: stable_mir::DefId,
args: &GenericArgs,
) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let args = args.internal(&mut *tables, tcx);
@@ -544,33 +596,38 @@ fn def_ty_with_args(&self, item: stable_mir::DefId, args: &GenericArgs) -> stabl
.stable(&mut *tables)
}
fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
/// Returns literal value of a const as a string.
pub fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
cnst.internal(&mut *tables, tcx).to_string()
}
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
/// `Span` of an item.
pub fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
let mut tables = self.0.borrow_mut();
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
}
fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
/// Obtain the representation of a type.
pub fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
let tables = self.0.borrow_mut();
tables.types[ty].to_string()
}
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
/// Obtain the representation of a type.
pub fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
let mut tables = self.0.borrow_mut();
tables.types[ty].kind().stable(&mut *tables)
}
fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
pub fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
let tables = self.0.borrow_mut();
tables.ty_consts[ct].to_string()
}
fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
/// Get the discriminant Ty for this Ty if there's one.
pub fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let internal_kind = ty.internal(&mut *tables, tcx);
@@ -578,7 +635,8 @@ fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables)
}
fn instance_body(&self, def: InstanceDef) -> Option<Body> {
/// Get the body of an Instance which is already monomorphized.
pub fn instance_body(&self, def: InstanceDef) -> Option<Body> {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
tables
@@ -586,63 +644,74 @@ fn instance_body(&self, def: InstanceDef) -> Option<Body> {
.then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
}
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
/// Get the instance type with generic instantiations applied and lifetimes erased.
pub fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables)
}
fn instance_args(&self, def: InstanceDef) -> GenericArgs {
/// Get the instantiation types.
pub fn instance_args(&self, def: InstanceDef) -> GenericArgs {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
instance.args.stable(&mut *tables)
}
fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
/// Get an instance ABI.
pub fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
}
fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
/// Get the ABI of a function pointer.
pub fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let sig = fn_ptr.internal(&mut *tables, tcx);
Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables))
}
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
/// Get the instance.
pub fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
let mut tables = self.0.borrow_mut();
let def_id = tables.instances[def].def_id();
tables.create_def_id(def_id)
}
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
/// Get the instance mangled name.
pub fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
let tables = self.0.borrow_mut();
let instance = tables.instances[instance];
tables.tcx.symbol_name(instance).name.to_string()
}
fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
/// Check if this is an empty DropGlue shim.
pub fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
let tables = self.0.borrow_mut();
let instance = tables.instances[def];
matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
}
fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
/// Check if this is an empty AsyncDropGlueCtor shim.
pub fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
let tables = self.0.borrow_mut();
let instance = tables.instances[def];
matches!(instance.def, ty::InstanceKind::AsyncDropGlueCtorShim(_, None))
}
fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
/// Convert a non-generic crate item into an instance.
/// This function will panic if the item is generic.
pub fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
Instance::mono(tables.tcx, def_id).stable(&mut *tables)
}
fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
/// Item requires monomorphization.
pub fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
let tables = self.0.borrow();
let def_id = tables[def_id];
let generics = tables.tcx.generics_of(def_id);
@@ -650,7 +719,8 @@ fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
result
}
fn resolve_instance(
/// Resolve an instance from the given function definition and generic arguments.
pub fn resolve_instance(
&self,
def: stable_mir::ty::FnDef,
args: &stable_mir::ty::GenericArgs,
@@ -670,7 +740,8 @@ fn resolve_instance(
}
}
fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
/// Resolve an instance for drop_in_place for the given type.
pub fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let internal_ty = ty.internal(&mut *tables, tcx);
@@ -678,7 +749,8 @@ fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono
instance.stable(&mut *tables)
}
fn resolve_for_fn_ptr(
/// Resolve instance for a function pointer.
pub fn resolve_for_fn_ptr(
&self,
def: FnDef,
args: &GenericArgs,
@@ -696,7 +768,8 @@ fn resolve_for_fn_ptr(
.stable(&mut *tables)
}
fn resolve_closure(
/// Resolve instance for a closure with the requested type.
pub fn resolve_closure(
&self,
def: ClosureDef,
args: &GenericArgs,
@@ -713,7 +786,8 @@ fn resolve_closure(
)
}
fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
/// Try to evaluate an instance into a constant.
pub fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
let tcx = tables.tcx;
@@ -733,21 +807,24 @@ fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Er
.map_err(|e| e.stable(&mut *tables))?
}
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
/// Evaluate a static's initializer.
pub fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = def.0.internal(&mut *tables, tcx);
tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
}
fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
/// Retrieve global allocation for the given allocation ID.
pub fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let alloc_id = alloc.internal(&mut *tables, tcx);
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
}
fn vtable_allocation(
/// Retrieve the id for the virtual table.
pub fn vtable_allocation(
&self,
global_alloc: &GlobalAlloc,
) -> Option<stable_mir::mir::alloc::AllocId> {
@@ -765,7 +842,7 @@ fn vtable_allocation(
Some(alloc_id.stable(&mut *tables))
}
fn krate(&self, def_id: stable_mir::DefId) -> Crate {
pub fn krate(&self, def_id: stable_mir::DefId) -> Crate {
let tables = self.0.borrow();
smir_crate(tables.tcx, tables[def_id].krate)
}
@@ -773,7 +850,7 @@ fn krate(&self, def_id: stable_mir::DefId) -> Crate {
/// Retrieve the instance name for diagnostic messages.
///
/// This will return the specialized name, e.g., `Vec<char>::new`.
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
pub fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
let tables = self.0.borrow_mut();
let instance = tables.instances[def];
if trimmed {
@@ -787,7 +864,8 @@ fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
}
}
fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
/// Get the layout of a type.
pub fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let ty = ty.internal(&mut *tables, tcx);
@@ -795,19 +873,22 @@ fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
Ok(layout.stable(&mut *tables))
}
fn layout_shape(&self, id: Layout) -> LayoutShape {
/// Get the layout shape.
pub fn layout_shape(&self, id: Layout) -> LayoutShape {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
id.internal(&mut *tables, tcx).0.stable(&mut *tables)
}
fn place_pretty(&self, place: &Place) -> String {
/// Get a debug string representation of a place.
pub fn place_pretty(&self, place: &Place) -> String {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
format!("{:?}", place.internal(&mut *tables, tcx))
}
fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
/// Get the resulting type of binary operation.
pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let rhs_internal = rhs.internal(&mut *tables, tcx);
@@ -816,7 +897,8 @@ fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
ty.stable(&mut *tables)
}
fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
/// Get the resulting type of unary operation.
pub fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let arg_internal = arg.internal(&mut *tables, tcx);
@@ -824,7 +906,8 @@ fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
ty.stable(&mut *tables)
}
fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems {
/// Get all associated items of a definition.
pub fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let def_id = tables[def_id];
@@ -840,8 +923,6 @@ fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems
}
}
pub(crate) struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
/// Implement error handling for extracting function ABI information.
impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> {
type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, ty::Ty<'tcx>>, Error>;
+1 -1
View File
@@ -25,7 +25,7 @@
mod alloc;
mod builder;
pub(crate) mod context;
pub mod context;
mod convert;
pub struct Tables<'tcx> {
@@ -5,6 +5,7 @@
use std::cell::Cell;
use rustc_smir::context::SmirCtxt;
use stable_mir::abi::{FnAbi, Layout, LayoutShape};
use stable_mir::crate_def::Attribute;
use stable_mir::mir::alloc::{AllocId, GlobalAlloc};
@@ -22,47 +23,116 @@
ItemKind, Symbol, TraitDecls, mir,
};
use crate::stable_mir;
use crate::{rustc_smir, stable_mir};
/// Stable public API for querying compiler information.
///
/// All queries are delegated to an internal [`SmirCtxt`] that provides
/// similar APIs but based on internal rustc constructs.
///
/// Do not use this directly. This is currently used in the macro expansion.
pub(crate) struct SmirInterface<'tcx> {
pub(crate) cx: SmirCtxt<'tcx>,
}
impl<'tcx> SmirInterface<'tcx> {
pub(crate) fn entry_fn(&self) -> Option<CrateItem> {
self.cx.entry_fn()
}
/// This trait defines the interface between stable_mir and the Rust compiler.
/// Do not use this directly.
pub trait Context {
fn entry_fn(&self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
fn all_local_items(&self) -> CrateItems;
pub(crate) fn all_local_items(&self) -> CrateItems {
self.cx.all_local_items()
}
/// Retrieve the body of a function.
/// This function will panic if the body is not available.
fn mir_body(&self, item: DefId) -> mir::Body;
pub(crate) fn mir_body(&self, item: DefId) -> mir::Body {
self.cx.mir_body(item)
}
/// Check whether the body of a function is available.
fn has_body(&self, item: DefId) -> bool;
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
pub(crate) fn has_body(&self, item: DefId) -> bool {
self.cx.has_body(item)
}
pub(crate) fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> {
self.cx.foreign_modules(crate_num)
}
/// Retrieve all functions defined in this crate.
fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>;
pub(crate) fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
self.cx.crate_functions(crate_num)
}
/// Retrieve all static items defined in this crate.
fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>;
fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
fn all_trait_decls(&self) -> TraitDecls;
fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls;
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&self) -> ImplTraitDecls;
fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls;
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&self, def_id: DefId) -> Generics;
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
pub(crate) fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
self.cx.crate_statics(crate_num)
}
pub(crate) fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule {
self.cx.foreign_module(mod_def)
}
pub(crate) fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> {
self.cx.foreign_items(mod_def)
}
pub(crate) fn all_trait_decls(&self) -> TraitDecls {
self.cx.all_trait_decls()
}
pub(crate) fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls {
self.cx.trait_decls(crate_num)
}
pub(crate) fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl {
self.cx.trait_decl(trait_def)
}
pub(crate) fn all_trait_impls(&self) -> ImplTraitDecls {
self.cx.all_trait_impls()
}
pub(crate) fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls {
self.cx.trait_impls(crate_num)
}
pub(crate) fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait {
self.cx.trait_impl(trait_impl)
}
pub(crate) fn generics_of(&self, def_id: DefId) -> Generics {
self.cx.generics_of(def_id)
}
pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates {
self.cx.predicates_of(def_id)
}
pub(crate) fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates {
self.cx.explicit_predicates_of(def_id)
}
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
pub(crate) fn local_crate(&self) -> Crate {
self.cx.local_crate()
}
/// Retrieve a list of all external crates.
fn external_crates(&self) -> Vec<Crate>;
pub(crate) fn external_crates(&self) -> Vec<Crate> {
self.cx.external_crates()
}
/// Find a crate with the given name.
fn find_crates(&self, name: &str) -> Vec<Crate>;
pub(crate) fn find_crates(&self, name: &str) -> Vec<Crate> {
self.cx.find_crates(name)
}
/// Returns the name of given `DefId`
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
/// Returns the name of given `DefId`.
pub(crate) fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol {
self.cx.def_name(def_id, trimmed)
}
/// Return registered tool attributes with the given attribute name.
///
@@ -71,218 +141,362 @@ pub trait Context {
///
/// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
pub(crate) fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> {
self.cx.tool_attrs(def_id, attr)
}
/// Get all tool attributes of a definition.
fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute>;
pub(crate) fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> {
self.cx.all_tool_attrs(def_id)
}
/// Returns printable, human readable form of `Span`
fn span_to_string(&self, span: Span) -> String;
/// Returns printable, human readable form of `Span`.
pub(crate) fn span_to_string(&self, span: Span) -> String {
self.cx.span_to_string(span)
}
/// Return filename from given `Span`, for diagnostic purposes
fn get_filename(&self, span: &Span) -> Filename;
/// Return filename from given `Span`, for diagnostic purposes.
pub(crate) fn get_filename(&self, span: &Span) -> Filename {
self.cx.get_filename(span)
}
/// Return lines corresponding to this `Span`
fn get_lines(&self, span: &Span) -> LineInfo;
/// Return lines corresponding to this `Span`.
pub(crate) fn get_lines(&self, span: &Span) -> LineInfo {
self.cx.get_lines(span)
}
/// Returns the `kind` of given `DefId`
fn item_kind(&self, item: CrateItem) -> ItemKind;
/// Returns the `kind` of given `DefId`.
pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind {
self.cx.item_kind(item)
}
/// Returns whether this is a foreign item.
fn is_foreign_item(&self, item: DefId) -> bool;
pub(crate) fn is_foreign_item(&self, item: DefId) -> bool {
self.cx.is_foreign_item(item)
}
/// Returns the kind of a given foreign item.
fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind;
pub(crate) fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
self.cx.foreign_item_kind(def)
}
/// Returns the kind of a given algebraic data type
fn adt_kind(&self, def: AdtDef) -> AdtKind;
/// Returns the kind of a given algebraic data type.
pub(crate) fn adt_kind(&self, def: AdtDef) -> AdtKind {
self.cx.adt_kind(def)
}
/// Returns if the ADT is a box.
fn adt_is_box(&self, def: AdtDef) -> bool;
pub(crate) fn adt_is_box(&self, def: AdtDef) -> bool {
self.cx.adt_is_box(def)
}
/// Returns whether this ADT is simd.
fn adt_is_simd(&self, def: AdtDef) -> bool;
pub(crate) fn adt_is_simd(&self, def: AdtDef) -> bool {
self.cx.adt_is_simd(def)
}
/// Returns whether this definition is a C string.
fn adt_is_cstr(&self, def: AdtDef) -> bool;
pub(crate) fn adt_is_cstr(&self, def: AdtDef) -> bool {
self.cx.adt_is_cstr(def)
}
/// Retrieve the function signature for the given generic arguments.
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig;
pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
self.cx.fn_sig(def, args)
}
/// Retrieve the intrinsic definition if the item corresponds one.
fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>;
pub(crate) fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> {
self.cx.intrinsic(item)
}
/// Retrieve the plain function name of an intrinsic.
fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
pub(crate) fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
self.cx.intrinsic_name(def)
}
/// Retrieve the closure signature for the given generic arguments.
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
pub(crate) fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
self.cx.closure_sig(args)
}
/// The number of variants in this ADT.
fn adt_variants_len(&self, def: AdtDef) -> usize;
pub(crate) fn adt_variants_len(&self, def: AdtDef) -> usize {
self.cx.adt_variants_len(def)
}
/// The name of a variant.
fn variant_name(&self, def: VariantDef) -> Symbol;
fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef>;
pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol {
self.cx.variant_name(def)
}
pub(crate) fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
self.cx.variant_fields(def)
}
/// Evaluate constant as a target usize.
fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error>;
fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error>;
pub(crate) fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
self.cx.eval_target_usize(cnst)
}
pub(crate) fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
self.cx.eval_target_usize_ty(cnst)
}
/// Create a new zero-sized constant.
fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error>;
pub(crate) fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
self.cx.try_new_const_zst(ty)
}
/// Create a new constant that represents the given string value.
fn new_const_str(&self, value: &str) -> MirConst;
pub(crate) fn new_const_str(&self, value: &str) -> MirConst {
self.cx.new_const_str(value)
}
/// Create a new constant that represents the given boolean value.
fn new_const_bool(&self, value: bool) -> MirConst;
pub(crate) fn new_const_bool(&self, value: bool) -> MirConst {
self.cx.new_const_bool(value)
}
/// Create a new constant that represents the given value.
fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error>;
fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error>;
pub(crate) fn try_new_const_uint(
&self,
value: u128,
uint_ty: UintTy,
) -> Result<MirConst, Error> {
self.cx.try_new_const_uint(value, uint_ty)
}
pub(crate) fn try_new_ty_const_uint(
&self,
value: u128,
uint_ty: UintTy,
) -> Result<TyConst, Error> {
self.cx.try_new_ty_const_uint(value, uint_ty)
}
/// Create a new type from the given kind.
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
pub(crate) fn new_rigid_ty(&self, kind: RigidTy) -> Ty {
self.cx.new_rigid_ty(kind)
}
/// Create a new box type, `Box<T>`, for the given inner type `T`.
fn new_box_ty(&self, ty: Ty) -> Ty;
pub(crate) fn new_box_ty(&self, ty: Ty) -> Ty {
self.cx.new_box_ty(ty)
}
/// Returns the type of given crate item.
fn def_ty(&self, item: DefId) -> Ty;
pub(crate) fn def_ty(&self, item: DefId) -> Ty {
self.cx.def_ty(item)
}
/// Returns the type of given definition instantiated with the given arguments.
fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
pub(crate) fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty {
self.cx.def_ty_with_args(item, args)
}
/// Returns literal value of a const as a string.
fn mir_const_pretty(&self, cnst: &MirConst) -> String;
pub(crate) fn mir_const_pretty(&self, cnst: &MirConst) -> String {
self.cx.mir_const_pretty(cnst)
}
/// `Span` of an item
fn span_of_an_item(&self, def_id: DefId) -> Span;
/// `Span` of an item.
pub(crate) fn span_of_an_item(&self, def_id: DefId) -> Span {
self.cx.span_of_an_item(def_id)
}
fn ty_const_pretty(&self, ct: TyConstId) -> String;
pub(crate) fn ty_const_pretty(&self, ct: TyConstId) -> String {
self.cx.ty_const_pretty(ct)
}
/// Obtain the representation of a type.
fn ty_pretty(&self, ty: Ty) -> String;
pub(crate) fn ty_pretty(&self, ty: Ty) -> String {
self.cx.ty_pretty(ty)
}
/// Obtain the representation of a type.
fn ty_kind(&self, ty: Ty) -> TyKind;
pub(crate) fn ty_kind(&self, ty: Ty) -> TyKind {
self.cx.ty_kind(ty)
}
// Get the discriminant Ty for this Ty if there's one.
fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty;
/// Get the discriminant Ty for this Ty if there's one.
pub(crate) fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty {
self.cx.rigid_ty_discriminant_ty(ty)
}
/// Get the body of an Instance which is already monomorphized.
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option<Body> {
self.cx.instance_body(instance)
}
/// Get the instance type with generic instantiations applied and lifetimes erased.
fn instance_ty(&self, instance: InstanceDef) -> Ty;
pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty {
self.cx.instance_ty(instance)
}
/// Get the instantiation types.
fn instance_args(&self, def: InstanceDef) -> GenericArgs;
pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs {
self.cx.instance_args(def)
}
/// Get the instance.
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
pub(crate) fn instance_def_id(&self, instance: InstanceDef) -> DefId {
self.cx.instance_def_id(instance)
}
/// Get the instance mangled name.
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol;
pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
self.cx.instance_mangled_name(instance)
}
/// Check if this is an empty DropGlue shim.
fn is_empty_drop_shim(&self, def: InstanceDef) -> bool;
pub(crate) fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
self.cx.is_empty_drop_shim(def)
}
/// Check if this is an empty AsyncDropGlueCtor shim.
fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool;
pub(crate) fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
self.cx.is_empty_async_drop_ctor_shim(def)
}
/// Convert a non-generic crate item into an instance.
/// This function will panic if the item is generic.
fn mono_instance(&self, def_id: DefId) -> Instance;
pub(crate) fn mono_instance(&self, def_id: DefId) -> Instance {
self.cx.mono_instance(def_id)
}
/// Item requires monomorphization.
fn requires_monomorphization(&self, def_id: DefId) -> bool;
pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool {
self.cx.requires_monomorphization(def_id)
}
/// Resolve an instance from the given function definition and generic arguments.
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
pub(crate) fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
self.cx.resolve_instance(def, args)
}
/// Resolve an instance for drop_in_place for the given type.
fn resolve_drop_in_place(&self, ty: Ty) -> Instance;
pub(crate) fn resolve_drop_in_place(&self, ty: Ty) -> Instance {
self.cx.resolve_drop_in_place(ty)
}
/// Resolve instance for a function pointer.
fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
pub(crate) fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
self.cx.resolve_for_fn_ptr(def, args)
}
/// Resolve instance for a closure with the requested type.
fn resolve_closure(
pub(crate) fn resolve_closure(
&self,
def: ClosureDef,
args: &GenericArgs,
kind: ClosureKind,
) -> Option<Instance>;
) -> Option<Instance> {
self.cx.resolve_closure(def, args, kind)
}
/// Evaluate a static's initializer.
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
pub(crate) fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
self.cx.eval_static_initializer(def)
}
/// Try to evaluate an instance into a constant.
fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error>;
pub(crate) fn eval_instance(
&self,
def: InstanceDef,
const_ty: Ty,
) -> Result<Allocation, Error> {
self.cx.eval_instance(def, const_ty)
}
/// Retrieve global allocation for the given allocation ID.
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
pub(crate) fn global_alloc(&self, id: AllocId) -> GlobalAlloc {
self.cx.global_alloc(id)
}
/// Retrieve the id for the virtual table.
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
fn krate(&self, def_id: DefId) -> Crate;
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
pub(crate) fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> {
self.cx.vtable_allocation(global_alloc)
}
pub(crate) fn krate(&self, def_id: DefId) -> Crate {
self.cx.krate(def_id)
}
pub(crate) fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
self.cx.instance_name(def, trimmed)
}
/// Return information about the target machine.
fn target_info(&self) -> MachineInfo;
pub(crate) fn target_info(&self) -> MachineInfo {
self.cx.target_info()
}
/// Get an instance ABI.
fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>;
pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
self.cx.instance_abi(def)
}
/// Get the ABI of a function pointer.
fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>;
pub(crate) fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
self.cx.fn_ptr_abi(fn_ptr)
}
/// Get the layout of a type.
fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>;
pub(crate) fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
self.cx.ty_layout(ty)
}
/// Get the layout shape.
fn layout_shape(&self, id: Layout) -> LayoutShape;
pub(crate) fn layout_shape(&self, id: Layout) -> LayoutShape {
self.cx.layout_shape(id)
}
/// Get a debug string representation of a place.
fn place_pretty(&self, place: &Place) -> String;
pub(crate) fn place_pretty(&self, place: &Place) -> String {
self.cx.place_pretty(place)
}
/// Get the resulting type of binary operation.
fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty;
pub(crate) fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
self.cx.binop_ty(bin_op, rhs, lhs)
}
/// Get the resulting type of unary operation.
fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty;
pub(crate) fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
self.cx.unop_ty(un_op, arg)
}
/// Get all associated items of a definition.
fn associated_items(&self, def_id: DefId) -> AssocItems;
pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems {
self.cx.associated_items(def_id)
}
}
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
// datastructures and stable MIR datastructures
// A thread local variable that stores a pointer to [`SmirInterface`].
scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>);
pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error>
pub(crate) fn run<'tcx, T, F>(interface: &SmirInterface<'tcx>, f: F) -> Result<T, Error>
where
F: FnOnce() -> T,
{
if TLV.is_set() {
Err(Error::from("StableMIR already running"))
} else {
let ptr: *const () = (&raw const context) as _;
let ptr: *const () = (interface as *const SmirInterface<'tcx>) as *const ();
TLV.set(&Cell::new(ptr), || Ok(f()))
}
}
/// Execute the given function with access the compiler [Context].
/// Execute the given function with access the [`SmirInterface`].
///
/// I.e., This function will load the current context and calls a function with it.
/// I.e., This function will load the current interface and calls a function with it.
/// Do not nest these, as that will ICE.
pub(crate) fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
pub(crate) fn with<R>(f: impl FnOnce(&SmirInterface<'_>) -> R) -> R {
assert!(TLV.is_set());
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
f(unsafe { *(ptr as *const &dyn Context) })
f(unsafe { &*(ptr as *const SmirInterface<'_>) })
})
}
+7 -20
View File
@@ -9,7 +9,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt};
@@ -551,19 +551,6 @@ struct ImplicitLifetimeFinder {
impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
let make_suggestion = |lifetime: &hir::Lifetime| {
if lifetime.is_anon_in_path == IsAnonInPath::Yes
&& lifetime.ident.span.is_empty()
{
format!("{}, ", self.suggestion_param_name)
} else if lifetime.ident.name == kw::UnderscoreLifetime
&& lifetime.ident.span.is_empty()
{
format!("{} ", self.suggestion_param_name)
} else {
self.suggestion_param_name.clone()
}
};
match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
for segment in path.segments {
@@ -572,7 +559,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
matches!(
arg,
hir::GenericArg::Lifetime(lifetime)
if lifetime.is_anon_in_path == IsAnonInPath::Yes
if lifetime.is_syntactically_hidden()
)
}) {
self.suggestions.push((
@@ -591,10 +578,10 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
if let hir::GenericArg::Lifetime(lifetime) = arg
&& lifetime.is_anonymous()
{
self.suggestions.push((
lifetime.ident.span,
make_suggestion(lifetime),
));
self.suggestions.push(
lifetime
.suggestion(&self.suggestion_param_name),
);
}
}
}
@@ -602,7 +589,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
}
}
hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime)));
self.suggestions.push(lifetime.suggestion(&self.suggestion_param_name));
}
_ => {}
}
@@ -117,8 +117,7 @@ fn relate_mir_and_user_args<'tcx>(
CRATE_DEF_ID,
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
);
let instantiated_predicate =
ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
let instantiated_predicate = ocx.normalize(&cause, param_env, instantiated_predicate);
ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
}
+1 -1
View File
@@ -139,7 +139,7 @@ pub struct Iter<'a, T: 'a> {
#[stable(feature = "collection_debug", since = "1.17.0")]
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Iter").field(&self.iter.clone()).finish()
f.debug_tuple("Iter").field(&self.iter).finish()
}
}
+1 -3
View File
@@ -549,8 +549,6 @@ pub const fn get(&self) -> T {
/// # Examples
///
/// ```
/// #![feature(cell_update)]
///
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
@@ -558,7 +556,7 @@ pub const fn get(&self) -> T {
/// assert_eq!(c.get(), 6);
/// ```
#[inline]
#[unstable(feature = "cell_update", issue = "50186")]
#[stable(feature = "cell_update", since = "CURRENT_RUSTC_VERSION")]
pub fn update(&self, f: impl FnOnce(T) -> T) {
let old = self.get();
self.set(f(old));
-1
View File
@@ -12,7 +12,6 @@
#![feature(async_iterator)]
#![feature(bigint_helper_methods)]
#![feature(bstr)]
#![feature(cell_update)]
#![feature(char_max_len)]
#![feature(clone_to_uninit)]
#![feature(const_eval_select)]
+3
View File
@@ -973,6 +973,9 @@ pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
/// Returns an array of length `N` with the results of each query. For soundness, at most one
/// mutable reference will be returned to any value. `None` will be used if the key is missing.
///
/// This method performs a check to ensure there are no duplicate keys, which currently has a time-complexity of O(n^2),
/// so be careful when passing many keys.
///
/// # Panics
///
/// Panics if any keys are overlapping.
+36
View File
@@ -1100,3 +1100,39 @@ pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io:
pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
sys::fs::chroot(dir.as_ref())
}
/// Create a FIFO special file at the specified path with the specified mode.
///
/// # Examples
///
/// ```no_run
/// # #![feature(unix_mkfifo)]
/// # #[cfg(not(unix))]
/// # fn main() {}
/// # #[cfg(unix)]
/// # fn main() -> std::io::Result<()> {
/// # use std::{
/// # os::unix::fs::{mkfifo, PermissionsExt},
/// # fs::{File, Permissions, remove_file},
/// # io::{Write, Read},
/// # };
/// # let _ = remove_file("/tmp/fifo");
/// mkfifo("/tmp/fifo", Permissions::from_mode(0o774))?;
///
/// let mut wx = File::options().read(true).write(true).open("/tmp/fifo")?;
/// let mut rx = File::open("/tmp/fifo")?;
///
/// wx.write_all(b"hello, world!")?;
/// drop(wx);
///
/// let mut s = String::new();
/// rx.read_to_string(&mut s)?;
///
/// assert_eq!(s, "hello, world!");
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "unix_mkfifo", issue = "139324")]
pub fn mkfifo<P: AsRef<Path>>(path: P, permissions: Permissions) -> io::Result<()> {
sys::fs::mkfifo(path.as_ref(), permissions.mode())
}
+20
View File
@@ -55,3 +55,23 @@ fn write_vectored_at() {
let content = fs::read(&filename).unwrap();
assert_eq!(&content, expected);
}
#[test]
fn test_mkfifo() {
let tmp_dir = crate::test_helpers::tmpdir();
let fifo = tmp_dir.path().join("fifo");
mkfifo(&fifo, Permissions::from_mode(0o774)).unwrap();
let mut wx = fs::File::options().read(true).write(true).open(&fifo).unwrap();
let mut rx = fs::File::open(fifo).unwrap();
wx.write_all(b"hello, world!").unwrap();
drop(wx);
let mut s = String::new();
rx.read_to_string(&mut s).unwrap();
assert_eq!(s, "hello, world!");
}
+1 -1
View File
@@ -9,7 +9,7 @@
if #[cfg(target_family = "unix")] {
mod unix;
use unix as imp;
pub use unix::{chown, fchown, lchown};
pub use unix::{chown, fchown, lchown, mkfifo};
#[cfg(not(target_os = "fuchsia"))]
pub use unix::chroot;
pub(crate) use unix::debug_assert_fd_is_open;
+6
View File
@@ -2137,6 +2137,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
Err(io::const_error!(io::ErrorKind::Unsupported, "chroot not supported by vxworks"))
}
pub fn mkfifo(path: &Path, mode: u32) -> io::Result<()> {
run_path_with_cstr(path, &|path| {
cvt(unsafe { libc::mkfifo(path.as_ptr(), mode.try_into().unwrap()) }).map(|_| ())
})
}
pub use remove_dir_impl::remove_dir_all;
// Fallback for REDOX, ESP-ID, Horizon, Vita, Vxworks and Miri
+3 -3
View File
@@ -683,7 +683,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
match EditorKind::prompt_user() {
Ok(editor_kind) => {
if let Some(editor_kind) = editor_kind {
while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
while !t!(create_editor_settings_maybe(config, &editor_kind)) {}
} else {
println!("Ok, skipping editor setup!");
}
@@ -695,7 +695,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
/// Create the recommended editor LSP config file for rustc development, or just print it
/// If this method should be re-called, it returns `false`.
fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Result<bool> {
fn create_editor_settings_maybe(config: &Config, editor: &EditorKind) -> io::Result<bool> {
let hashes = editor.hashes();
let (current_hash, historical_hashes) = hashes.split_last().unwrap();
let settings_path = editor.settings_path(config);
@@ -752,7 +752,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
// exists but user modified, back it up
Some(false) => {
// exists and is not current version or outdated, so back it up
let backup = settings_path.clone().with_extension(editor.backup_extension());
let backup = settings_path.with_extension(editor.backup_extension());
eprintln!(
"WARNING: copying `{}` to `{}`",
settings_path.file_name().unwrap().to_str().unwrap(),
@@ -54,4 +54,25 @@ if let [b] = &mut *v {
assert_eq!(v, [Box::new(Some(2))]);
```
Additionally, when `deref_patterns` is enabled, string literal patterns may be written where `str`
is expected. Likewise, byte string literal patterns may be written where `[u8]` or `[u8; _]` is
expected. This lets them be used in `deref!(_)` patterns:
```rust
# #![feature(deref_patterns)]
# #![allow(incomplete_features)]
match ("test".to_string(), b"test".to_vec()) {
(deref!("test"), deref!(b"test")) => {}
_ => panic!(),
}
// Matching on slices and arrays using literals is possible elsewhere as well:
match *"test" {
"test" => {}
_ => panic!(),
}
```
Implicit deref pattern syntax is not yet supported for string or byte string literals.
[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
-1
View File
@@ -1,6 +1,5 @@
#![feature(rustc_private)]
#![feature(cfg_match)]
#![feature(cell_update)]
#![feature(float_gamma)]
#![feature(float_erf)]
#![feature(map_try_insert)]
+1 -1
View File
@@ -145,7 +145,7 @@ fn get_item<'a>(
fn main() {
let path = "alloc_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
@@ -219,7 +219,7 @@ fn get_item<'a>(
fn main() {
let path = "alloc_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--edition=2021".to_string(),
"--crate-name".to_string(),
@@ -85,7 +85,7 @@ fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
fn main() {
let path = "assoc_items.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
@@ -57,7 +57,7 @@ fn get_item<'a>(
fn main() {
let path = "attribute_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
+1 -1
View File
@@ -81,7 +81,7 @@ fn visit_terminator(&mut self, term: &Terminator, _loc: Location) {
fn main() {
let path = "binop_input.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
run!(args, test_binops).unwrap();
}
@@ -84,7 +84,7 @@ fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
fn main() {
let path = "crate_definitions.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
+1 -1
View File
@@ -76,7 +76,7 @@ fn check_fn_def(ty: Ty) {
fn main() {
let path = "defs_ty_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),
+1 -1
View File
@@ -112,7 +112,7 @@ fn get_instances(body: mir::Body) -> Vec<Instance> {
fn main() {
let path = "defs_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),
@@ -58,7 +58,7 @@ fn test_foreign() -> ControlFlow<()> {
fn main() {
let path = "foreign_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),
@@ -87,7 +87,7 @@ fn test_body(body: mir::Body) {
fn main() {
let path = "instance_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),
@@ -115,7 +115,7 @@ fn visit_terminator(&mut self, term: &Terminator, _loc: Location) {
fn main() {
let path = "binop_input.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
run!(args, test_intrinsics).unwrap();
}
@@ -47,7 +47,7 @@ fn test_item_kind() -> ControlFlow<()> {
fn main() {
let path = "item_kind_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),
@@ -61,7 +61,7 @@ fn check_ty(ty: Ty) {
fn main() {
let path = "normalization_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),
@@ -72,7 +72,7 @@ fn assert_impl(impl_names: &HashSet<String>, target: &str) {
fn main() {
let path = "trait_queries.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
@@ -120,7 +120,7 @@ fn get_item<'a>(
fn main() {
let path = "transform_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
@@ -78,7 +78,7 @@ fn visit_place(&mut self, place: &Place, _ptx: PlaceContext, _loc: Location) {
fn main() {
let path = "ty_fold_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),
@@ -25,40 +25,42 @@
fn main() {
let path = "input_compilation_result_test.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), path.to_string()];
test_continue(args.clone());
test_break(args.clone());
test_failed(args.clone());
test_skipped(args.clone());
let args = &["rustc".to_string(), path.to_string()];
test_continue(args);
test_break(args);
test_failed(args);
test_skipped(args);
test_captured(args)
}
fn test_continue(args: Vec<String>) {
fn test_continue(args: &[String]) {
let result = run!(args, || ControlFlow::Continue::<(), bool>(true));
assert_eq!(result, Ok(true));
}
fn test_break(args: Vec<String>) {
fn test_break(args: &[String]) {
let result = run!(args, || ControlFlow::Break::<bool, i32>(false));
assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false)));
}
#[allow(unreachable_code)]
fn test_skipped(mut args: Vec<String>) {
fn test_skipped(args: &[String]) {
let mut args = args.to_vec();
args.push("--version".to_string());
let result = run!(args, || unreachable!() as ControlFlow<()>);
let result = run!(&args, || unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::Skipped));
}
#[allow(unreachable_code)]
fn test_failed(mut args: Vec<String>) {
fn test_failed(args: &[String]) {
let mut args = args.to_vec();
args.push("--cfg=broken".to_string());
let result = run!(args, || unreachable!() as ControlFlow<()>);
let result = run!(&args, || unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::Failed));
}
/// Test that we are able to pass a closure and set the return according to the captured value.
fn test_captured(args: Vec<String>) {
fn test_captured(args: &[String]) {
let captured = "10".to_string();
let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len()));
assert_eq!(result, Ok(captured.len()));
+1 -1
View File
@@ -186,7 +186,7 @@ fn get_item<'a>(
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
+1 -1
View File
@@ -146,7 +146,7 @@ fn get_item<'a>(
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
@@ -40,7 +40,7 @@ fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn main() {
let path = "internal_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
+1 -1
View File
@@ -46,7 +46,7 @@ fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn main() {
let path = "internal_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
+2 -2
View File
@@ -183,14 +183,14 @@ fn visit_terminator(&mut self, term: &mut mir::Terminator, location: mir::visit:
fn main() {
let path = "sim_visitor_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args.clone(), test_visitor).unwrap();
run!(args, test_visitor).unwrap();
run!(args, test_mut_visitor).unwrap();
}
+11 -1
View File
@@ -3,7 +3,7 @@
//@ add-core-stubs
//@ build-fail
#![feature(no_core)]
#![feature(no_core, repr_simd)]
#![no_core]
#![crate_type = "lib"]
#![deny(wasm_c_abi)]
@@ -45,3 +45,13 @@ pub fn call_other_fun(x: MyType) {
pub struct MyZstType;
#[allow(improper_ctypes_definitions)]
pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {}
// The old and new wasm ABI treats simd types like `v128` the same way, so no
// wasm_c_abi warning should be emitted.
#[repr(simd)]
#[allow(non_camel_case_types)]
pub struct v128([i32; 4]);
#[target_feature(enable = "simd128")]
pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
//~^ WARN `extern` fn uses type `v128`, which is not FFI-safe
//~| WARN `extern` fn uses type `v128`, which is not FFI-safe
+30 -1
View File
@@ -1,3 +1,32 @@
warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:35
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^
= note: `#[warn(improper_ctypes_definitions)]` on by default
warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:44
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:18:1
|
@@ -33,7 +62,7 @@ LL | unsafe { other_fun(x) }
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
error: aborting due to 3 previous errors
error: aborting due to 3 previous errors; 2 warnings emitted
Future incompatibility report: Future breakage diagnostic:
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
@@ -0,0 +1,19 @@
//! Byte string literal patterns use the mutability of the literal, rather than the mutability of
//! the pattern's scrutinee. Since byte string literals are always shared references, it's a
//! mismatch to use a byte string literal pattern to match on a mutable array or slice reference.
fn main() {
let mut val = [97u8, 10u8];
match &mut val {
b"a\n" => {},
//~^ ERROR mismatched types
//~| types differ in mutability
_ => {},
}
match &mut val[..] {
b"a\n" => {},
//~^ ERROR mismatched types
//~| types differ in mutability
_ => {},
}
}
@@ -0,0 +1,25 @@
error[E0308]: mismatched types
--> $DIR/byte-string-mutability-mismatch.rs:8:9
|
LL | match &mut val {
| -------- this expression has type `&mut [u8; 2]`
LL | b"a\n" => {},
| ^^^^^^ types differ in mutability
|
= note: expected mutable reference `&mut _`
found reference `&'static _`
error[E0308]: mismatched types
--> $DIR/byte-string-mutability-mismatch.rs:14:10
|
LL | match &mut val[..] {
| ------------ this expression has type `&mut [u8]`
LL | b"a\n" => {},
| ^^^^^^ types differ in mutability
|
= note: expected mutable reference `&mut _`
found reference `&'static _`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
@@ -0,0 +1,34 @@
//! Test type errors for byte string literal patterns. `deref_patterns` allows byte string literal
//! patterns to have type `[u8]` or `[u8; N]` when matching on a slice or array; this can affect the
//! "found" type reported in error messages when matching on a slice or array of the wrong type.
#![feature(deref_patterns)]
#![expect(incomplete_features)]
fn main() {
// Baseline 1: under normal circumstances, byte string literal patterns have type `&[u8; N]`,
// the same as byte string literals.
if let b"test" = () {}
//~^ ERROR mismatched types
//~| expected `()`, found `&[u8; 4]`
// Baseline 2: there's a special case for byte string patterns in stable rust, allowing them to
// match on slice references. This affects the error when matching on a non-`&[u8]` slice ref,
// reporting the "found" type as `&[u8]`.
if let b"test" = &[] as &[i8] {}
//~^ ERROR mismatched types
//~| expected `&[i8]`, found `&[u8]`
// Test matching on a non-`[u8]` slice: the pattern has type `[u8]` if a slice is expected.
if let b"test" = *(&[] as &[i8]) {}
//~^ ERROR mismatched types
//~| expected `[i8]`, found `[u8]`
// Test matching on a non-`[u8;4]` array: the pattern has type `[u8;4]` if an array is expected.
if let b"test" = [()] {}
//~^ ERROR mismatched types
//~| expected `[(); 1]`, found `[u8; 4]`
if let b"test" = *b"this array is too long" {}
//~^ ERROR mismatched types
//~| expected an array with a size of 22, found one with a size of 4
}
@@ -0,0 +1,52 @@
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:11:12
|
LL | if let b"test" = () {}
| ^^^^^^^ -- this expression has type `()`
| |
| expected `()`, found `&[u8; 4]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:18:12
|
LL | if let b"test" = &[] as &[i8] {}
| ^^^^^^^ ------------ this expression has type `&[i8]`
| |
| expected `&[i8]`, found `&[u8]`
|
= note: expected reference `&[i8]`
found reference `&'static [u8]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:23:12
|
LL | if let b"test" = *(&[] as &[i8]) {}
| ^^^^^^^ --------------- this expression has type `[i8]`
| |
| expected `[i8]`, found `[u8]`
|
= note: expected slice `[i8]`
found slice `[u8]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:28:12
|
LL | if let b"test" = [()] {}
| ^^^^^^^ ---- this expression has type `[(); 1]`
| |
| expected `[(); 1]`, found `[u8; 4]`
|
= note: expected array `[(); 1]`
found array `[u8; 4]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:31:12
|
LL | if let b"test" = *b"this array is too long" {}
| ^^^^^^^ -------------------------- this expression has type `[u8; 22]`
| |
| expected an array with a size of 22, found one with a size of 4
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.
@@ -12,4 +12,21 @@ fn main() {
//~^ ERROR: mismatched types
_ => {}
}
// `deref_patterns` allows string and byte string literals to have non-ref types.
match *"test" {
"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
match *b"test" {
b"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
match *(b"test" as &[u8]) {
b"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
}
@@ -23,7 +23,31 @@ help: consider dereferencing to access the inner value using the Deref trait
LL | match *Box::new(0) {
| +
error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:18:9
|
LL | match *"test" {
| ------- this expression has type `str`
LL | "test" => {}
| ^^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:23:9
|
LL | match *b"test" {
| -------- this expression has type `[u8; 4]`
LL | b"test" => {}
| ^^^^^^^ expected `[u8; 4]`, found `&[u8; 4]`
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:28:9
|
LL | match *(b"test" as &[u8]) {
| ------------------- this expression has type `[u8]`
LL | b"test" => {}
| ^^^^^^^ expected `[u8]`, found `&[u8; 4]`
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0658.
For more information about an error, try `rustc --explain E0308`.
@@ -0,0 +1,66 @@
//@ run-pass
//! Test deref patterns using string and bytestring literals.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
fn main() {
for (test_in, test_expect) in [("zero", 0), ("one", 1), ("two", 2)] {
// Test string literal patterns having type `str`.
let test_actual = match *test_in {
"zero" => 0,
"one" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test string literals in explicit `deref!(_)` patterns.
let test_actual = match test_in.to_string() {
deref!("zero") => 0,
deref!("one") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
}
// Test that we can still mutate in the match arm after using a literal to test equality:
let mut test = "test".to_string();
if let deref!(s @ "test") = &mut test {
s.make_ascii_uppercase();
}
assert_eq!(test, "TEST");
for (test_in, test_expect) in [(b"0", 0), (b"1", 1), (b"2", 2)] {
// Test byte string literal patterns having type `[u8; N]`
let test_actual = match *test_in {
b"0" => 0,
b"1" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literal patterns having type `[u8]`
let test_actual = match *(test_in as &[u8]) {
b"0" => 0,
b"1" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literals used as arrays in explicit `deref!(_)` patterns.
let test_actual = match Box::new(*test_in) {
deref!(b"0") => 0,
deref!(b"1") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literals used as slices in explicit `deref!(_)` patterns.
let test_actual = match test_in.to_vec() {
deref!(b"0") => 0,
deref!(b"1") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
}
}
@@ -2,18 +2,14 @@
#![allow(incomplete_features)]
fn main() {
// FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
// place of type `str`.
// FIXME(deref_patterns): fails to typecheck because string literal patterns don't peel
// references from the scrutinee.
match "foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}
}
match &"foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}
@@ -1,34 +1,16 @@
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:8:16
--> $DIR/typeck_fail.rs:8:9
|
LL | match "foo".to_string() {
| ----------------- this expression has type `String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:10:9
|
LL | match "foo".to_string() {
| ----------------- this expression has type `String`
...
LL | "foo" => {}
| ^^^^^ expected `String`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:15:16
--> $DIR/typeck_fail.rs:13:9
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:17:9
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
...
LL | "foo" => {}
| ^^^^^ expected `&String`, found `&str`
|
@@ -36,7 +18,7 @@ LL | "foo" => {}
found reference `&'static str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:24:9
--> $DIR/typeck_fail.rs:20:9
|
LL | match Some(0) {
| ------- this expression has type `Option<{integer}>`
@@ -46,6 +28,6 @@ LL | Ok(0) => {}
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
error: aborting due to 5 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.