mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Merge from rustc
This commit is contained in:
commit
7b1cb69efa
@ -305,7 +305,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
);
|
||||
this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
|
||||
}
|
||||
Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
|
||||
Some(ty) => this.lower_ty(
|
||||
ty,
|
||||
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false },
|
||||
),
|
||||
},
|
||||
);
|
||||
hir::ItemKind::TyAlias(ty, generics)
|
||||
@ -852,7 +855,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::ImplItemKind::Type(ty)
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
|
||||
let ty = this.lower_ty(
|
||||
ty,
|
||||
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true },
|
||||
);
|
||||
hir::ImplItemKind::Type(ty)
|
||||
}
|
||||
},
|
||||
|
@ -247,7 +247,7 @@ enum ImplTraitContext {
|
||||
in_trait: bool,
|
||||
},
|
||||
/// Impl trait in type aliases.
|
||||
TypeAliasesOpaqueTy,
|
||||
TypeAliasesOpaqueTy { in_assoc_ty: bool },
|
||||
/// `impl Trait` is unstably accepted in this position.
|
||||
FeatureGated(ImplTraitPosition, Symbol),
|
||||
/// `impl Trait` is not accepted in this position.
|
||||
@ -1407,14 +1407,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
*in_trait,
|
||||
itctx,
|
||||
),
|
||||
ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
|
||||
span,
|
||||
hir::OpaqueTyOrigin::TyAlias,
|
||||
*def_node_id,
|
||||
bounds,
|
||||
false,
|
||||
itctx,
|
||||
),
|
||||
&ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
|
||||
.lower_opaque_impl_trait(
|
||||
span,
|
||||
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
|
||||
*def_node_id,
|
||||
bounds,
|
||||
false,
|
||||
itctx,
|
||||
),
|
||||
ImplTraitContext::Universal => {
|
||||
let span = t.span;
|
||||
self.create_def(
|
||||
@ -1534,13 +1535,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
|
||||
// to capture the lifetimes that appear in the bounds. So visit the bounds to find out
|
||||
// exactly which ones those are.
|
||||
let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias {
|
||||
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
|
||||
Vec::new()
|
||||
} else {
|
||||
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
|
||||
// we only keep the lifetimes that appear in the `impl Debug` itself:
|
||||
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
|
||||
let lifetimes_to_remap = match origin {
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
|
||||
Vec::new()
|
||||
}
|
||||
hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..) => {
|
||||
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
|
||||
// we only keep the lifetimes that appear in the `impl Debug` itself:
|
||||
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
|
||||
}
|
||||
};
|
||||
debug!(?lifetimes_to_remap);
|
||||
|
||||
|
@ -328,7 +328,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
||||
|
||||
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
|
||||
// bottom = nothing is reserved or activated yet;
|
||||
BitSet::new_empty(self.borrow_set.len() * 2)
|
||||
BitSet::new_empty(self.borrow_set.len())
|
||||
}
|
||||
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
|
||||
|
@ -265,7 +265,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
|
||||
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
|
||||
// on stable and we'd break that.
|
||||
let OpaqueTyOrigin::TyAlias = origin else {
|
||||
let OpaqueTyOrigin::TyAlias { .. } = origin else {
|
||||
return definition_ty;
|
||||
};
|
||||
let def_id = opaque_type_key.def_id;
|
||||
@ -360,7 +360,7 @@ fn check_opaque_type_parameter_valid(
|
||||
// which would error here on all of the `'static` args.
|
||||
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
|
||||
// Check these
|
||||
OpaqueTyOrigin::TyAlias => {}
|
||||
OpaqueTyOrigin::TyAlias { .. } => {}
|
||||
}
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||
|
@ -562,15 +562,13 @@ pub(crate) mod printf {
|
||||
}
|
||||
|
||||
if let Type = state {
|
||||
drop(c);
|
||||
type_ = at.slice_between(next).unwrap();
|
||||
|
||||
// Don't use `move_to!` here, as we *can* be at the end of the input.
|
||||
at = next;
|
||||
}
|
||||
|
||||
drop(c);
|
||||
drop(next);
|
||||
let _ = c; // to avoid never used value
|
||||
|
||||
end = at;
|
||||
let position = InnerSpan::new(start.at, end.at);
|
||||
|
@ -321,6 +321,8 @@ declare_features! (
|
||||
(active, c_unwind, "1.52.0", Some(74990), None),
|
||||
/// Allows using C-variadics.
|
||||
(active, c_variadic, "1.34.0", Some(44930), None),
|
||||
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
|
||||
(active, cfg_overflow_checks, "CURRENT_RUSTC_VERSION", Some(111466), None),
|
||||
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
|
||||
(active, cfg_sanitize, "1.41.0", Some(39699), None),
|
||||
/// Allows `cfg(target_abi = "...")`.
|
||||
|
@ -24,6 +24,7 @@ pub type GatedCfg = (Symbol, Symbol, GateFn);
|
||||
/// `cfg(...)`'s that are feature gated.
|
||||
const GATED_CFGS: &[GatedCfg] = &[
|
||||
// (name in cfg, feature, function to check if the feature is enabled)
|
||||
(sym::overflow_checks, sym::cfg_overflow_checks, cfg_fn!(cfg_overflow_checks)),
|
||||
(sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
|
||||
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
|
||||
(
|
||||
|
@ -2662,7 +2662,10 @@ pub enum OpaqueTyOrigin {
|
||||
/// `async fn`
|
||||
AsyncFn(LocalDefId),
|
||||
/// type aliases: `type Foo = impl Trait;`
|
||||
TyAlias,
|
||||
TyAlias {
|
||||
/// associated types in impl blocks for traits.
|
||||
in_assoc_ty: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// The various kinds of types recognized by the compiler.
|
||||
|
@ -397,7 +397,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
) {
|
||||
let defining_use_anchor = match *origin {
|
||||
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
|
||||
hir::OpaqueTyOrigin::TyAlias => def_id,
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
|
||||
};
|
||||
let param_env = tcx.param_env(defining_use_anchor);
|
||||
|
||||
@ -455,10 +455,10 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
|
||||
// We don't have to check them here because their well-formedness follows from the WF of
|
||||
// the projection input types in the defining- and use-sites.
|
||||
hir::OpaqueTyOrigin::TyAlias
|
||||
hir::OpaqueTyOrigin::TyAlias { .. }
|
||||
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
|
||||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
|
@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, ErrorGuaranteed};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::util::IgnoreRegions;
|
||||
use rustc_middle::ty::util::CheckRegions;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
@ -81,7 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
|
||||
self_type_did: DefId,
|
||||
adt_to_impl_substs: SubstsRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, IgnoreRegions::No) else {
|
||||
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
|
||||
return Ok(())
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, DelayDm};
|
||||
use rustc_errors::{Diagnostic, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IgnoreRegions;
|
||||
use rustc_middle::ty::util::CheckRegions;
|
||||
use rustc_middle::ty::{
|
||||
self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
TypeVisitor,
|
||||
@ -507,7 +507,7 @@ fn lint_auto_trait_impl<'tcx>(
|
||||
// Impls which completely cover a given root type are fine as they
|
||||
// disable auto impls entirely. So only lint if the substs
|
||||
// are not a permutation of the identity substs.
|
||||
let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
|
||||
let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
|
||||
// ok
|
||||
return;
|
||||
};
|
||||
|
@ -1483,7 +1483,7 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorK
|
||||
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
|
||||
match tcx.hir().get_by_def_id(def_id) {
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
|
||||
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
|
||||
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
|
||||
}
|
||||
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
|
||||
}
|
||||
|
@ -159,7 +159,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
}
|
||||
Some(fn_def_id.to_def_id())
|
||||
}
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
}) => {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
|
||||
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
|
||||
|
@ -721,7 +721,7 @@ pub(super) fn type_param_predicates(
|
||||
| ItemKind::TyAlias(_, generics)
|
||||
| ItemKind::OpaqueTy(OpaqueTy {
|
||||
generics,
|
||||
origin: hir::OpaqueTyOrigin::TyAlias,
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
})
|
||||
| ItemKind::Enum(_, generics)
|
||||
|
@ -526,7 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
});
|
||||
}
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias, ..
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
}) => {
|
||||
// Opaque types are visited when we visit the
|
||||
// `TyKind::OpaqueDef`, so that they have the lifetimes from
|
||||
@ -707,7 +708,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
let opaque_ty = self.tcx.hir().item(item_id);
|
||||
match &opaque_ty.kind {
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias,
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
}) => {
|
||||
intravisit::walk_ty(self, ty);
|
||||
|
@ -426,9 +426,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
tcx.mk_adt(def, substs)
|
||||
}
|
||||
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
|
||||
find_opaque_ty_constraints_for_tait(tcx, def_id)
|
||||
}
|
||||
ItemKind::OpaqueTy(OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
}) => find_opaque_ty_constraints_for_tait(tcx, def_id),
|
||||
// Opaque types desugared from `impl Trait`.
|
||||
ItemKind::OpaqueTy(OpaqueTy {
|
||||
origin:
|
||||
|
@ -2,6 +2,7 @@ use super::TypeErrCtxt;
|
||||
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
|
||||
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::error::ExpectedFound;
|
||||
use rustc_middle::ty::print::Printer;
|
||||
@ -256,6 +257,15 @@ impl<T> Trait<T> for X {
|
||||
);
|
||||
}
|
||||
}
|
||||
(ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
|
||||
if tcx.is_type_alias_impl_trait(alias.def_id) {
|
||||
if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
|
||||
diag.span_note(tcx.def_span(body_owner_def_id), "\
|
||||
this item must have the opaque type in its signature \
|
||||
in order to be able to register hidden types");
|
||||
}
|
||||
}
|
||||
}
|
||||
(ty::FnPtr(_), ty::FnDef(def, _))
|
||||
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
|
||||
diag.note(
|
||||
|
@ -828,7 +828,7 @@ where
|
||||
} else {
|
||||
match variables.probe(vid) {
|
||||
TypeVariableValue::Known { value: u } => {
|
||||
drop(variables);
|
||||
drop(inner);
|
||||
self.relate(u, u)
|
||||
}
|
||||
TypeVariableValue::Unknown { universe: _universe } => {
|
||||
|
@ -149,7 +149,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
// no one encounters it in practice.
|
||||
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
|
||||
// where it is of no concern, so we only check for TAITs.
|
||||
if let Some(OpaqueTyOrigin::TyAlias) =
|
||||
if let Some(OpaqueTyOrigin::TyAlias { .. }) =
|
||||
b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id))
|
||||
{
|
||||
self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
|
||||
@ -381,8 +381,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
// Anonymous `impl Trait`
|
||||
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
|
||||
// Named `type Foo = impl Bar;`
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
|
||||
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
|
||||
if in_assoc_ty {
|
||||
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
|
||||
} else {
|
||||
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
|
||||
}
|
||||
}
|
||||
};
|
||||
in_definition_scope.then_some(origin)
|
||||
|
@ -520,3 +520,19 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
|
||||
.specifically = this associated type bound is unsatisfied for `{$proj_ty}`
|
||||
|
||||
lint_opaque_hidden_inferred_bound_sugg = add this bound
|
||||
|
||||
lint_drop_ref = calls to `std::mem::drop` with a reference instead of an owned value does nothing
|
||||
.label = argument has type `{$arg_ty}`
|
||||
.note = use `let _ = ...` to ignore the expression or result
|
||||
|
||||
lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy` does nothing
|
||||
.label = argument has type `{$arg_ty}`
|
||||
.note = use `let _ = ...` to ignore the expression or result
|
||||
|
||||
lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value does nothing
|
||||
.label = argument has type `{$arg_ty}`
|
||||
.note = use `let _ = ...` to ignore the expression or result
|
||||
|
||||
lint_forget_copy = calls to `std::mem::forget` with a value that implements `Copy` does nothing
|
||||
.label = argument has type `{$arg_ty}`
|
||||
.note = use `let _ = ...` to ignore the expression or result
|
||||
|
164
compiler/rustc_lint/src/drop_forget_useless.rs
Normal file
164
compiler/rustc_lint/src/drop_forget_useless.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use rustc_hir::{Arm, Expr, ExprKind, Node};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::{
|
||||
lints::{DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag},
|
||||
LateContext, LateLintPass, LintContext,
|
||||
};
|
||||
|
||||
declare_lint! {
|
||||
/// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
|
||||
/// instead of an owned value.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn operation_that_requires_mutex_to_be_unlocked() {} // just to make it compile
|
||||
/// # let mutex = std::sync::Mutex::new(1); // just to make it compile
|
||||
/// let mut lock_guard = mutex.lock();
|
||||
/// std::mem::drop(&lock_guard); // Should have been drop(lock_guard), mutex
|
||||
/// // still locked
|
||||
/// operation_that_requires_mutex_to_be_unlocked();
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Calling `drop` on a reference will only drop the
|
||||
/// reference itself, which is a no-op. It will not call the `drop` method (from
|
||||
/// the `Drop` trait implementation) on the underlying referenced value, which
|
||||
/// is likely what was intended.
|
||||
pub DROP_REF,
|
||||
Warn,
|
||||
"calls to `std::mem::drop` with a reference instead of an owned value"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `forget_ref` lint checks for calls to `std::mem::forget` with a reference
|
||||
/// instead of an owned value.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let x = Box::new(1);
|
||||
/// std::mem::forget(&x); // Should have been forget(x), x will still be dropped
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Calling `forget` on a reference will only forget the
|
||||
/// reference itself, which is a no-op. It will not forget the underlying
|
||||
/// referenced value, which is likely what was intended.
|
||||
pub FORGET_REF,
|
||||
Warn,
|
||||
"calls to `std::mem::forget` with a reference instead of an owned value"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `drop_copy` lint checks for calls to `std::mem::drop` with a value
|
||||
/// that derives the Copy trait.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let x: i32 = 42; // i32 implements Copy
|
||||
/// std::mem::drop(x); // A copy of x is passed to the function, leaving the
|
||||
/// // original unaffected
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Calling `std::mem::drop` [does nothing for types that
|
||||
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
|
||||
/// value will be copied and moved into the function on invocation.
|
||||
pub DROP_COPY,
|
||||
Warn,
|
||||
"calls to `std::mem::drop` with a value that implements Copy"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `forget_copy` lint checks for calls to `std::mem::forget` with a value
|
||||
/// that derives the Copy trait.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let x: i32 = 42; // i32 implements Copy
|
||||
/// std::mem::forget(x); // A copy of x is passed to the function, leaving the
|
||||
/// // original unaffected
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Calling `std::mem::forget` [does nothing for types that
|
||||
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
|
||||
/// value will be copied and moved into the function on invocation.
|
||||
///
|
||||
/// An alternative, but also valid, explanation is that Copy types do not
|
||||
/// implement the Drop trait, which means they have no destructors. Without a
|
||||
/// destructor, there is nothing for `std::mem::forget` to ignore.
|
||||
pub FORGET_COPY,
|
||||
Warn,
|
||||
"calls to `std::mem::forget` with a value that implements Copy"
|
||||
}
|
||||
|
||||
declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Call(path, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
|
||||
{
|
||||
let arg_ty = cx.typeck_results().expr_ty(arg);
|
||||
let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
|
||||
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
|
||||
match fn_name {
|
||||
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
|
||||
cx.emit_spanned_lint(DROP_REF, expr.span, DropRefDiag { arg_ty, label: arg.span });
|
||||
},
|
||||
sym::mem_forget if arg_ty.is_ref() => {
|
||||
cx.emit_spanned_lint(FORGET_REF, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
|
||||
},
|
||||
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
|
||||
cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, label: arg.span });
|
||||
}
|
||||
sym::mem_forget if is_copy => {
|
||||
cx.emit_spanned_lint(FORGET_COPY, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dropping returned value of a function, as in the following snippet is considered idiomatic, see
|
||||
// rust-lang/rust-clippy#9482 for examples.
|
||||
//
|
||||
// ```
|
||||
// match <var> {
|
||||
// <pat> => drop(fn_with_side_effect_and_returning_some_value()),
|
||||
// ..
|
||||
// }
|
||||
// ```
|
||||
fn is_single_call_in_arm<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
arg: &'tcx Expr<'_>,
|
||||
drop_expr: &'tcx Expr<'_>,
|
||||
) -> bool {
|
||||
if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
|
||||
let parent_node = cx.tcx.hir().find_parent(drop_expr.hir_id);
|
||||
if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
|
||||
return body.hir_id == drop_expr.hir_id;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
@ -52,6 +52,7 @@ mod array_into_iter;
|
||||
pub mod builtin;
|
||||
mod context;
|
||||
mod deref_into_dyn_supertrait;
|
||||
mod drop_forget_useless;
|
||||
mod early;
|
||||
mod enum_intrinsics_non_enums;
|
||||
mod errors;
|
||||
@ -96,6 +97,7 @@ use rustc_span::Span;
|
||||
use array_into_iter::ArrayIntoIter;
|
||||
use builtin::*;
|
||||
use deref_into_dyn_supertrait::*;
|
||||
use drop_forget_useless::*;
|
||||
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
|
||||
use for_loops_over_fallibles::*;
|
||||
use hidden_unicode_codepoints::*;
|
||||
@ -201,6 +203,7 @@ late_lint_methods!(
|
||||
[
|
||||
ForLoopsOverFallibles: ForLoopsOverFallibles,
|
||||
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
|
||||
DropForgetUseless: DropForgetUseless,
|
||||
HardwiredLints: HardwiredLints,
|
||||
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
|
||||
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
|
||||
|
@ -662,6 +662,43 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
|
||||
pub end_span: Span,
|
||||
}
|
||||
|
||||
// drop_ref.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_drop_ref)]
|
||||
#[note]
|
||||
pub struct DropRefDiag<'a> {
|
||||
pub arg_ty: Ty<'a>,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_drop_copy)]
|
||||
#[note]
|
||||
pub struct DropCopyDiag<'a> {
|
||||
pub arg_ty: Ty<'a>,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_forget_ref)]
|
||||
#[note]
|
||||
pub struct ForgetRefDiag<'a> {
|
||||
pub arg_ty: Ty<'a>,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_forget_copy)]
|
||||
#[note]
|
||||
pub struct ForgetCopyDiag<'a> {
|
||||
pub arg_ty: Ty<'a>,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
}
|
||||
|
||||
// hidden_unicode_codepoints.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_hidden_unicode_codepoints)]
|
||||
|
@ -745,6 +745,9 @@ LLVMRustOptimize(
|
||||
if (InstrProfileOutput) {
|
||||
Options.InstrProfileOutput = InstrProfileOutput;
|
||||
}
|
||||
// cargo run tests in multhreading mode by default
|
||||
// so use atomics for coverage counters
|
||||
Options.Atomic = true;
|
||||
MPM.addPass(InstrProfiling(Options, false));
|
||||
}
|
||||
);
|
||||
|
@ -856,7 +856,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
ty::EarlyBinder(&*output)
|
||||
}
|
||||
|
||||
fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef {
|
||||
fn get_variant(
|
||||
self,
|
||||
kind: DefKind,
|
||||
index: DefIndex,
|
||||
parent_did: DefId,
|
||||
) -> (VariantIdx, ty::VariantDef) {
|
||||
let adt_kind = match kind {
|
||||
DefKind::Variant => ty::AdtKind::Enum,
|
||||
DefKind::Struct => ty::AdtKind::Struct,
|
||||
@ -870,22 +875,25 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
|
||||
let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));
|
||||
|
||||
ty::VariantDef::new(
|
||||
self.item_name(index),
|
||||
variant_did,
|
||||
ctor,
|
||||
data.discr,
|
||||
self.get_associated_item_or_field_def_ids(index)
|
||||
.map(|did| ty::FieldDef {
|
||||
did,
|
||||
name: self.item_name(did.index),
|
||||
vis: self.get_visibility(did.index),
|
||||
})
|
||||
.collect(),
|
||||
adt_kind,
|
||||
parent_did,
|
||||
false,
|
||||
data.is_non_exhaustive,
|
||||
(
|
||||
data.idx,
|
||||
ty::VariantDef::new(
|
||||
self.item_name(index),
|
||||
variant_did,
|
||||
ctor,
|
||||
data.discr,
|
||||
self.get_associated_item_or_field_def_ids(index)
|
||||
.map(|did| ty::FieldDef {
|
||||
did,
|
||||
name: self.item_name(did.index),
|
||||
vis: self.get_visibility(did.index),
|
||||
})
|
||||
.collect(),
|
||||
adt_kind,
|
||||
parent_did,
|
||||
false,
|
||||
data.is_non_exhaustive,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -901,7 +909,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
};
|
||||
let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self);
|
||||
|
||||
let variants = if let ty::AdtKind::Enum = adt_kind {
|
||||
let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind {
|
||||
self.root
|
||||
.tables
|
||||
.module_children_non_reexports
|
||||
@ -912,15 +920,22 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
let kind = self.def_kind(index);
|
||||
match kind {
|
||||
DefKind::Ctor(..) => None,
|
||||
_ => Some(self.get_variant(&kind, index, did)),
|
||||
_ => Some(self.get_variant(kind, index, did)),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
std::iter::once(self.get_variant(&kind, item_id, did)).collect()
|
||||
std::iter::once(self.get_variant(kind, item_id, did)).collect()
|
||||
};
|
||||
|
||||
tcx.mk_adt_def(did, adt_kind, variants, repr)
|
||||
variants.sort_by_key(|(idx, _)| *idx);
|
||||
|
||||
tcx.mk_adt_def(
|
||||
did,
|
||||
adt_kind,
|
||||
variants.into_iter().map(|(_, variant)| variant).collect(),
|
||||
repr,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
|
||||
|
@ -1375,9 +1375,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
// Therefore, the loop over variants will encode its fields as the adt's children.
|
||||
}
|
||||
|
||||
for variant in adt_def.variants().iter() {
|
||||
for (idx, variant) in adt_def.variants().iter_enumerated() {
|
||||
let data = VariantData {
|
||||
discr: variant.discr,
|
||||
idx,
|
||||
ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
|
||||
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
|
||||
};
|
||||
@ -1641,9 +1642,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
}
|
||||
hir::ItemKind::OpaqueTy(ref opaque) => {
|
||||
self.encode_explicit_item_bounds(def_id);
|
||||
self.tables
|
||||
.is_type_alias_impl_trait
|
||||
.set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias));
|
||||
self.tables.is_type_alias_impl_trait.set(
|
||||
def_id.index,
|
||||
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }),
|
||||
);
|
||||
}
|
||||
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
|
||||
self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
|
||||
|
@ -31,6 +31,7 @@ use rustc_span::edition::Edition;
|
||||
use rustc_span::hygiene::{ExpnIndex, MacroKind};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
@ -430,6 +431,7 @@ define_tables! {
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
struct VariantData {
|
||||
idx: VariantIdx,
|
||||
discr: ty::VariantDiscr,
|
||||
/// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
|
||||
ctor: Option<(CtorKind, DefIndex)>,
|
||||
|
@ -880,12 +880,11 @@ macro_rules! make_mir_visitor {
|
||||
) {
|
||||
let Constant {
|
||||
span,
|
||||
user_ty,
|
||||
user_ty: _, // no visit method for this
|
||||
literal,
|
||||
} = constant;
|
||||
|
||||
self.visit_span($(& $mutability)? *span);
|
||||
drop(user_ty); // no visit method for this
|
||||
match literal {
|
||||
ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
|
@ -172,6 +172,10 @@ impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
|
||||
type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
|
||||
}
|
||||
|
||||
impl EraseType for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
|
||||
type Result = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
|
||||
}
|
||||
|
||||
impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
|
||||
type Result = [u8; size_of::<(&'static (), &'static ())>()];
|
||||
}
|
||||
|
@ -236,6 +236,15 @@ rustc_queries! {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
query opaque_types_defined_by(
|
||||
key: LocalDefId
|
||||
) -> &'tcx [LocalDefId] {
|
||||
desc {
|
||||
|tcx| "computing the opaque types defined by `{}`",
|
||||
tcx.def_path_str(key.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of bounds that can be used for
|
||||
/// `SelectionCandidate::ProjectionCandidate(_)` and
|
||||
/// `ProjectionTyCandidate::TraitDef`.
|
||||
|
@ -281,9 +281,6 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
|
||||
ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
|
||||
|
||||
/// Obligation incurred due to an object cast.
|
||||
ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),
|
||||
|
||||
/// Obligation incurred due to a coercion.
|
||||
Coercion {
|
||||
source: Ty<'tcx>,
|
||||
|
@ -2476,6 +2476,18 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `DefId` of the item within which the `impl Trait` is declared.
|
||||
/// For type-alias-impl-trait this is the `type` alias.
|
||||
/// For impl-trait-in-assoc-type this is the assoc type.
|
||||
/// For return-position-impl-trait this is the function.
|
||||
pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
|
||||
// Find the surrounding item (type alias or assoc type)
|
||||
while let DefKind::OpaqueTy = self.def_kind(def_id) {
|
||||
def_id = self.local_parent(def_id);
|
||||
}
|
||||
def_id
|
||||
}
|
||||
|
||||
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
|
||||
if self.def_kind(def_id) != DefKind::AssocFn {
|
||||
return false;
|
||||
@ -2520,7 +2532,7 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId>
|
||||
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
|
||||
Some(parent)
|
||||
}
|
||||
hir::OpaqueTyOrigin::TyAlias => None,
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
///
|
||||
/// This should only be used outside of type inference. For example,
|
||||
/// it assumes that normalization will succeed.
|
||||
#[tracing::instrument(level = "debug", skip(self, param_env))]
|
||||
#[tracing::instrument(level = "debug", skip(self, param_env), ret)]
|
||||
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
@ -1265,7 +1265,7 @@ impl<'tcx> AliasTy<'tcx> {
|
||||
|
||||
/// Extracts the underlying trait reference and own substs from this projection.
|
||||
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
|
||||
/// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
|
||||
/// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own substs
|
||||
pub fn trait_ref_and_own_substs(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -34,9 +34,14 @@ pub struct Discr<'tcx> {
|
||||
|
||||
/// Used as an input to [`TyCtxt::uses_unique_generic_params`].
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum IgnoreRegions {
|
||||
Yes,
|
||||
pub enum CheckRegions {
|
||||
No,
|
||||
/// Only permit early bound regions. This is useful for Adts which
|
||||
/// can never have late bound regions.
|
||||
OnlyEarlyBound,
|
||||
/// Permit both late bound and early bound regions. Use this for functions,
|
||||
/// which frequently have late bound regions.
|
||||
Bound,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -468,21 +473,28 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn uses_unique_generic_params(
|
||||
self,
|
||||
substs: SubstsRef<'tcx>,
|
||||
ignore_regions: IgnoreRegions,
|
||||
ignore_regions: CheckRegions,
|
||||
) -> Result<(), NotUniqueParam<'tcx>> {
|
||||
let mut seen = GrowableBitSet::default();
|
||||
let mut seen_late = FxHashSet::default();
|
||||
for arg in substs {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
if ignore_regions == IgnoreRegions::No {
|
||||
let ty::ReEarlyBound(p) = lt.kind() else {
|
||||
return Err(NotUniqueParam::NotParam(lt.into()))
|
||||
};
|
||||
GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
|
||||
(CheckRegions::Bound, ty::ReLateBound(di, reg)) => {
|
||||
if !seen_late.insert((di, reg)) {
|
||||
return Err(NotUniqueParam::DuplicateParam(lt.into()));
|
||||
}
|
||||
}
|
||||
(CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => {
|
||||
if !seen.insert(p.index) {
|
||||
return Err(NotUniqueParam::DuplicateParam(lt.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
(CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => {
|
||||
return Err(NotUniqueParam::NotParam(lt.into()));
|
||||
}
|
||||
(CheckRegions::No, _) => {}
|
||||
},
|
||||
GenericArgKind::Type(t) => match t.kind() {
|
||||
ty::Param(p) => {
|
||||
if !seen.insert(p.index) {
|
||||
|
@ -1060,6 +1060,9 @@ fn default_configuration(sess: &Session) -> CrateConfig {
|
||||
if sess.opts.debug_assertions {
|
||||
ret.insert((sym::debug_assertions, None));
|
||||
}
|
||||
if sess.overflow_checks() {
|
||||
ret.insert((sym::overflow_checks, None));
|
||||
}
|
||||
// JUSTIFICATION: before wrapper fn is available
|
||||
#[allow(rustc::bad_opt_access)]
|
||||
if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
|
||||
@ -1209,6 +1212,7 @@ impl CrateCheckConfig {
|
||||
sym::windows,
|
||||
sym::proc_macro,
|
||||
sym::debug_assertions,
|
||||
sym::overflow_checks,
|
||||
sym::target_thread_local,
|
||||
] {
|
||||
self.expecteds.entry(name).or_insert_with(no_values);
|
||||
|
@ -463,6 +463,7 @@ symbols! {
|
||||
cfg_doctest,
|
||||
cfg_eval,
|
||||
cfg_hide,
|
||||
cfg_overflow_checks,
|
||||
cfg_panic,
|
||||
cfg_sanitize,
|
||||
cfg_target_abi,
|
||||
@ -1065,6 +1066,7 @@ symbols! {
|
||||
or_patterns,
|
||||
other,
|
||||
out,
|
||||
overflow_checks,
|
||||
overlapping_marker_traits,
|
||||
owned_box,
|
||||
packed,
|
||||
|
@ -882,8 +882,8 @@ impl InlineAsmClobberAbi {
|
||||
_ => Err(&["C", "system", "efiapi"]),
|
||||
},
|
||||
InlineAsmArch::LoongArch64 => match name {
|
||||
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::LoongArch),
|
||||
_ => Err(&["C", "system", "efiapi"]),
|
||||
"C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
|
||||
_ => Err(&["C", "system"]),
|
||||
},
|
||||
_ => Err(&[]),
|
||||
}
|
||||
|
@ -797,9 +797,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err.span_label(span, explanation);
|
||||
}
|
||||
|
||||
if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
|
||||
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
|
||||
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
|
||||
if let ObligationCauseCode::Coercion { source, target } =
|
||||
*obligation.cause.code().peel_derives()
|
||||
{
|
||||
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
|
||||
self.suggest_borrowing_for_object_cast(
|
||||
&mut err,
|
||||
&root_obligation,
|
||||
source,
|
||||
target,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let UnsatisfiedConst(unsatisfied_const) = self
|
||||
@ -1510,7 +1518,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
| ObligationCauseCode::BindingObligation(_, _)
|
||||
| ObligationCauseCode::ExprItemObligation(..)
|
||||
| ObligationCauseCode::ExprBindingObligation(..)
|
||||
| ObligationCauseCode::ObjectCastObligation(..)
|
||||
| ObligationCauseCode::Coercion { .. }
|
||||
| ObligationCauseCode::OpaqueType
|
||||
);
|
||||
|
||||
|
@ -1442,8 +1442,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err: &mut Diagnostic,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
object_ty: Ty<'tcx>,
|
||||
target_ty: Ty<'tcx>,
|
||||
) {
|
||||
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
|
||||
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
|
||||
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
|
||||
|
||||
@ -1458,7 +1459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err.span_suggestion(
|
||||
obligation.cause.span.shrink_to_lo(),
|
||||
format!(
|
||||
"consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
|
||||
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
|
||||
),
|
||||
"&",
|
||||
Applicability::MaybeIncorrect,
|
||||
@ -2851,30 +2852,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err.span_note(tcx.def_span(item_def_id), descr);
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
|
||||
let (concrete_ty, concrete_file) =
|
||||
self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
|
||||
let (object_ty, object_file) =
|
||||
self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
|
||||
ObligationCauseCode::Coercion { source, target } => {
|
||||
let (source, source_file) =
|
||||
self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
|
||||
let (target, target_file) =
|
||||
self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
|
||||
err.note(with_forced_trimmed_paths!(format!(
|
||||
"required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
|
||||
"required for the cast from `{source}` to `{target}`",
|
||||
)));
|
||||
if let Some(file) = concrete_file {
|
||||
if let Some(file) = source_file {
|
||||
err.note(format!(
|
||||
"the full name for the casted type has been written to '{}'",
|
||||
"the full name for the source type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
}
|
||||
if let Some(file) = object_file {
|
||||
if let Some(file) = target_file {
|
||||
err.note(format!(
|
||||
"the full name for the object type has been written to '{}'",
|
||||
"the full name for the target type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::Coercion { source: _, target } => {
|
||||
err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
|
||||
}
|
||||
ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
|
||||
err.note(
|
||||
"the `Copy` trait is required because this value will be copied for each element of the array",
|
||||
|
@ -29,9 +29,9 @@ use crate::traits::{
|
||||
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
|
||||
ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
|
||||
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
|
||||
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
|
||||
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
|
||||
SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
|
||||
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
|
||||
ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
|
||||
TraitNotObjectSafe, TraitObligation, Unimplemented,
|
||||
};
|
||||
|
||||
use super::BuiltinImplConditions;
|
||||
@ -905,16 +905,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
.map_err(|_| Unimplemented)?;
|
||||
nested.extend(obligations);
|
||||
|
||||
// Register one obligation for 'a: 'b.
|
||||
let cause = ObligationCause::new(
|
||||
obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(source, target),
|
||||
);
|
||||
let outlives = ty::OutlivesPredicate(r_a, r_b);
|
||||
nested.push(Obligation::with_depth(
|
||||
tcx,
|
||||
cause,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
obligation.predicate.rebind(outlives),
|
||||
@ -1005,15 +999,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
nested.extend(obligations);
|
||||
|
||||
// Register one obligation for 'a: 'b.
|
||||
let cause = ObligationCause::new(
|
||||
obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(source, target),
|
||||
);
|
||||
let outlives = ty::OutlivesPredicate(r_a, r_b);
|
||||
nested.push(Obligation::with_depth(
|
||||
tcx,
|
||||
cause,
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
obligation.predicate.rebind(outlives),
|
||||
@ -1027,16 +1016,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return Err(TraitNotObjectSafe(did));
|
||||
}
|
||||
|
||||
let cause = ObligationCause::new(
|
||||
obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(source, target),
|
||||
);
|
||||
|
||||
let predicate_to_obligation = |predicate| {
|
||||
Obligation::with_depth(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
obligation.cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
predicate,
|
||||
@ -1056,7 +1039,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
);
|
||||
|
||||
// We can only make objects from sized types.
|
||||
let tr = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, cause.span, [source]);
|
||||
let tr = ty::TraitRef::from_lang_item(
|
||||
tcx,
|
||||
LangItem::Sized,
|
||||
obligation.cause.span,
|
||||
[source],
|
||||
);
|
||||
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
|
||||
|
||||
// If the type is `Foo + 'a`, ensure that the type
|
||||
|
@ -2647,14 +2647,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
let predicates = predicates.instantiate_own(tcx, substs);
|
||||
let mut obligations = Vec::with_capacity(predicates.len());
|
||||
for (index, (predicate, span)) in predicates.into_iter().enumerate() {
|
||||
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
|
||||
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
||||
derived,
|
||||
impl_or_alias_def_id: def_id,
|
||||
impl_def_predicate_index: Some(index),
|
||||
span,
|
||||
}))
|
||||
});
|
||||
let cause =
|
||||
if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() {
|
||||
cause.clone()
|
||||
} else {
|
||||
cause.clone().derived_cause(parent_trait_pred, |derived| {
|
||||
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
||||
derived,
|
||||
impl_or_alias_def_id: def_id,
|
||||
impl_def_predicate_index: Some(index),
|
||||
span,
|
||||
}))
|
||||
})
|
||||
};
|
||||
let predicate = normalize_with_depth_to(
|
||||
self,
|
||||
param_env,
|
||||
|
@ -55,3 +55,11 @@ ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with
|
||||
ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
|
||||
|
||||
ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
|
||||
|
||||
ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
|
||||
.label = generic argument `{$arg}` used twice
|
||||
.note = for this opaque type
|
||||
|
||||
ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
|
||||
.label = argument `{$arg}` is not a generic parameter
|
||||
.note = for this opaque type
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Errors emitted by ty_utils
|
||||
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{GenericArg, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -100,3 +100,25 @@ pub struct NonPrimitiveSimdType<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub e_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_impl_trait_duplicate_arg)]
|
||||
pub struct DuplicateArg<'tcx> {
|
||||
pub arg: GenericArg<'tcx>,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[note]
|
||||
pub opaque_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_impl_trait_not_param)]
|
||||
pub struct NotParam<'tcx> {
|
||||
pub arg: GenericArg<'tcx>,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[note]
|
||||
pub opaque_span: Span,
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ pub mod instance;
|
||||
mod layout;
|
||||
mod layout_sanity_check;
|
||||
mod needs_drop;
|
||||
mod opaque_types;
|
||||
pub mod representability;
|
||||
mod structural_match;
|
||||
mod ty;
|
||||
@ -47,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
implied_bounds::provide(providers);
|
||||
layout::provide(providers);
|
||||
needs_drop::provide(providers);
|
||||
opaque_types::provide(providers);
|
||||
representability::provide(providers);
|
||||
ty::provide(providers);
|
||||
instance::provide(providers);
|
||||
|
197
compiler/rustc_ty_utils/src/opaque_types.rs
Normal file
197
compiler/rustc_ty_utils/src/opaque_types.rs
Normal file
@ -0,0 +1,197 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::{def::DefKind, def_id::LocalDefId};
|
||||
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::AliasKind;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use crate::errors::{DuplicateArg, NotParam};
|
||||
|
||||
struct OpaqueTypeCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaques: Vec<LocalDefId>,
|
||||
/// The `DefId` of the item which we are collecting opaque types for.
|
||||
item: LocalDefId,
|
||||
|
||||
/// Avoid infinite recursion due to recursive declarations.
|
||||
seen: FxHashSet<LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeCollector<'tcx> {
|
||||
fn collect(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: LocalDefId,
|
||||
val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
|
||||
) -> Vec<LocalDefId> {
|
||||
let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
|
||||
val.skip_binder().visit_with(&mut collector);
|
||||
collector.opaques
|
||||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
self.tcx.def_span(self.item)
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<LocalDefId> {
|
||||
match self.tcx.def_kind(self.item) {
|
||||
DefKind::Fn => None,
|
||||
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||
Some(self.tcx.local_parent(self.item))
|
||||
}
|
||||
other => span_bug!(
|
||||
self.tcx.def_span(self.item),
|
||||
"unhandled item with opaque types: {other:?}"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||
type BreakTy = ErrorGuaranteed;
|
||||
|
||||
#[instrument(skip(self), ret, level = "trace")]
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
|
||||
match t.kind() {
|
||||
ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
|
||||
if !self.seen.insert(alias_ty.def_id.expect_local()) {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
|
||||
Ok(()) => {
|
||||
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
|
||||
// supported at all, so this is sound to do, but once we want to support them, you'll
|
||||
// start seeing the error below.
|
||||
|
||||
self.opaques.push(alias_ty.def_id.expect_local());
|
||||
|
||||
// Collect opaque types nested within the associated type bounds of this opaque type.
|
||||
for (pred, _span) in self
|
||||
.tcx
|
||||
.explicit_item_bounds(alias_ty.def_id)
|
||||
.subst_iter_copied(self.tcx, alias_ty.substs)
|
||||
{
|
||||
trace!(?pred);
|
||||
pred.visit_with(self)?;
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
Err(NotUniqueParam::NotParam(arg)) => {
|
||||
let err = self.tcx.sess.emit_err(NotParam {
|
||||
arg,
|
||||
span: self.span(),
|
||||
opaque_span: self.tcx.def_span(alias_ty.def_id),
|
||||
});
|
||||
ControlFlow::Break(err)
|
||||
}
|
||||
Err(NotUniqueParam::DuplicateParam(arg)) => {
|
||||
let err = self.tcx.sess.emit_err(DuplicateArg {
|
||||
arg,
|
||||
span: self.span(),
|
||||
opaque_span: self.tcx.def_span(alias_ty.def_id),
|
||||
});
|
||||
ControlFlow::Break(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Alias(AliasKind::Projection, alias_ty) => {
|
||||
if let Some(parent) = self.parent() {
|
||||
trace!(?alias_ty);
|
||||
let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx);
|
||||
|
||||
trace!(?trait_ref, ?own_substs);
|
||||
// This avoids having to do normalization of `Self::AssocTy` by only
|
||||
// supporting the case of a method defining opaque types from assoc types
|
||||
// in the same impl block.
|
||||
if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() {
|
||||
for assoc in self.tcx.associated_items(parent).in_definition_order() {
|
||||
trace!(?assoc);
|
||||
if assoc.trait_item_def_id == Some(alias_ty.def_id) {
|
||||
// We reconstruct the generic args of the associated type within the impl
|
||||
// from the impl's generics and the generic args passed to the type via the
|
||||
// projection.
|
||||
let substs = ty::InternalSubsts::identity_for_item(
|
||||
self.tcx,
|
||||
parent.to_def_id(),
|
||||
);
|
||||
trace!(?substs);
|
||||
let substs: Vec<_> =
|
||||
substs.iter().chain(own_substs.iter().copied()).collect();
|
||||
trace!(?substs);
|
||||
// Find opaque types in this associated type.
|
||||
return self
|
||||
.tcx
|
||||
.type_of(assoc.def_id)
|
||||
.subst(self.tcx, &substs)
|
||||
.visit_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
|
||||
let kind = tcx.def_kind(item);
|
||||
trace!(?kind);
|
||||
// FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
|
||||
match kind {
|
||||
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
|
||||
DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||
let defined_opaques = match kind {
|
||||
DefKind::Fn => {
|
||||
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
|
||||
}
|
||||
DefKind::AssocFn => {
|
||||
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
|
||||
}
|
||||
DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
|
||||
tcx,
|
||||
item,
|
||||
ty::Binder::dummy(tcx.type_of(item).subst_identity()),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
tcx.arena.alloc_from_iter(defined_opaques)
|
||||
}
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::TyParam
|
||||
| DefKind::Const
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Static(_)
|
||||
| DefKind::Ctor(_, _)
|
||||
| DefKind::Macro(_)
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::AnonConst
|
||||
| DefKind::InlineConst
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::ImplTraitPlaceholder
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator => &[],
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { opaque_types_defined_by, ..*providers };
|
||||
}
|
@ -766,16 +766,11 @@ impl<T: ?Sized> !Sync for *mut T {}
|
||||
///
|
||||
/// ## Ownership and the drop check
|
||||
///
|
||||
/// Adding a field of type `PhantomData<T>` indicates that your
|
||||
/// type owns data of type `T`. This in turn implies that when your
|
||||
/// type is dropped, it may drop one or more instances of the type
|
||||
/// `T`. This has bearing on the Rust compiler's [drop check]
|
||||
/// analysis.
|
||||
/// The exact interaction of `PhantomData` with drop check **may change in the future**.
|
||||
///
|
||||
/// If your struct does not in fact *own* the data of type `T`, it is
|
||||
/// better to use a reference type, like `PhantomData<&'a T>`
|
||||
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
|
||||
/// as not to indicate ownership.
|
||||
/// Currently, adding a field of type `PhantomData<T>` indicates that your type *owns* data of type
|
||||
/// `T` in very rare circumstances. This in turn has effects on the Rust compiler's [drop check]
|
||||
/// analysis. For the exact rules, see the [drop check] documentation.
|
||||
///
|
||||
/// ## Layout
|
||||
///
|
||||
@ -783,7 +778,7 @@ impl<T: ?Sized> !Sync for *mut T {}
|
||||
/// * `size_of::<PhantomData<T>>() == 0`
|
||||
/// * `align_of::<PhantomData<T>>() == 1`
|
||||
///
|
||||
/// [drop check]: ../../nomicon/dropck.html
|
||||
/// [drop check]: Drop#drop-check
|
||||
#[lang = "phantom_data"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
|
@ -968,6 +968,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
|
||||
/// Integers and other types implementing [`Copy`] are unaffected by `drop`.
|
||||
///
|
||||
/// ```
|
||||
/// # #![cfg_attr(not(bootstrap), allow(drop_copy))]
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct Foo(u8);
|
||||
///
|
||||
|
@ -132,6 +132,74 @@
|
||||
/// are `Copy` get implicitly duplicated by the compiler, making it very
|
||||
/// hard to predict when, and how often destructors will be executed. As such,
|
||||
/// these types cannot have destructors.
|
||||
///
|
||||
/// ## Drop check
|
||||
///
|
||||
/// Dropping interacts with the borrow checker in subtle ways: when a type `T` is being implicitly
|
||||
/// dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that
|
||||
/// calling `T`'s destructor at this moment is safe. In particular, it also needs to be safe to
|
||||
/// recursively drop all the fields of `T`. For example, it is crucial that code like the following
|
||||
/// is being rejected:
|
||||
///
|
||||
/// ```compile_fail,E0597
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// struct S<'a>(Cell<Option<&'a S<'a>>>, Box<i32>);
|
||||
/// impl Drop for S<'_> {
|
||||
/// fn drop(&mut self) {
|
||||
/// if let Some(r) = self.0.get() {
|
||||
/// // Print the contents of the `Box` in `r`.
|
||||
/// println!("{}", r.1);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// // Set up two `S` that point to each other.
|
||||
/// let s1 = S(Cell::new(None), Box::new(42));
|
||||
/// let s2 = S(Cell::new(Some(&s1)), Box::new(42));
|
||||
/// s1.0.set(Some(&s2));
|
||||
/// // Now they both get dropped. But whichever is the 2nd one
|
||||
/// // to be dropped will access the `Box` in the first one,
|
||||
/// // which is a use-after-free!
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The Nomicon discusses the need for [drop check in more detail][drop check].
|
||||
///
|
||||
/// To reject such code, the "drop check" analysis determines which types and lifetimes need to
|
||||
/// still be live when `T` gets dropped. The exact details of this analysis are not yet
|
||||
/// stably guaranteed and **subject to change**. Currently, the analysis works as follows:
|
||||
/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if
|
||||
/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`]
|
||||
/// and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type.
|
||||
/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`,
|
||||
/// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of
|
||||
/// owned types is determined by recursively traversing `T`:
|
||||
/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of
|
||||
/// length 0).
|
||||
/// - Stop at reference and raw pointer types as well as function pointers and function items;
|
||||
/// they do not own anything.
|
||||
/// - Stop at non-composite types (type parameters that remain generic in the current context and
|
||||
/// base types such as integers and `bool`); these types are owned.
|
||||
/// - When hitting an ADT with `impl Drop`, stop there; this type is owned.
|
||||
/// - When hitting an ADT without `impl Drop`, recursively descend to its fields. (For an `enum`,
|
||||
/// consider all fields of all variants.)
|
||||
/// - Furthermore, if `T` implements `Drop`, then all generic (lifetime and type) parameters of `T`
|
||||
/// must be live.
|
||||
///
|
||||
/// In the above example, the last clause implies that `'a` must be live when `S<'a>` is dropped,
|
||||
/// and hence the example is rejected. If we remove the `impl Drop`, the liveness requirement
|
||||
/// disappears and the example is accepted.
|
||||
///
|
||||
/// There exists an unstable way for a type to opt-out of the last clause; this is called "drop
|
||||
/// check eyepatch" or `may_dangle`. For more details on this nightly-only feature, see the
|
||||
/// [discussion in the Nomicon][nomicon].
|
||||
///
|
||||
/// [`ManuallyDrop`]: crate::mem::ManuallyDrop
|
||||
/// [`PhantomData`]: crate::marker::PhantomData
|
||||
/// [drop check]: ../../nomicon/dropck.html
|
||||
/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
|
||||
#[lang = "drop"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[const_trait]
|
||||
|
@ -90,8 +90,6 @@ impl<'a, T> Iter<'a, T> {
|
||||
let ptr = slice.as_ptr();
|
||||
// SAFETY: Similar to `IterMut::new`.
|
||||
unsafe {
|
||||
assume(!ptr.is_null());
|
||||
|
||||
let end = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) };
|
||||
|
||||
Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
|
||||
@ -228,8 +226,6 @@ impl<'a, T> IterMut<'a, T> {
|
||||
// See the `next_unchecked!` and `is_empty!` macros as well as the
|
||||
// `post_inc_start` method for more information.
|
||||
unsafe {
|
||||
assume(!ptr.is_null());
|
||||
|
||||
let end = if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) };
|
||||
|
||||
Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData }
|
||||
|
@ -116,7 +116,7 @@ impl<T> Poll<T> {
|
||||
/// let fut = Pin::new(&mut fut);
|
||||
///
|
||||
/// let num = fut.poll(cx).ready()?;
|
||||
/// # drop(num);
|
||||
/// # let _ = num; // to silence unused warning
|
||||
/// // ... use num
|
||||
///
|
||||
/// Poll::Ready(())
|
||||
|
@ -22,7 +22,7 @@ use core::task::Poll;
|
||||
/// let fut = Pin::new(&mut fut);
|
||||
///
|
||||
/// let num = ready!(fut.poll(cx));
|
||||
/// # drop(num);
|
||||
/// # let _ = num;
|
||||
/// // ... use num
|
||||
///
|
||||
/// Poll::Ready(())
|
||||
@ -44,7 +44,7 @@ use core::task::Poll;
|
||||
/// Poll::Ready(t) => t,
|
||||
/// Poll::Pending => return Poll::Pending,
|
||||
/// };
|
||||
/// # drop(num);
|
||||
/// # let _ = num; // to silence unused warning
|
||||
/// # // ... use num
|
||||
/// #
|
||||
/// # Poll::Ready(())
|
||||
|
@ -541,7 +541,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
||||
// Lazily, the first time this gets called, run the actual string formatting.
|
||||
self.string.get_or_insert_with(|| {
|
||||
let mut s = String::new();
|
||||
drop(s.write_fmt(*inner));
|
||||
let _err = s.write_fmt(*inner);
|
||||
s
|
||||
})
|
||||
}
|
||||
|
@ -202,12 +202,18 @@ impl WaitQueue {
|
||||
pub fn notify_one<T>(
|
||||
mut guard: SpinMutexGuard<'_, WaitVariable<T>>,
|
||||
) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
|
||||
// SAFETY: lifetime of the pop() return value is limited to the map
|
||||
// closure (The closure return value is 'static). The underlying
|
||||
// stack frame won't be freed until after the WaitGuard created below
|
||||
// is dropped.
|
||||
unsafe {
|
||||
if let Some(entry) = guard.queue.inner.pop() {
|
||||
let tcs = guard.queue.inner.pop().map(|entry| -> Tcs {
|
||||
let mut entry_guard = entry.lock();
|
||||
let tcs = entry_guard.tcs;
|
||||
entry_guard.wake = true;
|
||||
drop(entry);
|
||||
entry_guard.tcs
|
||||
});
|
||||
|
||||
if let Some(tcs) = tcs {
|
||||
Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::Single(tcs) })
|
||||
} else {
|
||||
Err(guard)
|
||||
@ -223,6 +229,9 @@ impl WaitQueue {
|
||||
pub fn notify_all<T>(
|
||||
mut guard: SpinMutexGuard<'_, WaitVariable<T>>,
|
||||
) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
|
||||
// SAFETY: lifetime of the pop() return values are limited to the
|
||||
// while loop body. The underlying stack frames won't be freed until
|
||||
// after the WaitGuard created below is dropped.
|
||||
unsafe {
|
||||
let mut count = 0;
|
||||
while let Some(entry) = guard.queue.inner.pop() {
|
||||
@ -230,6 +239,7 @@ impl WaitQueue {
|
||||
let mut entry_guard = entry.lock();
|
||||
entry_guard.wake = true;
|
||||
}
|
||||
|
||||
if let Some(count) = NonZeroUsize::new(count) {
|
||||
Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::All { count } })
|
||||
} else {
|
||||
|
@ -1210,7 +1210,7 @@ impl File {
|
||||
// Redox doesn't appear to support `UTIME_OMIT`.
|
||||
// ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
|
||||
// the same as for Redox.
|
||||
drop(times);
|
||||
let _ = times;
|
||||
Err(io::const_io_error!(
|
||||
io::ErrorKind::Unsupported,
|
||||
"setting file times not supported",
|
||||
|
@ -375,7 +375,9 @@ fn test_scoped_threads_nll() {
|
||||
// this is mostly a *compilation test* for this exact function:
|
||||
fn foo(x: &u8) {
|
||||
thread::scope(|s| {
|
||||
s.spawn(|| drop(x));
|
||||
s.spawn(|| match x {
|
||||
_ => (),
|
||||
});
|
||||
});
|
||||
}
|
||||
// let's also run it for good measure
|
||||
|
@ -455,7 +455,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
| hir::ItemKind::Union(..)
|
||||
| hir::ItemKind::TyAlias(..)
|
||||
| hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias, ..
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
})
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Trait(..)
|
||||
|
@ -132,12 +132,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
|
||||
crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
|
||||
crate::double_parens::DOUBLE_PARENS_INFO,
|
||||
crate::drop_forget_ref::DROP_COPY_INFO,
|
||||
crate::drop_forget_ref::DROP_NON_DROP_INFO,
|
||||
crate::drop_forget_ref::DROP_REF_INFO,
|
||||
crate::drop_forget_ref::FORGET_COPY_INFO,
|
||||
crate::drop_forget_ref::FORGET_NON_DROP_INFO,
|
||||
crate::drop_forget_ref::FORGET_REF_INFO,
|
||||
crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO,
|
||||
crate::duplicate_mod::DUPLICATE_MOD_INFO,
|
||||
crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
|
||||
|
@ -7,102 +7,6 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `std::mem::drop` with a reference
|
||||
/// instead of an owned value.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Calling `drop` on a reference will only drop the
|
||||
/// reference itself, which is a no-op. It will not call the `drop` method (from
|
||||
/// the `Drop` trait implementation) on the underlying referenced value, which
|
||||
/// is likely what was intended.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```ignore
|
||||
/// let mut lock_guard = mutex.lock();
|
||||
/// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
|
||||
/// // still locked
|
||||
/// operation_that_requires_mutex_to_be_unlocked();
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub DROP_REF,
|
||||
correctness,
|
||||
"calls to `std::mem::drop` with a reference instead of an owned value"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `std::mem::forget` with a reference
|
||||
/// instead of an owned value.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Calling `forget` on a reference will only forget the
|
||||
/// reference itself, which is a no-op. It will not forget the underlying
|
||||
/// referenced
|
||||
/// value, which is likely what was intended.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let x = Box::new(1);
|
||||
/// std::mem::forget(&x) // Should have been forget(x), x will still be dropped
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub FORGET_REF,
|
||||
correctness,
|
||||
"calls to `std::mem::forget` with a reference instead of an owned value"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `std::mem::drop` with a value
|
||||
/// that derives the Copy trait
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Calling `std::mem::drop` [does nothing for types that
|
||||
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
|
||||
/// value will be copied and moved into the function on invocation.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let x: i32 = 42; // i32 implements Copy
|
||||
/// std::mem::drop(x) // A copy of x is passed to the function, leaving the
|
||||
/// // original unaffected
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub DROP_COPY,
|
||||
correctness,
|
||||
"calls to `std::mem::drop` with a value that implements Copy"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `std::mem::forget` with a value that
|
||||
/// derives the Copy trait
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Calling `std::mem::forget` [does nothing for types that
|
||||
/// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
|
||||
/// value will be copied and moved into the function on invocation.
|
||||
///
|
||||
/// An alternative, but also valid, explanation is that Copy types do not
|
||||
/// implement
|
||||
/// the Drop trait, which means they have no destructors. Without a destructor,
|
||||
/// there
|
||||
/// is nothing for `std::mem::forget` to ignore.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let x: i32 = 42; // i32 implements Copy
|
||||
/// std::mem::forget(x) // A copy of x is passed to the function, leaving the
|
||||
/// // original unaffected
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub FORGET_COPY,
|
||||
correctness,
|
||||
"calls to `std::mem::forget` with a value that implements Copy"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calls to `std::mem::drop` with a value that does not implement `Drop`.
|
||||
@ -172,24 +76,12 @@ declare_clippy_lint! {
|
||||
"use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
|
||||
}
|
||||
|
||||
const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \
|
||||
Dropping a reference does nothing";
|
||||
const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \
|
||||
Forgetting a reference does nothing";
|
||||
const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements `Copy`. \
|
||||
Dropping a copy leaves the original intact";
|
||||
const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements `Copy`. \
|
||||
Forgetting a copy leaves the original intact";
|
||||
const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \
|
||||
Dropping such a type only extends its contained lifetimes";
|
||||
const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \
|
||||
Forgetting such a type is the same as dropping it";
|
||||
|
||||
declare_lint_pass!(DropForgetRef => [
|
||||
DROP_REF,
|
||||
FORGET_REF,
|
||||
DROP_COPY,
|
||||
FORGET_COPY,
|
||||
DROP_NON_DROP,
|
||||
FORGET_NON_DROP,
|
||||
UNDROPPED_MANUALLY_DROPS
|
||||
@ -206,10 +98,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
|
||||
let is_copy = is_copy(cx, arg_ty);
|
||||
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
|
||||
let (lint, msg) = match fn_name {
|
||||
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
|
||||
sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
|
||||
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
|
||||
sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
|
||||
// early return for uplifted lints: drop_ref, drop_copy, forget_ref, forget_copy
|
||||
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
|
||||
sym::mem_forget if arg_ty.is_ref() => return,
|
||||
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
|
||||
sym::mem_forget if is_copy => return,
|
||||
sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
|
@ -32,9 +32,13 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
||||
("clippy::zero_width_space", "clippy::invisible_characters"),
|
||||
("clippy::clone_double_ref", "suspicious_double_ref_op"),
|
||||
("clippy::drop_bounds", "drop_bounds"),
|
||||
("clippy::drop_copy", "drop_copy"),
|
||||
("clippy::drop_ref", "drop_ref"),
|
||||
("clippy::for_loop_over_option", "for_loops_over_fallibles"),
|
||||
("clippy::for_loop_over_result", "for_loops_over_fallibles"),
|
||||
("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
|
||||
("clippy::forget_copy", "forget_copy"),
|
||||
("clippy::forget_ref", "forget_ref"),
|
||||
("clippy::into_iter_on_array", "array_into_iter"),
|
||||
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
|
||||
("clippy::invalid_ref", "invalid_value"),
|
||||
|
@ -1,86 +0,0 @@
|
||||
#![warn(clippy::drop_copy, clippy::forget_copy)]
|
||||
#![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)]
|
||||
|
||||
use std::mem::{drop, forget};
|
||||
use std::vec::Vec;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct SomeStruct;
|
||||
|
||||
struct AnotherStruct {
|
||||
x: u8,
|
||||
y: u8,
|
||||
z: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Clone for AnotherStruct {
|
||||
fn clone(&self) -> AnotherStruct {
|
||||
AnotherStruct {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
z: self.z.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s1 = SomeStruct {};
|
||||
let s2 = s1;
|
||||
let s3 = &s1;
|
||||
let mut s4 = s1;
|
||||
let ref s5 = s1;
|
||||
|
||||
drop(s1);
|
||||
drop(s2);
|
||||
drop(s3);
|
||||
drop(s4);
|
||||
drop(s5);
|
||||
|
||||
forget(s1);
|
||||
forget(s2);
|
||||
forget(s3);
|
||||
forget(s4);
|
||||
forget(s5);
|
||||
|
||||
let a1 = AnotherStruct {
|
||||
x: 255,
|
||||
y: 0,
|
||||
z: vec![1, 2, 3],
|
||||
};
|
||||
let a2 = &a1;
|
||||
let mut a3 = a1.clone();
|
||||
let ref a4 = a1;
|
||||
let a5 = a1.clone();
|
||||
|
||||
drop(a2);
|
||||
drop(a3);
|
||||
drop(a4);
|
||||
drop(a5);
|
||||
|
||||
forget(a2);
|
||||
let a3 = &a1;
|
||||
forget(a3);
|
||||
forget(a4);
|
||||
let a5 = a1.clone();
|
||||
forget(a5);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[allow(clippy::unit_cmp)]
|
||||
fn issue9482(x: u8) {
|
||||
fn println_and<T>(t: T) -> T {
|
||||
println!("foo");
|
||||
t
|
||||
}
|
||||
|
||||
match x {
|
||||
0 => drop(println_and(12)), // Don't lint (copy type), we only care about side-effects
|
||||
1 => drop(println_and(String::new())), // Don't lint (no copy type), we only care about side-effects
|
||||
2 => {
|
||||
drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
},
|
||||
3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
4 => drop(2), // Lint, not a fn/method call
|
||||
_ => (),
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:33:5
|
||||
|
|
||||
LL | drop(s1);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:33:10
|
||||
|
|
||||
LL | drop(s1);
|
||||
| ^^
|
||||
= note: `-D clippy::drop-copy` implied by `-D warnings`
|
||||
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:34:5
|
||||
|
|
||||
LL | drop(s2);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:34:10
|
||||
|
|
||||
LL | drop(s2);
|
||||
| ^^
|
||||
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:36:5
|
||||
|
|
||||
LL | drop(s4);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:36:10
|
||||
|
|
||||
LL | drop(s4);
|
||||
| ^^
|
||||
|
||||
error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:39:5
|
||||
|
|
||||
LL | forget(s1);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:39:12
|
||||
|
|
||||
LL | forget(s1);
|
||||
| ^^
|
||||
= note: `-D clippy::forget-copy` implied by `-D warnings`
|
||||
|
||||
error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:40:5
|
||||
|
|
||||
LL | forget(s2);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:40:12
|
||||
|
|
||||
LL | forget(s2);
|
||||
| ^^
|
||||
|
||||
error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:42:5
|
||||
|
|
||||
LL | forget(s4);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `SomeStruct`
|
||||
--> $DIR/drop_forget_copy.rs:42:12
|
||||
|
|
||||
LL | forget(s4);
|
||||
| ^^
|
||||
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:80:13
|
||||
|
|
||||
LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `i32`
|
||||
--> $DIR/drop_forget_copy.rs:80:18
|
||||
|
|
||||
LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:82:14
|
||||
|
|
||||
LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `i32`
|
||||
--> $DIR/drop_forget_copy.rs:82:19
|
||||
|
|
||||
LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
|
||||
--> $DIR/drop_forget_copy.rs:83:14
|
||||
|
|
||||
LL | 4 => drop(2), // Lint, not a fn/method call
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: argument has type `i32`
|
||||
--> $DIR/drop_forget_copy.rs:83:19
|
||||
|
|
||||
LL | 4 => drop(2), // Lint, not a fn/method call
|
||||
| ^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
@ -1,147 +0,0 @@
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:11:5
|
||||
|
|
||||
LL | drop(&SomeStruct);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:11:10
|
||||
|
|
||||
LL | drop(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
= note: `-D clippy::drop-ref` implied by `-D warnings`
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:14:5
|
||||
|
|
||||
LL | drop(&owned1);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:14:10
|
||||
|
|
||||
LL | drop(&owned1);
|
||||
| ^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:15:5
|
||||
|
|
||||
LL | drop(&&owned1);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:15:10
|
||||
|
|
||||
LL | drop(&&owned1);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:16:5
|
||||
|
|
||||
LL | drop(&mut owned1);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&mut SomeStruct`
|
||||
--> $DIR/drop_ref.rs:16:10
|
||||
|
|
||||
LL | drop(&mut owned1);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:20:5
|
||||
|
|
||||
LL | drop(reference1);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:20:10
|
||||
|
|
||||
LL | drop(reference1);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:23:5
|
||||
|
|
||||
LL | drop(reference2);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&mut SomeStruct`
|
||||
--> $DIR/drop_ref.rs:23:10
|
||||
|
|
||||
LL | drop(reference2);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:26:5
|
||||
|
|
||||
LL | drop(reference3);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:26:10
|
||||
|
|
||||
LL | drop(reference3);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:31:5
|
||||
|
|
||||
LL | drop(&val);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&T`
|
||||
--> $DIR/drop_ref.rs:31:10
|
||||
|
|
||||
LL | drop(&val);
|
||||
| ^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:39:5
|
||||
|
|
||||
LL | std::mem::drop(&SomeStruct);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/drop_ref.rs:39:20
|
||||
|
|
||||
LL | std::mem::drop(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:91:13
|
||||
|
|
||||
LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:91:18
|
||||
|
|
||||
LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:93:14
|
||||
|
|
||||
LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:93:19
|
||||
|
|
||||
LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:94:14
|
||||
|
|
||||
LL | 4 => drop(&2), // Lint, not a fn/method call
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:94:19
|
||||
|
|
||||
LL | 4 => drop(&2), // Lint, not a fn/method call
|
||||
| ^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
@ -1,50 +0,0 @@
|
||||
#![warn(clippy::forget_ref)]
|
||||
#![allow(clippy::toplevel_ref_arg)]
|
||||
#![allow(clippy::unnecessary_wraps, clippy::forget_non_drop)]
|
||||
#![allow(clippy::borrow_deref_ref)]
|
||||
|
||||
use std::mem::forget;
|
||||
|
||||
struct SomeStruct;
|
||||
|
||||
fn main() {
|
||||
forget(&SomeStruct);
|
||||
|
||||
let mut owned = SomeStruct;
|
||||
forget(&owned);
|
||||
forget(&&owned);
|
||||
forget(&mut owned);
|
||||
forget(owned); //OK
|
||||
|
||||
let reference1 = &SomeStruct;
|
||||
forget(&*reference1);
|
||||
|
||||
let reference2 = &mut SomeStruct;
|
||||
forget(reference2);
|
||||
|
||||
let ref reference3 = SomeStruct;
|
||||
forget(reference3);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn test_generic_fn_forget<T>(val: T) {
|
||||
forget(&val);
|
||||
forget(val); //OK
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn test_similarly_named_function() {
|
||||
fn forget<T>(_val: T) {}
|
||||
forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
|
||||
std::mem::forget(&SomeStruct);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Error;
|
||||
fn produce_half_owl_error() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn produce_half_owl_ok() -> Result<bool, ()> {
|
||||
Ok(true)
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:11:5
|
||||
|
|
||||
LL | forget(&SomeStruct);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:11:12
|
||||
|
|
||||
LL | forget(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
= note: `-D clippy::forget-ref` implied by `-D warnings`
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:14:5
|
||||
|
|
||||
LL | forget(&owned);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:14:12
|
||||
|
|
||||
LL | forget(&owned);
|
||||
| ^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:15:5
|
||||
|
|
||||
LL | forget(&&owned);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:15:12
|
||||
|
|
||||
LL | forget(&&owned);
|
||||
| ^^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:16:5
|
||||
|
|
||||
LL | forget(&mut owned);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&mut SomeStruct`
|
||||
--> $DIR/forget_ref.rs:16:12
|
||||
|
|
||||
LL | forget(&mut owned);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:20:5
|
||||
|
|
||||
LL | forget(&*reference1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:20:12
|
||||
|
|
||||
LL | forget(&*reference1);
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:23:5
|
||||
|
|
||||
LL | forget(reference2);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&mut SomeStruct`
|
||||
--> $DIR/forget_ref.rs:23:12
|
||||
|
|
||||
LL | forget(reference2);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:26:5
|
||||
|
|
||||
LL | forget(reference3);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:26:12
|
||||
|
|
||||
LL | forget(reference3);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:31:5
|
||||
|
|
||||
LL | forget(&val);
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&T`
|
||||
--> $DIR/forget_ref.rs:31:12
|
||||
|
|
||||
LL | forget(&val);
|
||||
| ^^^^
|
||||
|
||||
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
|
||||
--> $DIR/forget_ref.rs:39:5
|
||||
|
|
||||
LL | std::mem::forget(&SomeStruct);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&SomeStruct`
|
||||
--> $DIR/forget_ref.rs:39:22
|
||||
|
|
||||
LL | std::mem::forget(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
@ -5,7 +5,7 @@ use std::mem as memstuff;
|
||||
use std::mem::forget as forgetSomething;
|
||||
|
||||
#[warn(clippy::mem_forget)]
|
||||
#[allow(clippy::forget_copy)]
|
||||
#[allow(forget_copy)]
|
||||
fn main() {
|
||||
let five: i32 = 5;
|
||||
forgetSomething(five);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(unused)]
|
||||
#![allow(deref_nullptr)]
|
||||
#![allow(clippy::unnecessary_operation)]
|
||||
#![allow(clippy::drop_copy)]
|
||||
#![allow(drop_copy)]
|
||||
#![warn(clippy::multiple_unsafe_ops_per_block)]
|
||||
|
||||
extern crate proc_macros;
|
||||
|
@ -29,7 +29,11 @@
|
||||
#![allow(clippy::invisible_characters)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(drop_bounds)]
|
||||
#![allow(drop_copy)]
|
||||
#![allow(drop_ref)]
|
||||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forget_copy)]
|
||||
#![allow(forget_ref)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
@ -71,9 +75,13 @@
|
||||
#![warn(clippy::invisible_characters)]
|
||||
#![warn(suspicious_double_ref_op)]
|
||||
#![warn(drop_bounds)]
|
||||
#![warn(drop_copy)]
|
||||
#![warn(drop_ref)]
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(forget_copy)]
|
||||
#![warn(forget_ref)]
|
||||
#![warn(array_into_iter)]
|
||||
#![warn(invalid_atomic_ordering)]
|
||||
#![warn(invalid_value)]
|
||||
|
@ -29,7 +29,11 @@
|
||||
#![allow(clippy::invisible_characters)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(drop_bounds)]
|
||||
#![allow(drop_copy)]
|
||||
#![allow(drop_ref)]
|
||||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forget_copy)]
|
||||
#![allow(forget_ref)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
@ -71,9 +75,13 @@
|
||||
#![warn(clippy::zero_width_space)]
|
||||
#![warn(clippy::clone_double_ref)]
|
||||
#![warn(clippy::drop_bounds)]
|
||||
#![warn(clippy::drop_copy)]
|
||||
#![warn(clippy::drop_ref)]
|
||||
#![warn(clippy::for_loop_over_option)]
|
||||
#![warn(clippy::for_loop_over_result)]
|
||||
#![warn(clippy::for_loops_over_fallibles)]
|
||||
#![warn(clippy::forget_copy)]
|
||||
#![warn(clippy::forget_ref)]
|
||||
#![warn(clippy::into_iter_on_array)]
|
||||
#![warn(clippy::invalid_atomic_ordering)]
|
||||
#![warn(clippy::invalid_ref)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
|
||||
--> $DIR/rename.rs:44:9
|
||||
--> $DIR/rename.rs:48:9
|
||||
|
|
||||
LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
||||
@ -7,256 +7,280 @@ LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||
--> $DIR/rename.rs:45:9
|
||||
--> $DIR/rename.rs:49:9
|
||||
|
|
||||
LL | #![warn(clippy::blacklisted_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:46:9
|
||||
--> $DIR/rename.rs:50:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:47:9
|
||||
--> $DIR/rename.rs:51:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
||||
--> $DIR/rename.rs:48:9
|
||||
--> $DIR/rename.rs:52:9
|
||||
|
|
||||
LL | #![warn(clippy::box_vec)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||
|
||||
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
||||
--> $DIR/rename.rs:49:9
|
||||
--> $DIR/rename.rs:53:9
|
||||
|
|
||||
LL | #![warn(clippy::const_static_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||
|
||||
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
||||
--> $DIR/rename.rs:50:9
|
||||
--> $DIR/rename.rs:54:9
|
||||
|
|
||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||
|
||||
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
|
||||
--> $DIR/rename.rs:51:9
|
||||
--> $DIR/rename.rs:55:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:56:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_method)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||
|
||||
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
||||
--> $DIR/rename.rs:53:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_type)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||
|
||||
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
||||
--> $DIR/rename.rs:54:9
|
||||
--> $DIR/rename.rs:58:9
|
||||
|
|
||||
LL | #![warn(clippy::eval_order_dependence)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||
--> $DIR/rename.rs:55:9
|
||||
--> $DIR/rename.rs:59:9
|
||||
|
|
||||
LL | #![warn(clippy::identity_conversion)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||
|
||||
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
||||
--> $DIR/rename.rs:56:9
|
||||
--> $DIR/rename.rs:60:9
|
||||
|
|
||||
LL | #![warn(clippy::if_let_some_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||
--> $DIR/rename.rs:57:9
|
||||
--> $DIR/rename.rs:61:9
|
||||
|
|
||||
LL | #![warn(clippy::logic_bug)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
||||
|
||||
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
||||
--> $DIR/rename.rs:58:9
|
||||
--> $DIR/rename.rs:62:9
|
||||
|
|
||||
LL | #![warn(clippy::new_without_default_derive)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
||||
|
||||
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
||||
--> $DIR/rename.rs:59:9
|
||||
--> $DIR/rename.rs:63:9
|
||||
|
|
||||
LL | #![warn(clippy::option_and_then_some)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||
|
||||
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:60:9
|
||||
--> $DIR/rename.rs:64:9
|
||||
|
|
||||
LL | #![warn(clippy::option_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:61:9
|
||||
--> $DIR/rename.rs:65:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:62:9
|
||||
--> $DIR/rename.rs:66:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:63:9
|
||||
--> $DIR/rename.rs:67:9
|
||||
|
|
||||
LL | #![warn(clippy::option_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:68:9
|
||||
|
|
||||
LL | #![warn(clippy::ref_in_deref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||
|
||||
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:69:9
|
||||
|
|
||||
LL | #![warn(clippy::result_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:66:9
|
||||
--> $DIR/rename.rs:70:9
|
||||
|
|
||||
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:67:9
|
||||
--> $DIR/rename.rs:71:9
|
||||
|
|
||||
LL | #![warn(clippy::result_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
||||
--> $DIR/rename.rs:68:9
|
||||
--> $DIR/rename.rs:72:9
|
||||
|
|
||||
LL | #![warn(clippy::single_char_push_str)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||
|
||||
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
||||
--> $DIR/rename.rs:69:9
|
||||
--> $DIR/rename.rs:73:9
|
||||
|
|
||||
LL | #![warn(clippy::stutter)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||
|
||||
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
||||
--> $DIR/rename.rs:70:9
|
||||
--> $DIR/rename.rs:74:9
|
||||
|
|
||||
LL | #![warn(clippy::to_string_in_display)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||
|
||||
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
||||
--> $DIR/rename.rs:71:9
|
||||
--> $DIR/rename.rs:75:9
|
||||
|
|
||||
LL | #![warn(clippy::zero_width_space)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
|
||||
--> $DIR/rename.rs:72:9
|
||||
--> $DIR/rename.rs:76:9
|
||||
|
|
||||
LL | #![warn(clippy::clone_double_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
|
||||
|
||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||
--> $DIR/rename.rs:73:9
|
||||
--> $DIR/rename.rs:77:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
error: lint `clippy::drop_copy` has been renamed to `drop_copy`
|
||||
--> $DIR/rename.rs:78:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `drop_copy`
|
||||
|
||||
error: lint `clippy::drop_ref` has been renamed to `drop_ref`
|
||||
--> $DIR/rename.rs:79:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_ref)]
|
||||
| ^^^^^^^^^^^^^^^^ help: use the new name: `drop_ref`
|
||||
|
||||
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:74:9
|
||||
--> $DIR/rename.rs:80:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:75:9
|
||||
--> $DIR/rename.rs:81:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:76:9
|
||||
--> $DIR/rename.rs:82:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::forget_copy` has been renamed to `forget_copy`
|
||||
--> $DIR/rename.rs:83:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_copy`
|
||||
|
||||
error: lint `clippy::forget_ref` has been renamed to `forget_ref`
|
||||
--> $DIR/rename.rs:84:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_ref`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:77:9
|
||||
--> $DIR/rename.rs:85:9
|
||||
|
|
||||
LL | #![warn(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||
|
||||
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
||||
--> $DIR/rename.rs:78:9
|
||||
--> $DIR/rename.rs:86:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_atomic_ordering)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||
|
||||
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
||||
--> $DIR/rename.rs:79:9
|
||||
--> $DIR/rename.rs:87:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||
|
||||
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
|
||||
--> $DIR/rename.rs:80:9
|
||||
--> $DIR/rename.rs:88:9
|
||||
|
|
||||
LL | #![warn(clippy::let_underscore_drop)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
|
||||
|
||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||
--> $DIR/rename.rs:81:9
|
||||
--> $DIR/rename.rs:89:9
|
||||
|
|
||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||
|
||||
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
||||
--> $DIR/rename.rs:82:9
|
||||
--> $DIR/rename.rs:90:9
|
||||
|
|
||||
LL | #![warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||
--> $DIR/rename.rs:83:9
|
||||
--> $DIR/rename.rs:91:9
|
||||
|
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
--> $DIR/rename.rs:84:9
|
||||
--> $DIR/rename.rs:92:9
|
||||
|
|
||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
|
||||
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
||||
--> $DIR/rename.rs:85:9
|
||||
--> $DIR/rename.rs:93:9
|
||||
|
|
||||
LL | #![warn(clippy::unknown_clippy_lints)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||
|
||||
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
||||
--> $DIR/rename.rs:86:9
|
||||
--> $DIR/rename.rs:94:9
|
||||
|
|
||||
LL | #![warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
||||
error: aborting due to 43 previous errors
|
||||
error: aborting due to 47 previous errors
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#[warn(clippy::unnecessary_cast)]
|
||||
#[warn(clippy::useless_transmute)]
|
||||
// Shouldn't suggest rustc lint name(`dead_code`)
|
||||
#[warn(clippy::drop_copy)]
|
||||
#[warn(clippy::eq_op)]
|
||||
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
|
||||
#[warn(clippy::unused_self)]
|
||||
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
|
||||
|
@ -34,7 +34,7 @@ error: unknown lint: `clippy::dead_cod`
|
||||
--> $DIR/unknown_clippy_lints.rs:13:8
|
||||
|
|
||||
LL | #[warn(clippy::dead_cod)]
|
||||
| ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::drop_copy`
|
||||
| ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
|
||||
|
||||
error: unknown lint: `clippy::unused_colle`
|
||||
--> $DIR/unknown_clippy_lints.rs:15:8
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![allow(drop_ref)]
|
||||
|
||||
fn main() {
|
||||
let target = &mut 42;
|
||||
let target2 = target as *mut _;
|
||||
|
@ -1,5 +1,7 @@
|
||||
//@error-in-other-file: memory is uninitialized at [0x4..0x10]
|
||||
|
||||
#![allow(drop_copy)]
|
||||
|
||||
use std::alloc::{alloc, dealloc, Layout};
|
||||
use std::slice::from_raw_parts;
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
//@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
|
||||
#![feature(strict_provenance)]
|
||||
|
||||
#![allow(drop_copy)]
|
||||
|
||||
// Test printing allocations that contain single-byte provenance.
|
||||
|
||||
use std::alloc::{alloc, dealloc, Layout};
|
||||
|
@ -1,5 +1,8 @@
|
||||
//@compile-flags: -Zmiri-retag-fields
|
||||
// Checks that the test does not run forever (which relies on a fast path).
|
||||
|
||||
#![allow(drop_copy)]
|
||||
|
||||
fn main() {
|
||||
let array = [(); usize::MAX];
|
||||
drop(array); // Pass the array to a function, retagging its fields
|
||||
|
@ -40,3 +40,38 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'
|
||||
|
||||
it.next_back()
|
||||
}
|
||||
|
||||
// The slice iterator `new` methods used to `assume` that the pointer is non-null,
|
||||
// but passing slices already requires that, to the extent that LLVM actually
|
||||
// removed the `call @llvm.assume` anyway. These tests just demonstrate that the
|
||||
// attribute is there, and confirms adding the assume back doesn't do anything.
|
||||
|
||||
// CHECK-LABEL: @slice_iter_new
|
||||
// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
|
||||
#[no_mangle]
|
||||
pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: insertvalue {{.+}} ptr %[[END]], 1
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: }
|
||||
slice.iter()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @slice_iter_mut_new
|
||||
// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
|
||||
#[no_mangle]
|
||||
pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: insertvalue {{.+}} ptr %[[END]], 1
|
||||
// CHECK-NOT: slice
|
||||
// CHECK: }
|
||||
slice.iter_mut()
|
||||
}
|
||||
|
@ -6,58 +6,120 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/slice_iter.rs:+0:60: +0:60
|
||||
let mut _3: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _4: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _5: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let _6: (); // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _7: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _8: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _9: isize; // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
|
||||
let mut _11: &impl Fn(&T); // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
let mut _12: (&T,); // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
let _5: (); // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _6: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _7: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let mut _8: isize; // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
|
||||
let mut _10: &impl Fn(&T); // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
let mut _11: (&T,); // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
scope 1 {
|
||||
debug iter => _5; // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let _10: &T; // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
debug iter => _4; // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
let _9: &T; // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
scope 2 {
|
||||
debug x => _10; // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
debug x => _9; // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
}
|
||||
}
|
||||
scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:28:20: 28:26
|
||||
debug self => _1; // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
debug slice => _1; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let _12: *const T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _14: bool; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _15: usize; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _16: usize; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _17: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _18: *mut T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _19: *const T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 5 {
|
||||
debug ptr => _12; // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 6 {
|
||||
let _13: *const T; // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 7 {
|
||||
debug end => _13; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug ptr => _18; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
let mut _21: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
let mut _22: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
scope 14 {
|
||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
debug ptr => _22; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
debug self => _22; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
let mut _23: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 17 {
|
||||
scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug ptr => _23; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug self => _23; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 20 {
|
||||
scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug self => _23; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug addr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
scope 10 {
|
||||
}
|
||||
}
|
||||
scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug self => _12; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
debug count => _16; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
scope 12 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug self => _1; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
let mut _20: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:28:14: 28:26
|
||||
debug self => _4; // in scope 4 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:28:14: 28:26
|
||||
debug self => _3; // in scope 22 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
StorageLive(_4); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_4 = std::slice::Iter::<'_, T>::new(_1) -> [return: bb10, unwind: bb8]; // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
// mir::Constant
|
||||
// + span: $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
// + user_ty: UserType(0)
|
||||
// + literal: Const { ty: fn(&[T]) -> std::slice::Iter<'_, T> {std::slice::Iter::<'_, T>::new}, val: Value(<ZST>) }
|
||||
StorageLive(_12); // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageLive(_20); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
_20 = &raw const (*_1); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
_12 = move _20 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageDead(_20); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageLive(_13); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_14); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_14 = const _; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
switchInt(move _14) -> [0: bb11, otherwise: bb10]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_7); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_8 = &mut _5; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_7 = <std::slice::Iter<'_, T> as Iterator>::next(_8) -> [return: bb2, unwind: bb8]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
StorageLive(_6); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_7 = &mut _4; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_6 = <std::slice::Iter<'_, T> as Iterator>::next(_7) -> [return: bb2, unwind: bb8]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
// mir::Constant
|
||||
// + span: $DIR/slice_iter.rs:28:14: 28:26
|
||||
// + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as Iterator>::next}, val: Value(<ZST>) }
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_9 = discriminant(_7); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
switchInt(move _9) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_8 = discriminant(_6); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_10 = ((_7 as Some).0: &T); // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
StorageLive(_11); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
_11 = &_2; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
StorageLive(_12); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
_12 = (_10,); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
_6 = <impl Fn(&T) as Fn<(&T,)>>::call(move _11, move _12) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
_9 = ((_6 as Some).0: &T); // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
StorageLive(_10); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
_10 = &_2; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
|
||||
StorageLive(_11); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
_11 = (_9,); // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
_5 = <impl Fn(&T) as Fn<(&T,)>>::call(move _10, move _11) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
|
||||
// mir::Constant
|
||||
// + span: $DIR/slice_iter.rs:29:9: 29:10
|
||||
// + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
|
||||
@ -68,16 +130,15 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_7); // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
StorageDead(_5); // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
StorageDead(_3); // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
StorageDead(_6); // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
StorageDead(_4); // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
drop(_2) -> bb7; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_12); // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
|
||||
StorageDead(_11); // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
|
||||
StorageDead(_7); // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
StorageDead(_10); // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
|
||||
StorageDead(_6); // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
|
||||
goto -> bb1; // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
|
||||
}
|
||||
|
||||
@ -94,10 +155,49 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_3 = move _4; // scope 4 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
StorageDead(_4); // scope 0 at $DIR/slice_iter.rs:+1:25: +1:26
|
||||
StorageLive(_5); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_5 = move _3; // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
StorageLive(_15); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_15 = Len((*_1)); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_13 = _15 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
StorageDead(_15); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
goto -> bb12; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb11: {
|
||||
StorageLive(_16); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_16 = Len((*_1)); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_13 = Offset(_12, _16); // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
StorageDead(_16); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
goto -> bb12; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb12: {
|
||||
StorageDead(_14); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_17); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_18); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_18 = _12 as *mut T (PtrToPtr); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_21); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_22); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_23); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_21 = _18 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
_17 = NonNull::<T> { pointer: _21 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
StorageDead(_23); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_22); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_21); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_18); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_19); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_19 = _13; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_3 = std::slice::Iter::<'_, T> { ptr: move _17, end: move _19, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
// mir::Constant
|
||||
// + span: no-location
|
||||
// + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
|
||||
// adt
|
||||
// + user_ty: UserType(1)
|
||||
StorageDead(_19); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_17); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_13); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_12); // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageLive(_4); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_4 = move _3; // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
goto -> bb1; // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
|
||||
}
|
||||
}
|
||||
|
@ -19,39 +19,104 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||
scope 2 {
|
||||
debug x => _10; // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
|
||||
}
|
||||
scope 7 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { // at $DIR/slice_iter.rs:35:14: 35:32
|
||||
debug self => _8; // in scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
let mut _13: &mut std::slice::Iter<'_, T>; // in scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { // at $DIR/slice_iter.rs:35:14: 35:32
|
||||
debug self => _8; // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
let mut _25: &mut std::slice::Iter<'_, T>; // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
}
|
||||
}
|
||||
scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:35:20: 35:26
|
||||
debug self => _1; // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
}
|
||||
scope 4 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { // at $DIR/slice_iter.rs:35:27: 35:32
|
||||
debug self => _4; // in scope 4 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
scope 5 (inlined Rev::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
debug iter => _4; // in scope 5 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
debug slice => _1; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let _13: *const T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _15: bool; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _16: usize; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _17: usize; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _18: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _19: *mut T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
let mut _20: *const T; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 5 {
|
||||
debug ptr => _13; // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 6 {
|
||||
let _14: *const T; // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 7 {
|
||||
debug end => _14; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug ptr => _19; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
let mut _22: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
let mut _23: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
scope 14 {
|
||||
scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
debug ptr => _23; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||
scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
debug self => _23; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
let mut _24: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 17 {
|
||||
scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug ptr => _24; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug self => _24; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
scope 20 {
|
||||
scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
debug self => _24; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug addr => _16; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
scope 10 {
|
||||
}
|
||||
}
|
||||
scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug self => _13; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
debug count => _17; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
scope 12 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
debug self => _1; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
let mut _21: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 6 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:35:14: 35:32
|
||||
debug self => _3; // in scope 6 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { // at $DIR/slice_iter.rs:35:27: 35:32
|
||||
debug self => _4; // in scope 22 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
debug iter => _4; // in scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
}
|
||||
}
|
||||
scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:35:14: 35:32
|
||||
debug self => _3; // in scope 24 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_4); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
|
||||
_4 = std::slice::Iter::<'_, T>::new(_1) -> [return: bb9, unwind: bb7]; // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
// mir::Constant
|
||||
// + span: $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
// + user_ty: UserType(0)
|
||||
// + literal: Const { ty: fn(&[T]) -> std::slice::Iter<'_, T> {std::slice::Iter::<'_, T>::new}, val: Value(<ZST>) }
|
||||
StorageLive(_13); // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageLive(_21); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
_21 = &raw const (*_1); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
_13 = move _21 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageDead(_21); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
StorageLive(_14); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_15); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_15 = const _; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
switchInt(move _15) -> [0: bb10, otherwise: bb9]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageLive(_7); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
_8 = &mut _5; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
StorageLive(_13); // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
_13 = &mut ((*_8).0: std::slice::Iter<'_, T>); // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
_7 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb10, unwind: bb7]; // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
StorageLive(_25); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
_25 = &mut ((*_8).0: std::slice::Iter<'_, T>); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
_7 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _25) -> [return: bb12, unwind: bb7]; // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
// mir::Constant
|
||||
// + span: $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
// + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back}, val: Value(<ZST>) }
|
||||
@ -99,15 +164,56 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
|
||||
}
|
||||
|
||||
bb9: {
|
||||
_3 = Rev::<std::slice::Iter<'_, T>> { iter: move _4 }; // scope 5 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
StorageLive(_16); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_16 = Len((*_1)); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_14 = _16 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
StorageDead(_16); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
goto -> bb11; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageLive(_17); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_17 = Len((*_1)); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_14 = Offset(_13, _17); // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
StorageDead(_17); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
goto -> bb11; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
}
|
||||
|
||||
bb11: {
|
||||
StorageDead(_15); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_18); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_19); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_19 = _13 as *mut T (PtrToPtr); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_22); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_23); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_24); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_22 = _19 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
_18 = NonNull::<T> { pointer: _22 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
|
||||
StorageDead(_24); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_23); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_22); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_19); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageLive(_20); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_20 = _14; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
_4 = std::slice::Iter::<'_, T> { ptr: move _18, end: move _20, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
// mir::Constant
|
||||
// + span: no-location
|
||||
// + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
|
||||
// adt
|
||||
// + user_ty: UserType(1)
|
||||
StorageDead(_20); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_18); // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_14); // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
|
||||
StorageDead(_13); // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
|
||||
_3 = Rev::<std::slice::Iter<'_, T>> { iter: move _4 }; // scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
StorageDead(_4); // scope 0 at $DIR/slice_iter.rs:+1:31: +1:32
|
||||
StorageLive(_5); // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
_5 = move _3; // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
goto -> bb1; // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageDead(_13); // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
bb12: {
|
||||
StorageDead(_25); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
|
||||
_9 = discriminant(_7); // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
switchInt(move _9) -> [0: bb4, 1: bb2, otherwise: bb3]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ CHECK-SAME: section "llvm.metadata"
|
||||
CHECK: [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
|
||||
CHECK-NEXT: start:
|
||||
CHECK-NOT: [[DEFINE_INTERNAL]]
|
||||
CHECK: %pgocount = load i64, {{i64\*|ptr}}
|
||||
CHECK: atomicrmw add ptr
|
||||
CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
|
||||
|
||||
CHECK: declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#![feature(inherent_associated_types)]
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(drop_copy)]
|
||||
|
||||
use std::convert::identity;
|
||||
|
||||
|
@ -43,7 +43,7 @@ note: expected this to be `Bar`
|
||||
|
|
||||
LL | type A = usize;
|
||||
| ^^^^^
|
||||
= note: required for the cast from `isize` to the object type `dyn Foo<A = Bar>`
|
||||
= note: required for the cast from `&isize` to `&dyn Foo<A = Bar>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -4,7 +4,7 @@ error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but
|
||||
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
= note: required for the cast from `std::vec::IntoIter<u32>` to the object type `dyn Iterator<Item = u32, Item = i32>`
|
||||
= note: required for the cast from `&std::vec::IntoIter<u32>` to `&dyn Iterator<Item = u32, Item = i32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -25,7 +25,7 @@ LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
|
||||
| --------- ^^^^^^^^^ ^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: required for the cast from `&mut T` to the object type `dyn MyDisplay`
|
||||
= note: required for the cast from `&&mut T` to `&dyn MyDisplay`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -18,7 +18,7 @@ LL | writer.my_write(valref)
|
||||
| ^^^^^^ the trait `MyDisplay` is not implemented for `T`
|
||||
|
|
||||
= help: the trait `MyDisplay` is implemented for `&'a mut T`
|
||||
= note: required for the cast from `T` to the object type `dyn MyDisplay`
|
||||
= note: required for the cast from `&mut T` to `&dyn MyDisplay`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -35,7 +35,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
|
||||
LL | let _: &dyn Future<Output = ()> = █
|
||||
| ^^^^^^ expected `()`, found `u8`
|
||||
|
|
||||
= note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
|
||||
= note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to `&dyn Future<Output = ()>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:12:43
|
||||
@ -51,7 +51,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
|
||||
LL | let _: &dyn Future<Output = ()> = █
|
||||
| ^^^^^^ expected `()`, found `u8`
|
||||
|
|
||||
= note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
|
||||
= note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to `&dyn Future<Output = ()>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
||||
|
@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
|
||||
|
|
||||
LL | let x = x;
|
||||
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
||||
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
|
||||
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
|
||||
|
@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
|
||||
|
|
||||
LL | let x = x;
|
||||
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
||||
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
|
||||
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
|
||||
|
@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
|
||||
|
|
||||
LL | let x = x;
|
||||
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
||||
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
|
||||
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
|
||||
|
@ -4,7 +4,7 @@
|
||||
async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
|
||||
where 'b: 'a
|
||||
{
|
||||
drop((a, c));
|
||||
let _ = (a, c);
|
||||
(b, b)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Check that closure captures for slice patterns are inferred correctly
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![allow(drop_ref)]
|
||||
|
||||
// run-pass
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// run-pass
|
||||
#![allow(unused_mut)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(drop_copy)]
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
struct A { a: isize, b: Box<isize> }
|
||||
|
@ -1,6 +1,8 @@
|
||||
// run-pass
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![allow(drop_copy)]
|
||||
|
||||
struct A { a: isize, b: Box<isize> }
|
||||
|
||||
fn field_copy_after_field_borrow() {
|
||||
|
@ -9,7 +9,7 @@ LL | num += 1;
|
||||
LL | Box::new(closure)
|
||||
| ----------------- the requirement to implement `Fn` derives from here
|
||||
|
|
||||
= note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()`
|
||||
= note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]>` to `Box<(dyn Fn() + 'static)>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,7 +9,7 @@ LL | vec
|
||||
LL | Box::new(closure)
|
||||
| ----------------- the requirement to implement `Fn` derives from here
|
||||
|
|
||||
= note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec<u8>`
|
||||
= note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]>` to `Box<(dyn Fn() -> Vec<u8> + 'static)>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// run-pass
|
||||
|
||||
#![warn(rust_2021_incompatible_closure_captures)]
|
||||
#![allow(drop_ref, drop_copy)]
|
||||
|
||||
fn main() {
|
||||
if let a = "" {
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: irrefutable `if let` pattern
|
||||
--> $DIR/issue-78720.rs:6:8
|
||||
--> $DIR/issue-78720.rs:7:8
|
||||
|
|
||||
LL | if let a = "" {
|
||||
| ^^^^^^^^^^
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#![allow(unused)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(drop_ref)]
|
||||
|
||||
struct Int(i32);
|
||||
struct B<'a>(&'a i32);
|
||||
|
@ -1,6 +1,8 @@
|
||||
// edition:2021
|
||||
// check-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(drop_ref)]
|
||||
|
||||
fn main() {
|
||||
let mut x = 1;
|
||||
|
@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
|
||||
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
||||
|
|
||||
= note: required for the cast from `()` to the object type `dyn std::error::Error`
|
||||
= note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>`
|
||||
|
||||
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
|
||||
--> $DIR/coerce-issue-49593-box-never-windows.rs:23:49
|
||||
@ -12,7 +12,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
|
||||
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
|
||||
|
|
||||
= note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
|
||||
= note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user