Auto merge of #72036 - Dylan-DPC:rollup-ca8b0ql, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #70834 (Add core::future::{pending,ready}) - #71839 (Make BTreeMap::new and BTreeSet::new const) - #71890 (Simplify the error Registry methods a little) - #71942 (Shrink `LocalDecl`) - #71947 (Dead-code pass highlights too much of impl functions) - #71981 (Fix `strip-priv-imports` pass name in the rustdoc documentation) - #72018 (Fix canonicalization links) - #72031 (Better documentation for io::Read::read() return value) Failed merges: r? @ghost
This commit is contained in:
commit
945d110e05
@ -17,7 +17,7 @@ By default, rustdoc will run some passes, namely:
|
||||
* `collapse-docs`
|
||||
* `unindent-comments`
|
||||
|
||||
However, `strip-private` implies `strip-private-imports`, and so effectively,
|
||||
However, `strip-private` implies `strip-priv-imports`, and so effectively,
|
||||
all passes are run by default.
|
||||
|
||||
## `strip-hidden`
|
||||
|
@ -556,7 +556,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||
/// map.insert(1, "a");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> BTreeMap<K, V> {
|
||||
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
|
||||
pub const fn new() -> BTreeMap<K, V> {
|
||||
BTreeMap { root: None, length: 0 }
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,8 @@ impl<T: Ord> BTreeSet<T> {
|
||||
/// let mut set: BTreeSet<i32> = BTreeSet::new();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> BTreeSet<T> {
|
||||
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
|
||||
pub const fn new() -> BTreeSet<T> {
|
||||
BTreeSet { map: BTreeMap::new() }
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@
|
||||
#![feature(cfg_sanitize)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(coerce_unsized)]
|
||||
#![feature(const_btree_new)]
|
||||
#![feature(const_generic_impls_guard)]
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
|
@ -10,9 +10,17 @@ use crate::{
|
||||
};
|
||||
|
||||
mod future;
|
||||
mod pending;
|
||||
mod ready;
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::future::Future;
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub use pending::{pending, Pending};
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub use ready::{ready, Ready};
|
||||
|
||||
/// This type is needed because:
|
||||
///
|
||||
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
|
||||
|
57
src/libcore/future/pending.rs
Normal file
57
src/libcore/future/pending.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use crate::future::Future;
|
||||
use crate::marker;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future which never resolves, representing a computation that never
|
||||
/// finishes.
|
||||
///
|
||||
/// This `struct` is created by the [`pending`] function. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`pending`]: fn.pending.html
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Pending<T> {
|
||||
_data: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Creates a future which never resolves, representing a computation that never
|
||||
/// finishes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(future_readiness_fns)]
|
||||
/// use core::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let future = future::pending();
|
||||
/// let () = future.await;
|
||||
/// unreachable!();
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub fn pending<T>() -> Pending<T> {
|
||||
Pending { _data: marker::PhantomData }
|
||||
}
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
impl<T> Future for Pending<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
impl<T> Unpin for Pending<T> {}
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
impl<T> Clone for Pending<T> {
|
||||
fn clone(&self) -> Self {
|
||||
pending()
|
||||
}
|
||||
}
|
45
src/libcore/future/ready.rs
Normal file
45
src/libcore/future/ready.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::future::Future;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future that is immediately ready with a value.
|
||||
///
|
||||
/// This `struct` is created by the [`ready`] function. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`ready`]: fn.ready.html
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
#[derive(Debug, Clone)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Ready<T>(Option<T>);
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
impl<T> Unpin for Ready<T> {}
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
impl<T> Future for Ready<T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
|
||||
Poll::Ready(self.0.take().expect("Ready polled after completion"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a future that is immediately ready with a value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(future_readiness_fns)]
|
||||
/// use core::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let a = future::ready(1);
|
||||
/// assert_eq!(a.await, 1);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub fn ready<T>(t: T) -> Ready<T> {
|
||||
Ready(Some(t))
|
||||
}
|
@ -10,12 +10,12 @@ pub struct Registry {
|
||||
|
||||
impl Registry {
|
||||
pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
|
||||
Registry { long_descriptions: long_descriptions.iter().cloned().collect() }
|
||||
Registry { long_descriptions: long_descriptions.iter().copied().collect() }
|
||||
}
|
||||
|
||||
/// This will panic if an invalid error code is passed in
|
||||
pub fn find_description(&self, code: &str) -> Option<&'static str> {
|
||||
self.try_find_description(code).unwrap()
|
||||
self.long_descriptions[code]
|
||||
}
|
||||
/// Returns `InvalidErrorCode` if the code requested does not exist in the
|
||||
/// registry. Otherwise, returns an `Option` where `None` means the error
|
||||
@ -24,9 +24,6 @@ impl Registry {
|
||||
&self,
|
||||
code: &str,
|
||||
) -> Result<Option<&'static str>, InvalidErrorCode> {
|
||||
if !self.long_descriptions.contains_key(code) {
|
||||
return Err(InvalidErrorCode);
|
||||
}
|
||||
Ok(*self.long_descriptions.get(code).unwrap())
|
||||
self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! For an overview of what canonicalization is and how it fits into
|
||||
//! rustc, check out the [chapter in the rustc dev guide][c].
|
||||
//!
|
||||
//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::canonical::{
|
||||
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
|
||||
@ -35,7 +35,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||
/// To get a good understanding of what is happening here, check
|
||||
/// out the [chapter in the rustc dev guide][c].
|
||||
///
|
||||
/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query
|
||||
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query
|
||||
pub fn canonicalize_query<V>(
|
||||
&self,
|
||||
value: &V,
|
||||
@ -79,7 +79,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||
/// To get a good understanding of what is happening here, check
|
||||
/// out the [chapter in the rustc dev guide][c].
|
||||
///
|
||||
/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query-result
|
||||
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query-result
|
||||
pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx>,
|
||||
|
@ -19,7 +19,7 @@
|
||||
//! For a more detailed look at what is happening here, check
|
||||
//! out the [chapter in the rustc dev guide][c].
|
||||
//!
|
||||
//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
|
||||
|
@ -5,7 +5,7 @@
|
||||
//! For an overview of what canonicaliation is and how it fits into
|
||||
//! rustc, check out the [chapter in the rustc dev guide][c].
|
||||
//!
|
||||
//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::canonical::substitute::{substitute_value, CanonicalExt};
|
||||
use crate::infer::canonical::{
|
||||
@ -154,7 +154,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||
/// To get a good understanding of what is happening here, check
|
||||
/// out the [chapter in the rustc dev guide][c].
|
||||
///
|
||||
/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#processing-the-canonicalized-query-result
|
||||
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#processing-the-canonicalized-query-result
|
||||
pub fn instantiate_query_response_and_region_obligations<R>(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
|
@ -4,7 +4,7 @@
|
||||
//! For an overview of what canonicalization is and how it fits into
|
||||
//! rustc, check out the [chapter in the rustc dev guide][c].
|
||||
//!
|
||||
//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::canonical::{Canonical, CanonicalVarValues};
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
|
@ -19,7 +19,7 @@
|
||||
//! For a more detailed look at what is happening here, check
|
||||
//! out the [chapter in the rustc dev guide][c].
|
||||
//!
|
||||
//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use crate::infer::MemberConstraint;
|
||||
use crate::ty::subst::GenericArg;
|
||||
|
@ -474,6 +474,13 @@ pub struct SourceInfo {
|
||||
pub scope: SourceScope,
|
||||
}
|
||||
|
||||
impl SourceInfo {
|
||||
#[inline]
|
||||
pub fn outermost(span: Span) -> Self {
|
||||
SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Borrow kinds
|
||||
|
||||
@ -689,7 +696,7 @@ pub struct LocalDecl<'tcx> {
|
||||
pub mutability: Mutability,
|
||||
|
||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
||||
pub local_info: LocalInfo<'tcx>,
|
||||
pub local_info: Option<Box<LocalInfo<'tcx>>>,
|
||||
|
||||
/// `true` if this is an internal local.
|
||||
///
|
||||
@ -725,7 +732,7 @@ pub struct LocalDecl<'tcx> {
|
||||
/// borrow checker needs this information since it can affect
|
||||
/// region inference.
|
||||
// FIXME(matthewjasper) Don't store in this in `Body`
|
||||
pub user_ty: UserTypeProjections,
|
||||
pub user_ty: Option<Box<UserTypeProjections>>,
|
||||
|
||||
/// The *syntactic* (i.e., not visibility) source scope the local is defined
|
||||
/// in. If the local was defined in a let-statement, this
|
||||
@ -809,7 +816,13 @@ pub struct LocalDecl<'tcx> {
|
||||
pub source_info: SourceInfo,
|
||||
}
|
||||
|
||||
/// Extra information about a local that's used for diagnostics.
|
||||
// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(LocalDecl<'_>, 56);
|
||||
|
||||
/// Extra information about a some locals that's used for diagnostics. (Not
|
||||
/// used for non-StaticRef temporaries, the return place, or anonymous function
|
||||
/// parameters.)
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
|
||||
pub enum LocalInfo<'tcx> {
|
||||
/// A user-defined local variable or function parameter
|
||||
@ -820,8 +833,6 @@ pub enum LocalInfo<'tcx> {
|
||||
User(ClearCrossCrate<BindingForm<'tcx>>),
|
||||
/// A temporary created that references the static with the given `DefId`.
|
||||
StaticRef { def_id: DefId, is_thread_local: bool },
|
||||
/// Any other temporary, the return place, or an anonymous function parameter.
|
||||
Other,
|
||||
}
|
||||
|
||||
impl<'tcx> LocalDecl<'tcx> {
|
||||
@ -833,16 +844,16 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// - or `match ... { C(x) => ... }`
|
||||
pub fn can_be_made_mutable(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
}))) => true,
|
||||
})))) => true,
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
ImplicitSelfKind::Imm,
|
||||
))) => true,
|
||||
)))) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
@ -853,14 +864,14 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// mutable bindings, but the inverse does not necessarily hold).
|
||||
pub fn is_nonref_binding(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
}))) => true,
|
||||
})))) => true,
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
@ -871,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
#[inline]
|
||||
pub fn is_user_variable(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::User(_) => true,
|
||||
Some(box LocalInfo::User(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -881,7 +892,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// match arm.
|
||||
pub fn is_ref_for_guard(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -890,7 +901,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// access that static
|
||||
pub fn is_ref_to_static(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::StaticRef { .. } => true,
|
||||
Some(box LocalInfo::StaticRef { .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -899,7 +910,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// access that static
|
||||
pub fn is_ref_to_thread_local(&self) -> bool {
|
||||
match self.local_info {
|
||||
LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local,
|
||||
Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -911,10 +922,31 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
self.source_info.span.desugaring_kind().is_some()
|
||||
}
|
||||
|
||||
/// Creates a new `LocalDecl` for a temporary.
|
||||
/// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
|
||||
#[inline]
|
||||
pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
|
||||
Self::new_local(ty, Mutability::Mut, false, span)
|
||||
pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
|
||||
Self::with_source_info(ty, SourceInfo::outermost(span))
|
||||
}
|
||||
|
||||
/// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
|
||||
#[inline]
|
||||
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
|
||||
LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
local_info: None,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
ty,
|
||||
user_ty: None,
|
||||
source_info,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `self` into same `LocalDecl` except tagged as internal.
|
||||
#[inline]
|
||||
pub fn internal(mut self) -> Self {
|
||||
self.internal = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts `self` into same `LocalDecl` except tagged as immutable.
|
||||
@ -931,41 +963,6 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
self.is_block_tail = Some(info);
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates a new `LocalDecl` for a internal temporary.
|
||||
#[inline]
|
||||
pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
|
||||
Self::new_local(ty, Mutability::Mut, true, span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self {
|
||||
LocalDecl {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
internal,
|
||||
local_info: LocalInfo::Other,
|
||||
is_block_tail: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `LocalDecl` for the return place.
|
||||
///
|
||||
/// This must be inserted into the `local_decls` list as the first local.
|
||||
#[inline]
|
||||
pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
|
||||
LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: return_ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Debug information pertaining to a user variable.
|
||||
@ -1406,10 +1403,7 @@ impl<'tcx> BasicBlockData<'tcx> {
|
||||
let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
|
||||
self.statements.resize(
|
||||
gap.end,
|
||||
Statement {
|
||||
source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
kind: StatementKind::Nop,
|
||||
},
|
||||
Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
|
||||
);
|
||||
for (splice_start, new_stmts) in splices.into_iter().rev() {
|
||||
let splice_end = splice_start + new_stmts.size_hint().0;
|
||||
@ -2457,7 +2451,7 @@ impl Constant<'tcx> {
|
||||
/// &'static str`.
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
|
||||
pub struct UserTypeProjections {
|
||||
pub(crate) contents: Vec<(UserTypeProjection, Span)>,
|
||||
pub contents: Vec<(UserTypeProjection, Span)>,
|
||||
}
|
||||
|
||||
impl<'tcx> UserTypeProjections {
|
||||
@ -2465,6 +2459,10 @@ impl<'tcx> UserTypeProjections {
|
||||
UserTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.contents.is_empty()
|
||||
}
|
||||
|
||||
pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
|
||||
UserTypeProjections { contents: projs.collect() }
|
||||
}
|
||||
|
@ -242,10 +242,10 @@ macro_rules! make_mir_visitor {
|
||||
) {
|
||||
let span = body.span;
|
||||
if let Some(yield_ty) = &$($mutability)? body.yield_ty {
|
||||
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
|
||||
span,
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
}));
|
||||
self.visit_ty(
|
||||
yield_ty,
|
||||
TyContext::YieldTy(SourceInfo::outermost(span))
|
||||
);
|
||||
}
|
||||
|
||||
// for best performance, we want to use an iterator rather
|
||||
@ -263,10 +263,10 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_source_scope_data(scope);
|
||||
}
|
||||
|
||||
self.visit_ty(&$($mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo {
|
||||
span: body.span,
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
}));
|
||||
self.visit_ty(
|
||||
&$($mutability)? body.return_ty(),
|
||||
TyContext::ReturnTy(SourceInfo::outermost(body.span))
|
||||
);
|
||||
|
||||
for local in body.local_decls.indices() {
|
||||
self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
|
||||
@ -715,8 +715,10 @@ macro_rules! make_mir_visitor {
|
||||
local,
|
||||
source_info: *source_info,
|
||||
});
|
||||
for (user_ty, _) in & $($mutability)? user_ty.contents {
|
||||
self.visit_user_type_projection(user_ty);
|
||||
if let Some(user_ty) = user_ty {
|
||||
for (user_ty, _) in & $($mutability)? user_ty.contents {
|
||||
self.visit_user_type_projection(user_ty);
|
||||
}
|
||||
}
|
||||
self.visit_source_info(source_info);
|
||||
}
|
||||
|
@ -1447,15 +1447,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let (place_description, assigned_span) = match local_decl {
|
||||
Some(LocalDecl {
|
||||
local_info:
|
||||
LocalInfo::User(
|
||||
Some(box LocalInfo::User(
|
||||
ClearCrossCrate::Clear
|
||||
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: None,
|
||||
..
|
||||
})),
|
||||
)
|
||||
| LocalInfo::StaticRef { .. }
|
||||
| LocalInfo::Other,
|
||||
))
|
||||
| Some(box LocalInfo::StaticRef { .. })
|
||||
| None,
|
||||
..
|
||||
})
|
||||
| None => (self.describe_any_place(place.as_ref()), assigned_span),
|
||||
|
@ -202,7 +202,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if self.body.local_decls[local].is_ref_to_static() =>
|
||||
{
|
||||
let local_info = &self.body.local_decls[local].local_info;
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
|
||||
buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
|
||||
} else {
|
||||
unreachable!();
|
||||
|
@ -103,14 +103,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
//
|
||||
// opt_match_place is None for let [mut] x = ... statements,
|
||||
// whether or not the right-hand side is a place expression
|
||||
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
},
|
||||
))) = local_decl.local_info
|
||||
)))) = local_decl.local_info
|
||||
{
|
||||
let stmt_source_info = self.body.source_info(location);
|
||||
self.append_binding_error(
|
||||
@ -482,10 +482,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
|
||||
for local in binds_to {
|
||||
let bind_to = &self.body.local_decls[*local];
|
||||
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
pat_span,
|
||||
..
|
||||
}))) = bind_to.local_info
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm { pat_span, .. },
|
||||
)))) = bind_to.local_info
|
||||
{
|
||||
if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
let local_info = &self.body.local_decls[local].local_info;
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
|
||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||
reason = format!(", as `{}` is an immutable static item", static_name);
|
||||
} else {
|
||||
@ -216,9 +216,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
.local_decls
|
||||
.get(local)
|
||||
.map(|local_decl| {
|
||||
if let LocalInfo::User(ClearCrossCrate::Set(
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::ImplicitSelf(kind),
|
||||
)) = local_decl.local_info
|
||||
))) = local_decl.local_info
|
||||
{
|
||||
// Check if the user variable is a `&mut self` and we can therefore
|
||||
// suggest removing the `&mut`.
|
||||
@ -340,8 +340,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
|
||||
match self.local_names[local] {
|
||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||
let label = match local_decl.local_info {
|
||||
LocalInfo::User(ClearCrossCrate::Set(
|
||||
let label = match local_decl.local_info.as_ref().unwrap() {
|
||||
box LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::ImplicitSelf(_),
|
||||
)) => {
|
||||
let (span, suggestion) =
|
||||
@ -349,7 +349,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
Some((true, span, suggestion))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
@ -381,14 +381,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
self.infcx.tcx,
|
||||
local_decl,
|
||||
opt_assignment_rhs_span,
|
||||
opt_ty_info,
|
||||
*opt_ty_info,
|
||||
);
|
||||
Some((true, span, suggestion))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
@ -399,7 +399,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
.map(|replacement| (true, pattern_span, replacement))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Clear) => {
|
||||
box LocalInfo::User(ClearCrossCrate::Clear) => {
|
||||
bug!("saw cleared local state")
|
||||
}
|
||||
|
||||
|
@ -405,35 +405,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
self.super_local_decl(local, local_decl);
|
||||
self.sanitize_type(local_decl, local_decl.ty);
|
||||
|
||||
for (user_ty, span) in local_decl.user_ty.projections_and_spans() {
|
||||
let ty = if !local_decl.is_nonref_binding() {
|
||||
// If we have a binding of the form `let ref x: T = ..` then remove the outermost
|
||||
// reference so we can check the type annotation for the remaining type.
|
||||
if let ty::Ref(_, rty, _) = local_decl.ty.kind {
|
||||
rty
|
||||
if let Some(user_ty) = &local_decl.user_ty {
|
||||
for (user_ty, span) in user_ty.projections_and_spans() {
|
||||
let ty = if !local_decl.is_nonref_binding() {
|
||||
// If we have a binding of the form `let ref x: T = ..`
|
||||
// then remove the outermost reference so we can check the
|
||||
// type annotation for the remaining type.
|
||||
if let ty::Ref(_, rty, _) = local_decl.ty.kind {
|
||||
rty
|
||||
} else {
|
||||
bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
|
||||
}
|
||||
} else {
|
||||
bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
|
||||
}
|
||||
} else {
|
||||
local_decl.ty
|
||||
};
|
||||
local_decl.ty
|
||||
};
|
||||
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
ty,
|
||||
ty::Variance::Invariant,
|
||||
user_ty,
|
||||
Locations::All(*span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
local,
|
||||
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
|
||||
local,
|
||||
local_decl.ty,
|
||||
local_decl.user_ty,
|
||||
terr,
|
||||
);
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
ty,
|
||||
ty::Variance::Invariant,
|
||||
user_ty,
|
||||
Locations::All(*span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
local,
|
||||
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
|
||||
local,
|
||||
local_decl.ty,
|
||||
local_decl.user_ty,
|
||||
terr,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use crate::dataflow::BottomValue;
|
||||
/// This is the `Body` that will be used by the `MockAnalysis` below. The shape of its CFG is not
|
||||
/// important.
|
||||
fn mock_body() -> mir::Body<'static> {
|
||||
let source_info = mir::SourceInfo { scope: mir::OUTERMOST_SOURCE_SCOPE, span: DUMMY_SP };
|
||||
let source_info = mir::SourceInfo::outermost(DUMMY_SP);
|
||||
|
||||
let mut blocks = IndexVec::new();
|
||||
let mut block = |n, kind| {
|
||||
|
@ -145,25 +145,12 @@ enum CallKind {
|
||||
Direct(DefId),
|
||||
}
|
||||
|
||||
fn temp_decl(mutability: Mutability, ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
|
||||
let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span };
|
||||
LocalDecl {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
internal: false,
|
||||
local_info: LocalInfo::Other,
|
||||
is_block_tail: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn local_decls_for_sig<'tcx>(
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
span: Span,
|
||||
) -> IndexVec<Local, LocalDecl<'tcx>> {
|
||||
iter::once(temp_decl(Mutability::Mut, sig.output(), span))
|
||||
.chain(sig.inputs().iter().map(|ity| temp_decl(Mutability::Not, ity, span)))
|
||||
iter::once(LocalDecl::new(sig.output(), span))
|
||||
.chain(sig.inputs().iter().map(|ity| LocalDecl::new(ity, span).immutable()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -185,7 +172,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||
let sig = tcx.erase_late_bound_regions(&sig);
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||
let source_info = SourceInfo::outermost(span);
|
||||
|
||||
let return_block = BasicBlock::new(1);
|
||||
let mut blocks = IndexVec::with_capacity(2);
|
||||
@ -374,7 +361,7 @@ impl CloneShimBuilder<'tcx> {
|
||||
}
|
||||
|
||||
fn source_info(&self) -> SourceInfo {
|
||||
SourceInfo { span: self.span, scope: OUTERMOST_SOURCE_SCOPE }
|
||||
SourceInfo::outermost(self.span)
|
||||
}
|
||||
|
||||
fn block(
|
||||
@ -414,7 +401,11 @@ impl CloneShimBuilder<'tcx> {
|
||||
|
||||
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
|
||||
let span = self.span;
|
||||
Place::from(self.local_decls.push(temp_decl(mutability, ty, span)))
|
||||
let mut local = LocalDecl::new(ty, span);
|
||||
if mutability == Mutability::Not {
|
||||
local = local.immutable();
|
||||
}
|
||||
Place::from(self.local_decls.push(local))
|
||||
}
|
||||
|
||||
fn make_clone_call(
|
||||
@ -498,7 +489,7 @@ impl CloneShimBuilder<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let span = self.span;
|
||||
|
||||
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
|
||||
let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
|
||||
let end = self.make_place(Mutability::Not, tcx.types.usize);
|
||||
|
||||
// BB #0
|
||||
@ -553,7 +544,7 @@ impl CloneShimBuilder<'tcx> {
|
||||
// `let mut beg = 0;`
|
||||
// goto #6;
|
||||
let end = beg;
|
||||
let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
|
||||
let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
|
||||
let init = self.make_statement(StatementKind::Assign(box (
|
||||
Place::from(beg),
|
||||
Rvalue::Use(Operand::Constant(self.make_usize(0))),
|
||||
@ -687,7 +678,7 @@ fn build_call_shim<'tcx>(
|
||||
debug!("build_call_shim: sig={:?}", sig);
|
||||
|
||||
let mut local_decls = local_decls_for_sig(&sig, span);
|
||||
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||
let source_info = SourceInfo::outermost(span);
|
||||
|
||||
let rcvr_place = || {
|
||||
assert!(rcvr_adjustment.is_some());
|
||||
@ -701,14 +692,16 @@ fn build_call_shim<'tcx>(
|
||||
Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())),
|
||||
Adjustment::RefMut => {
|
||||
// let rcvr = &mut rcvr;
|
||||
let ref_rcvr = local_decls.push(temp_decl(
|
||||
Mutability::Not,
|
||||
tcx.mk_ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::Mut },
|
||||
),
|
||||
span,
|
||||
));
|
||||
let ref_rcvr = local_decls.push(
|
||||
LocalDecl::new(
|
||||
tcx.mk_ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::Mut },
|
||||
),
|
||||
span,
|
||||
)
|
||||
.immutable(),
|
||||
);
|
||||
let borrow_kind = BorrowKind::Mut { allow_two_phase_borrow: false };
|
||||
statements.push(Statement {
|
||||
source_info,
|
||||
@ -849,7 +842,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
|
||||
|
||||
let local_decls = local_decls_for_sig(&sig, span);
|
||||
|
||||
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||
let source_info = SourceInfo::outermost(span);
|
||||
|
||||
let variant_index = if adt_def.is_enum() {
|
||||
adt_def.variant_index_with_ctor_id(ctor_id)
|
||||
|
@ -77,11 +77,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
||||
// PART 1
|
||||
// Retag arguments at the beginning of the start block.
|
||||
{
|
||||
let source_info = SourceInfo {
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
span, // FIXME: Consider using just the span covering the function
|
||||
// argument declaration.
|
||||
};
|
||||
// FIXME: Consider using just the span covering the function
|
||||
// argument declaration.
|
||||
let source_info = SourceInfo::outermost(span);
|
||||
// Gather all arguments, skip return value.
|
||||
let places = local_decls
|
||||
.iter_enumerated()
|
||||
|
@ -455,7 +455,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||
if proj_base.is_empty() {
|
||||
if let (local, []) = (place_local, proj_base) {
|
||||
let decl = &self.body.local_decls[local];
|
||||
if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
|
||||
let span = decl.source_info.span;
|
||||
self.check_static(def_id, span);
|
||||
return;
|
||||
|
@ -50,7 +50,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
|
||||
const_context,
|
||||
min_const_fn,
|
||||
violations: vec![],
|
||||
source_info: SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
source_info: SourceInfo::outermost(body.span),
|
||||
tcx,
|
||||
param_env,
|
||||
used_unsafe: Default::default(),
|
||||
@ -218,7 +218,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||
if let [] = proj_base {
|
||||
let decl = &self.body.local_decls[place.local];
|
||||
if decl.internal {
|
||||
if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
|
||||
if self.tcx.is_mutable_static(def_id) {
|
||||
self.require_unsafe(
|
||||
"use of mutable static",
|
||||
|
@ -255,13 +255,13 @@ impl TransformVisitor<'tcx> {
|
||||
|
||||
// Create a statement which reads the discriminant into a temporary
|
||||
fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
|
||||
let temp_decl = LocalDecl::new_internal(self.tcx.types.isize, body.span);
|
||||
let temp_decl = LocalDecl::new(self.tcx.types.isize, body.span).internal();
|
||||
let local_decls_len = body.local_decls.push(temp_decl);
|
||||
let temp = Place::from(local_decls_len);
|
||||
|
||||
let self_place = Place::from(SELF_ARG);
|
||||
let assign = Statement {
|
||||
source_info: source_info(body),
|
||||
source_info: SourceInfo::outermost(body.span),
|
||||
kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))),
|
||||
};
|
||||
(assign, temp)
|
||||
@ -395,16 +395,7 @@ fn replace_local<'tcx>(
|
||||
body: &mut Body<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Local {
|
||||
let source_info = source_info(body);
|
||||
let new_decl = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::Other,
|
||||
};
|
||||
let new_decl = LocalDecl::new(ty, body.span);
|
||||
let new_local = body.local_decls.push(new_decl);
|
||||
body.local_decls.swap(local, new_local);
|
||||
|
||||
@ -784,7 +775,7 @@ fn insert_switch<'tcx>(
|
||||
targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(),
|
||||
};
|
||||
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
body.basic_blocks_mut().raw.insert(
|
||||
0,
|
||||
BasicBlockData {
|
||||
@ -858,7 +849,7 @@ fn create_generator_drop_shim<'tcx>(
|
||||
let mut body = body.clone();
|
||||
body.arg_count = 1; // make sure the resume argument is not included here
|
||||
|
||||
let source_info = source_info(&body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
|
||||
let mut cases = create_cases(&mut body, transform, Operation::Drop);
|
||||
|
||||
@ -877,28 +868,15 @@ fn create_generator_drop_shim<'tcx>(
|
||||
}
|
||||
|
||||
// Replace the return variable
|
||||
body.local_decls[RETURN_PLACE] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_unit(),
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::Other,
|
||||
};
|
||||
body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(tcx.mk_unit(), source_info);
|
||||
|
||||
make_generator_state_argument_indirect(tcx, &mut body);
|
||||
|
||||
// Change the generator argument from &mut to *mut
|
||||
body.local_decls[SELF_ARG] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
|
||||
user_ty: UserTypeProjections::none(),
|
||||
body.local_decls[SELF_ARG] = LocalDecl::with_source_info(
|
||||
tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
|
||||
source_info,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::Other,
|
||||
};
|
||||
);
|
||||
if tcx.sess.opts.debugging_opts.mir_emit_retag {
|
||||
// Alias tracking must know we changed the type
|
||||
body.basic_blocks_mut()[START_BLOCK].statements.insert(
|
||||
@ -922,7 +900,7 @@ fn create_generator_drop_shim<'tcx>(
|
||||
}
|
||||
|
||||
fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
terminator: Some(Terminator { source_info, kind }),
|
||||
@ -948,7 +926,7 @@ fn insert_panic_block<'tcx>(
|
||||
cleanup: None,
|
||||
};
|
||||
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: Vec::new(),
|
||||
terminator: Some(Terminator { source_info, kind: term }),
|
||||
@ -1025,7 +1003,7 @@ fn create_generator_resume_function<'tcx>(
|
||||
|
||||
// Poison the generator when it unwinds
|
||||
if can_unwind {
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
let poison_block = body.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
|
||||
terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
|
||||
@ -1092,10 +1070,6 @@ fn create_generator_resume_function<'tcx>(
|
||||
dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()));
|
||||
}
|
||||
|
||||
fn source_info(body: &Body<'_>) -> SourceInfo {
|
||||
SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE }
|
||||
}
|
||||
|
||||
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
||||
let return_block = insert_term_block(body, TerminatorKind::Return);
|
||||
|
||||
@ -1104,7 +1078,7 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
||||
target: return_block,
|
||||
unwind: None,
|
||||
};
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
|
||||
// Create a block to destroy an unresumed generators. This can only destroy upvars.
|
||||
body.basic_blocks_mut().push(BasicBlockData {
|
||||
@ -1135,7 +1109,7 @@ fn create_cases<'tcx>(
|
||||
transform: &TransformVisitor<'tcx>,
|
||||
operation: Operation,
|
||||
) -> Vec<(usize, BasicBlock)> {
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
|
||||
transform
|
||||
.suspension_points
|
||||
@ -1241,7 +1215,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||
replace_local(resume_local, body.local_decls[resume_local].ty, body, tcx);
|
||||
|
||||
// When first entering the generator, move the resume argument into its new local.
|
||||
let source_info = source_info(body);
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
let stmts = &mut body.basic_blocks_mut()[BasicBlock::new(0)].statements;
|
||||
stmts.insert(
|
||||
0,
|
||||
|
@ -480,7 +480,7 @@ impl Inliner<'tcx> {
|
||||
|
||||
let ty = dest.ty(caller_body, self.tcx);
|
||||
|
||||
let temp = LocalDecl::new_temp(ty, callsite.location.span);
|
||||
let temp = LocalDecl::new(ty, callsite.location.span);
|
||||
|
||||
let tmp = caller_body.local_decls.push(temp);
|
||||
let tmp = Place::from(tmp);
|
||||
@ -631,7 +631,7 @@ impl Inliner<'tcx> {
|
||||
|
||||
let ty = arg.ty(caller_body, self.tcx);
|
||||
|
||||
let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span);
|
||||
let arg_tmp = LocalDecl::new(ty, callsite.location.span);
|
||||
let arg_tmp = caller_body.local_decls.push(arg_tmp);
|
||||
|
||||
let stmt = Statement {
|
||||
|
@ -778,7 +778,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
self.promoted.basic_blocks_mut().push(BasicBlockData {
|
||||
statements: vec![],
|
||||
terminator: Some(Terminator {
|
||||
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
source_info: SourceInfo::outermost(span),
|
||||
kind: TerminatorKind::Return,
|
||||
}),
|
||||
is_cleanup: false,
|
||||
@ -789,7 +789,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
let last = self.promoted.basic_blocks().last().unwrap();
|
||||
let data = &mut self.promoted[last];
|
||||
data.statements.push(Statement {
|
||||
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
source_info: SourceInfo::outermost(span),
|
||||
kind: StatementKind::Assign(box (Place::from(dest), rvalue)),
|
||||
});
|
||||
}
|
||||
@ -818,7 +818,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let num_stmts = self.source[loc.block].statements.len();
|
||||
let new_temp = self.promoted.local_decls.push(LocalDecl::new_temp(
|
||||
let new_temp = self.promoted.local_decls.push(LocalDecl::new(
|
||||
self.source.local_decls[temp].ty,
|
||||
self.source.local_decls[temp].source_info.span,
|
||||
));
|
||||
@ -918,7 +918,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let mut promoted_operand = |ty, span| {
|
||||
promoted.span = span;
|
||||
promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
|
||||
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
|
||||
|
||||
Operand::Constant(Box::new(Constant {
|
||||
span,
|
||||
@ -966,7 +966,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
// Create a temp to hold the promoted reference.
|
||||
// This is because `*r` requires `r` to be a local,
|
||||
// otherwise we would use the `promoted` directly.
|
||||
let mut promoted_ref = LocalDecl::new_temp(ref_ty, span);
|
||||
let mut promoted_ref = LocalDecl::new(ref_ty, span);
|
||||
promoted_ref.source_info = statement.source_info;
|
||||
let promoted_ref = local_decls.push(promoted_ref);
|
||||
assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);
|
||||
@ -1084,8 +1084,7 @@ pub fn promote_candidates<'tcx>(
|
||||
}
|
||||
|
||||
// Declare return place local so that `mir::Body::new` doesn't complain.
|
||||
let initial_locals =
|
||||
iter::once(LocalDecl::new_return_place(tcx.types.never, body.span)).collect();
|
||||
let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect();
|
||||
|
||||
let mut promoted = Body::new(
|
||||
IndexVec::new(),
|
||||
|
@ -50,7 +50,7 @@ impl<'tcx> MirPatch<'tcx> {
|
||||
result.new_block(BasicBlockData {
|
||||
statements: vec![],
|
||||
terminator: Some(Terminator {
|
||||
source_info: SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
source_info: SourceInfo::outermost(body.span),
|
||||
kind: TerminatorKind::Resume,
|
||||
}),
|
||||
is_cleanup: true,
|
||||
@ -83,14 +83,14 @@ impl<'tcx> MirPatch<'tcx> {
|
||||
pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
|
||||
let index = self.next_local;
|
||||
self.next_local += 1;
|
||||
self.new_locals.push(LocalDecl::new_temp(ty, span));
|
||||
self.new_locals.push(LocalDecl::new(ty, span));
|
||||
Local::new(index as usize)
|
||||
}
|
||||
|
||||
pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
|
||||
let index = self.next_local;
|
||||
self.next_local += 1;
|
||||
self.new_locals.push(LocalDecl::new_internal(ty, span));
|
||||
self.new_locals.push(LocalDecl::new(ty, span).internal());
|
||||
Local::new(index as usize)
|
||||
}
|
||||
|
||||
|
@ -472,8 +472,10 @@ fn write_scope_tree(
|
||||
|
||||
let mut indented_decl =
|
||||
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
|
||||
for user_ty in local_decl.user_ty.projections() {
|
||||
write!(indented_decl, " as {:?}", user_ty).unwrap();
|
||||
if let Some(user_ty) = &local_decl.user_ty {
|
||||
for user_ty in user_ty.projections() {
|
||||
write!(indented_decl, " as {:?}", user_ty).unwrap();
|
||||
}
|
||||
}
|
||||
indented_decl.push_str(";");
|
||||
|
||||
|
@ -383,7 +383,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let fake_borrow_ty =
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
|
||||
let fake_borrow_temp =
|
||||
self.local_decls.push(LocalDecl::new_temp(fake_borrow_ty, expr_span));
|
||||
self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span));
|
||||
let projection = tcx.intern_place_elems(&base_place.projection[..idx]);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
|
@ -97,7 +97,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// The `Box<T>` temporary created here is not a part of the HIR,
|
||||
// and therefore is not considered during generator OIBIT
|
||||
// determination. See the comment about `box` at `yield_in_scope`.
|
||||
let result = this.local_decls.push(LocalDecl::new_internal(expr.ty, expr_span));
|
||||
let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal());
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement { source_info, kind: StatementKind::StorageLive(result) },
|
||||
@ -377,7 +377,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let this = self;
|
||||
|
||||
let source_info = this.source_info(upvar_span);
|
||||
let temp = this.local_decls.push(LocalDecl::new_temp(upvar_ty, upvar_span));
|
||||
let temp = this.local_decls.push(LocalDecl::new(upvar_ty, upvar_span));
|
||||
|
||||
this.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
|
||||
|
||||
|
@ -52,7 +52,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
let expr_ty = expr.ty;
|
||||
let temp = {
|
||||
let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span);
|
||||
let mut local_decl = LocalDecl::new(expr_ty, expr_span);
|
||||
if mutability == Mutability::Not {
|
||||
local_decl = local_decl.immutable();
|
||||
}
|
||||
@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if let ExprKind::StaticRef { def_id, .. } = expr.kind {
|
||||
let is_thread_local = this.hir.tcx().is_thread_local_static(def_id);
|
||||
local_decl.internal = true;
|
||||
local_decl.local_info = LocalInfo::StaticRef { def_id, is_thread_local };
|
||||
local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local });
|
||||
}
|
||||
this.local_decls.push(local_decl)
|
||||
};
|
||||
|
@ -187,15 +187,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let ptr_ty = ptr.ty;
|
||||
// Create an *internal* temp for the pointer, so that unsafety
|
||||
// checking won't complain about the raw pointer assignment.
|
||||
let ptr_temp = this.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ptr_ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
let ptr_temp = this.local_decls.push(LocalDecl::with_source_info(
|
||||
ptr_ty,
|
||||
source_info,
|
||||
internal: true,
|
||||
local_info: LocalInfo::Other,
|
||||
is_block_tail: None,
|
||||
});
|
||||
).internal());
|
||||
let ptr_temp = Place::from(ptr_temp);
|
||||
let block = unpack!(this.into(ptr_temp, block, ptr));
|
||||
this.into(this.hir.tcx().mk_place_deref(ptr_temp), block, val)
|
||||
@ -348,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// value is Sized. Usually, this is caught in type checking, but
|
||||
// in the case of box expr there is no such check.
|
||||
if !destination.projection.is_empty() {
|
||||
this.local_decls.push(LocalDecl::new_temp(expr.ty, expr.span));
|
||||
this.local_decls.push(LocalDecl::new(expr.ty, expr.span));
|
||||
}
|
||||
|
||||
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
|
||||
|
@ -470,9 +470,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
for binding in &candidate_ref.bindings {
|
||||
let local = self.var_local_id(binding.var_id, OutsideGuard);
|
||||
|
||||
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
|
||||
))) = self.local_decls[local].local_info
|
||||
)))) = self.local_decls[local].local_info
|
||||
{
|
||||
*match_place = Some(initializer);
|
||||
} else {
|
||||
@ -1539,7 +1539,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
|
||||
let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
|
||||
let fake_borrow_temp =
|
||||
self.local_decls.push(LocalDecl::new_temp(fake_borrow_ty, temp_span));
|
||||
self.local_decls.push(LocalDecl::new(fake_borrow_ty, temp_span));
|
||||
|
||||
(matched_place, fake_borrow_temp)
|
||||
})
|
||||
@ -1949,11 +1949,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let local = LocalDecl::<'tcx> {
|
||||
mutability,
|
||||
ty: var_ty,
|
||||
user_ty,
|
||||
user_ty: if user_ty.is_empty() { None } else { Some(box user_ty) },
|
||||
source_info,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode,
|
||||
// hypothetically, `visit_bindings` could try to unzip
|
||||
// an outermost hir::Ty as we descend, matching up
|
||||
@ -1962,7 +1962,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
opt_ty_info: None,
|
||||
opt_match_place,
|
||||
pat_span,
|
||||
}))),
|
||||
})))),
|
||||
};
|
||||
let for_arm_body = self.local_decls.push(local);
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
@ -1976,11 +1976,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// immutable to avoid the unused mut lint.
|
||||
mutability: Mutability::Not,
|
||||
ty: tcx.mk_imm_ref(tcx.lifetimes.re_erased, var_ty),
|
||||
user_ty: UserTypeProjections::none(),
|
||||
user_ty: None,
|
||||
source_info,
|
||||
internal: false,
|
||||
is_block_tail: None,
|
||||
local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)),
|
||||
local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))),
|
||||
});
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
|
@ -15,7 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// N.B., **No cleanup is scheduled for this temporary.** You should
|
||||
/// call `schedule_drop` once the temporary is initialized.
|
||||
crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
|
||||
let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
|
||||
let temp = self.local_decls.push(LocalDecl::new(ty, span));
|
||||
let place = Place::from(temp);
|
||||
debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
|
||||
place
|
||||
|
@ -708,15 +708,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t
|
||||
// Some MIR passes will expect the number of parameters to match the
|
||||
// function declaration.
|
||||
for _ in 0..num_params {
|
||||
builder.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
internal: false,
|
||||
local_info: LocalInfo::Other,
|
||||
is_block_tail: None,
|
||||
});
|
||||
builder.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||
}
|
||||
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
||||
let mut body = builder.finish();
|
||||
@ -750,10 +742,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
guard_context: vec![],
|
||||
push_unsafe_count: 0,
|
||||
unpushed_unsafe: safety,
|
||||
local_decls: IndexVec::from_elem_n(
|
||||
LocalDecl::new_return_place(return_ty, return_span),
|
||||
1,
|
||||
),
|
||||
local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
|
||||
canonical_user_type_annotations: IndexVec::new(),
|
||||
upvar_mutbls: vec![],
|
||||
var_indices: Default::default(),
|
||||
@ -804,19 +793,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
) -> BlockAnd<()> {
|
||||
// Allocate locals for the function arguments
|
||||
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
|
||||
let source_info = SourceInfo {
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
span: arg_opt.map_or(self.fn_span, |arg| arg.pat.span),
|
||||
};
|
||||
let arg_local = self.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
internal: false,
|
||||
local_info: LocalInfo::Other,
|
||||
is_block_tail: None,
|
||||
});
|
||||
let source_info =
|
||||
SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
|
||||
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||
|
||||
// If this is a simple binding pattern, give debuginfo a nice name.
|
||||
if let Some(arg) = arg_opt {
|
||||
@ -885,10 +864,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info: SourceInfo {
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
span: tcx_hir.span(var_id),
|
||||
},
|
||||
source_info: SourceInfo::outermost(tcx_hir.span(var_id)),
|
||||
place: Place {
|
||||
local: closure_env_arg,
|
||||
projection: tcx.intern_place_elems(&projs),
|
||||
@ -933,17 +909,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.local_decls[local].mutability = mutability;
|
||||
self.local_decls[local].source_info.scope = self.source_scope;
|
||||
self.local_decls[local].local_info = if let Some(kind) = self_binding {
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind))))
|
||||
} else {
|
||||
let binding_mode = ty::BindingMode::BindByValue(mutability);
|
||||
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm {
|
||||
binding_mode,
|
||||
opt_ty_info,
|
||||
opt_match_place: Some((Some(place), span)),
|
||||
pat_span: span,
|
||||
},
|
||||
)))
|
||||
))))
|
||||
};
|
||||
self.var_indices.insert(var, LocalsForNode::One(local));
|
||||
}
|
||||
|
@ -989,7 +989,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let resumeblk = self.cfg.start_new_cleanup_block();
|
||||
self.cfg.terminate(
|
||||
resumeblk,
|
||||
SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span: self.fn_span },
|
||||
SourceInfo::outermost(self.fn_span),
|
||||
TerminatorKind::Resume,
|
||||
);
|
||||
self.cached_resume_block = Some(resumeblk);
|
||||
|
@ -589,7 +589,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
||||
// FIXME(66095): Because item.span is annotated with things
|
||||
// like expansion data, and ident.span isn't, we use the
|
||||
// def_span method if it's part of a macro invocation
|
||||
// (and thus has asource_callee set).
|
||||
// (and thus has a source_callee set).
|
||||
// We should probably annotate ident.span with the macro
|
||||
// context, but that's a larger change.
|
||||
if item.span.source_callee().is_some() {
|
||||
@ -653,7 +653,17 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
||||
}
|
||||
hir::ImplItemKind::Fn(_, body_id) => {
|
||||
if !self.symbol_is_live(impl_item.hir_id) {
|
||||
let span = self.tcx.sess.source_map().guess_head_span(impl_item.span);
|
||||
// FIXME(66095): Because impl_item.span is annotated with things
|
||||
// like expansion data, and ident.span isn't, we use the
|
||||
// def_span method if it's part of a macro invocation
|
||||
// (and thus has a source_callee set).
|
||||
// We should probably annotate ident.span with the macro
|
||||
// context, but that's a larger change.
|
||||
let span = if impl_item.span.source_callee().is_some() {
|
||||
self.tcx.sess.source_map().guess_head_span(impl_item.span)
|
||||
} else {
|
||||
impl_item.ident.span
|
||||
};
|
||||
self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "used");
|
||||
}
|
||||
self.visit_nested_body(body_id)
|
||||
|
@ -44,7 +44,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
|
||||
/// first canonicalize the key and then invoke the query on the tcx,
|
||||
/// which produces the resulting query region constraints.
|
||||
///
|
||||
/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html
|
||||
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
|
||||
type QueryResponse: TypeFoldable<'tcx>;
|
||||
|
||||
|
@ -517,6 +517,11 @@ pub trait Read {
|
||||
/// reader will *always* no longer be able to produce bytes.
|
||||
/// 2. The buffer specified was 0 bytes in length.
|
||||
///
|
||||
/// It is not an error if the returned value `n` is smaller than the buffer size,
|
||||
/// even when the reader is not at the end of the stream yet.
|
||||
/// This may happen for example because fewer bytes are actually available right now
|
||||
/// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
|
||||
///
|
||||
/// No guarantees are provided about the contents of `buf` when this
|
||||
/// function is called, implementations cannot rely on any property of the
|
||||
/// contents of `buf` being true. It is recommended that *implementations*
|
||||
|
@ -3,9 +3,18 @@
|
||||
// Test several functions can be used for constants
|
||||
// 1. Vec::new()
|
||||
// 2. String::new()
|
||||
// 3. BTreeMap::new()
|
||||
// 4. BTreeSet::new()
|
||||
|
||||
#![feature(const_btree_new)]
|
||||
|
||||
const MY_VEC: Vec<usize> = Vec::new();
|
||||
|
||||
const MY_STRING: String = String::new();
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
const MY_BTREEMAP: BTreeMap<u32, u32> = BTreeMap::new();
|
||||
|
||||
const MY_BTREESET: BTreeSet<u32> = BTreeSet::new();
|
||||
|
||||
fn main() {}
|
||||
|
@ -11,10 +11,10 @@ LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: associated function is never used: `foo`
|
||||
--> $DIR/lint-dead-code-3.rs:15:5
|
||||
--> $DIR/lint-dead-code-3.rs:15:8
|
||||
|
|
||||
LL | fn foo(&self) {
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^^^
|
||||
|
||||
error: function is never used: `bar`
|
||||
--> $DIR/lint-dead-code-3.rs:20:4
|
||||
|
20
src/test/ui/lint/dead-code/lint-dead-code-6.rs
Normal file
20
src/test/ui/lint/dead-code/lint-dead-code-6.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![deny(dead_code)]
|
||||
|
||||
struct UnusedStruct; //~ ERROR struct is never constructed: `UnusedStruct`
|
||||
impl UnusedStruct {
|
||||
fn unused_impl_fn_1() { //~ ERROR associated function is never used: `unused_impl_fn_1`
|
||||
println!("blah");
|
||||
}
|
||||
|
||||
fn unused_impl_fn_2(var: i32) { //~ ERROR associated function is never used: `unused_impl_fn_2`
|
||||
println!("foo {}", var);
|
||||
}
|
||||
|
||||
fn unused_impl_fn_3( //~ ERROR associated function is never used: `unused_impl_fn_3`
|
||||
var: i32,
|
||||
) {
|
||||
println!("bar {}", var);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
32
src/test/ui/lint/dead-code/lint-dead-code-6.stderr
Normal file
32
src/test/ui/lint/dead-code/lint-dead-code-6.stderr
Normal file
@ -0,0 +1,32 @@
|
||||
error: struct is never constructed: `UnusedStruct`
|
||||
--> $DIR/lint-dead-code-6.rs:3:8
|
||||
|
|
||||
LL | struct UnusedStruct;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-dead-code-6.rs:1:9
|
||||
|
|
||||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: associated function is never used: `unused_impl_fn_1`
|
||||
--> $DIR/lint-dead-code-6.rs:5:8
|
||||
|
|
||||
LL | fn unused_impl_fn_1() {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: associated function is never used: `unused_impl_fn_2`
|
||||
--> $DIR/lint-dead-code-6.rs:9:8
|
||||
|
|
||||
LL | fn unused_impl_fn_2(var: i32) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: associated function is never used: `unused_impl_fn_3`
|
||||
--> $DIR/lint-dead-code-6.rs:13:8
|
||||
|
|
||||
LL | fn unused_impl_fn_3(
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
Loading…
x
Reference in New Issue
Block a user