Auto merge of #130807 - tgross35:rollup-p304vzf, r=tgross35
Rollup of 7 pull requests Successful merges: - #130234 (improve compile errors for invalid ptr-to-ptr casts with trait objects) - #130752 (Improve assembly test for CMSE ABIs) - #130764 (Separate collection of crate-local inherent impls from error tracking) - #130788 (Pin memchr to 2.5.0 in the library rather than rustc_ast) - #130789 (add InProgress ErrorKind gated behind io_error_inprogress feature) - #130793 (Mention `COMPILETEST_VERBOSE_CRASHES` on crash test failure) - #130798 (rustdoc: inherit parent's stability where applicable) Failed merges: - #130735 (Simple validation for unsize coercion in MIR validation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1b5aa96d60
164 changed files with 875 additions and 563 deletions
|
@ -2177,9 +2177,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
|
|
|
@ -4,10 +4,9 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# FIXME: bumping memchr to 2.7.1 causes linker errors in MSVC thin-lto
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
memchr = "=2.5.0"
|
||||
memchr = "2.7.4"
|
||||
rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
|
|
|
@ -153,7 +153,7 @@ pub enum StabilityLevel {
|
|||
}
|
||||
|
||||
/// Rust release in which a feature is stabilized.
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum StableSince {
|
||||
Version(RustcVersion),
|
||||
|
|
|
@ -333,7 +333,11 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let ConstraintCategory::Cast { unsize_to: Some(unsize_ty) } = category {
|
||||
if let ConstraintCategory::Cast {
|
||||
is_implicit_coercion: true,
|
||||
unsize_to: Some(unsize_ty),
|
||||
} = category
|
||||
{
|
||||
self.add_object_lifetime_default_note(tcx, err, unsize_ty);
|
||||
}
|
||||
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
|
||||
|
@ -740,7 +744,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
// If we see an unsized cast, then if it is our data we should check
|
||||
// whether it is being cast to a trait object.
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
||||
operand,
|
||||
ty,
|
||||
) => {
|
||||
|
|
|
@ -47,7 +47,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
|
|||
ConstraintCategory::Yield => "yielding this value ",
|
||||
ConstraintCategory::UseAsConst => "using this value as a constant ",
|
||||
ConstraintCategory::UseAsStatic => "using this value as a static ",
|
||||
ConstraintCategory::Cast { .. } => "cast ",
|
||||
ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ",
|
||||
ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ",
|
||||
ConstraintCategory::CallArgument(_) => "argument ",
|
||||
ConstraintCategory::TypeAnnotation => "type annotation ",
|
||||
ConstraintCategory::ClosureBounds => "closure body ",
|
||||
|
|
|
@ -1975,8 +1975,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
Rvalue::Cast(cast_kind, op, ty) => {
|
||||
self.check_operand(op, location);
|
||||
|
||||
match cast_kind {
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
|
||||
match *cast_kind {
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
let src_sig = op.ty(body, tcx).fn_sig(tcx);
|
||||
|
||||
// HACK: This shouldn't be necessary... We can remove this when we actually
|
||||
|
@ -2007,7 +2008,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.prove_predicate(
|
||||
ty::ClauseKind::WellFormed(src_ty.into()),
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
|
||||
let src_ty = self.normalize(src_ty, location);
|
||||
|
@ -2015,7 +2016,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
src_ty,
|
||||
*ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2036,7 +2037,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.prove_predicate(
|
||||
ty::ClauseKind::WellFormed(src_ty.into()),
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
|
||||
// The type that we see in the fcx is like
|
||||
|
@ -2049,7 +2050,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
src_ty,
|
||||
*ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2062,19 +2063,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(safety)) => {
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::ClosureFnPointer(safety),
|
||||
coercion_source,
|
||||
) => {
|
||||
let sig = match op.ty(body, tcx).kind() {
|
||||
ty::Closure(_, args) => args.as_closure().sig(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let ty_fn_ptr_from =
|
||||
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety));
|
||||
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
if let Err(terr) = self.sub_types(
|
||||
ty_fn_ptr_from,
|
||||
*ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2087,7 +2092,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::UnsafeFnPointer,
|
||||
coercion_source,
|
||||
) => {
|
||||
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
|
||||
|
||||
// The type that we see in the fcx is like
|
||||
|
@ -2099,11 +2107,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
if let Err(terr) = self.sub_types(
|
||||
ty_fn_ptr_from,
|
||||
*ty,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2116,7 +2125,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
|
||||
let &ty = ty;
|
||||
let trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
|
@ -2124,22 +2133,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
[op.ty(body, tcx), ty],
|
||||
);
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
let unsize_to = tcx.fold_regions(ty, |r, _| {
|
||||
if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
|
||||
});
|
||||
self.prove_trait_ref(
|
||||
trait_ref,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast {
|
||||
unsize_to: Some(tcx.fold_regions(ty, |r, _| {
|
||||
if let ty::ReVar(_) = r.kind() {
|
||||
tcx.lifetimes.re_erased
|
||||
} else {
|
||||
r
|
||||
}
|
||||
})),
|
||||
is_implicit_coercion,
|
||||
unsize_to: Some(unsize_to),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
CastKind::DynStar => {
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
|
||||
// get the constraints from the target type (`dyn* Clone`)
|
||||
//
|
||||
// apply them to prove that the source type `Foo` implements `Clone` etc
|
||||
|
@ -2150,12 +2158,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
let self_ty = op.ty(body, tcx);
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
self.prove_predicates(
|
||||
existential_predicates
|
||||
.iter()
|
||||
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
|
||||
let outlives_predicate = tcx.mk_predicate(Binder::dummy(
|
||||
|
@ -2166,11 +2175,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.prove_predicate(
|
||||
outlives_predicate,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
);
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::MutToConstPointer,
|
||||
coercion_source,
|
||||
) => {
|
||||
let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
|
||||
else {
|
||||
span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
|
||||
|
@ -2180,11 +2192,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
|
||||
return;
|
||||
};
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
if let Err(terr) = self.sub_types(
|
||||
*ty_from,
|
||||
*ty_to,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2197,7 +2210,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
|
||||
let ty_from = op.ty(body, tcx);
|
||||
|
||||
let opt_ty_elem_mut = match ty_from.kind() {
|
||||
|
@ -2242,11 +2255,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
if let Err(terr) = self.sub_types(
|
||||
*ty_elem,
|
||||
*ty_to,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
@ -2427,7 +2441,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
src_obj,
|
||||
dst_obj,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
ConstraintCategory::Cast {
|
||||
is_implicit_coercion: false,
|
||||
unsize_to: None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ fn codegen_stmt<'tcx>(
|
|||
lval.write_cvalue(fx, res);
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
|
||||
ref operand,
|
||||
to_ty,
|
||||
) => {
|
||||
|
@ -677,7 +677,7 @@ fn codegen_stmt<'tcx>(
|
|||
}
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer),
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _),
|
||||
ref operand,
|
||||
to_ty,
|
||||
) => {
|
||||
|
@ -688,6 +688,7 @@ fn codegen_stmt<'tcx>(
|
|||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
|
||||
_,
|
||||
),
|
||||
..,
|
||||
) => {
|
||||
|
@ -741,7 +742,7 @@ fn codegen_stmt<'tcx>(
|
|||
}
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
|
||||
ref operand,
|
||||
_to_ty,
|
||||
) => {
|
||||
|
@ -763,14 +764,18 @@ fn codegen_stmt<'tcx>(
|
|||
}
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
||||
ref operand,
|
||||
_to_ty,
|
||||
) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
crate::unsize::coerce_unsized_into(fx, operand, lval);
|
||||
}
|
||||
Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
crate::unsize::coerce_dyn_star(fx, operand, lval);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
||||
ref source,
|
||||
_,
|
||||
) => {
|
||||
|
@ -465,7 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let lladdr = bx.ptrtoint(llptr, llcast_ty);
|
||||
OperandValue::Immediate(lladdr)
|
||||
}
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
|
||||
match *operand.layout.ty.kind() {
|
||||
ty::FnDef(def_id, args) => {
|
||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||
|
@ -481,7 +481,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
|
||||
}
|
||||
}
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => {
|
||||
match *operand.layout.ty.kind() {
|
||||
ty::Closure(def_id, args) => {
|
||||
let instance = Instance::resolve_closure(
|
||||
|
@ -496,11 +496,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
_ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
|
||||
}
|
||||
}
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
|
||||
// This is a no-op at the LLVM level.
|
||||
operand.val
|
||||
}
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => {
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
|
||||
assert!(bx.cx().is_backend_scalar_pair(cast));
|
||||
let (lldata, llextra) = operand.val.pointer_parts();
|
||||
let (lldata, llextra) =
|
||||
|
@ -508,7 +508,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
OperandValue::Pair(lldata, llextra)
|
||||
}
|
||||
mir::CastKind::PointerCoercion(
|
||||
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
|
||||
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _
|
||||
) => {
|
||||
bug!("{kind:?} is for borrowck, and should never appear in codegen");
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bug!("unexpected non-pair operand");
|
||||
}
|
||||
}
|
||||
mir::CastKind::DynStar => {
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
let (lldata, llextra) = operand.val.pointer_parts();
|
||||
let (lldata, llextra) =
|
||||
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
|
||||
|
|
|
@ -440,6 +440,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
| PointerCoercion::UnsafeFnPointer
|
||||
| PointerCoercion::ClosureFnPointer(_)
|
||||
| PointerCoercion::ReifyFnPointer,
|
||||
_,
|
||||
),
|
||||
_,
|
||||
_,
|
||||
|
@ -447,8 +448,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// These are all okay; they only change the type, not the data.
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), _, _) => {
|
||||
// Unsizing is implemented for CTFE.
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize | PointerCoercion::DynStar, _),
|
||||
_,
|
||||
_,
|
||||
) => {
|
||||
// Unsizing and `dyn*` coercions are implemented for CTFE.
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
|
||||
|
@ -458,10 +463,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// Since no pointer can ever get exposed (rejected above), this is easy to support.
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||
// `dyn*` coercion is implemented for CTFE.
|
||||
}
|
||||
|
||||
Rvalue::Cast(_, _, _) => {}
|
||||
|
||||
Rvalue::NullaryOp(
|
||||
|
|
|
@ -32,7 +32,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
if cast_ty == dest.layout.ty { dest.layout } else { self.layout_of(cast_ty)? };
|
||||
// FIXME: In which cases should we trigger UB when the source is uninit?
|
||||
match cast_kind {
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
|
||||
self.unsize_into(src, cast_layout, dest)?;
|
||||
}
|
||||
|
||||
|
@ -68,11 +68,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
|
||||
_,
|
||||
) => {
|
||||
bug!("{cast_kind:?} casts are for borrowck only, not runtime MIR");
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
|
||||
// All reifications must be monomorphic, bail out otherwise.
|
||||
ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
|
||||
|
||||
|
@ -94,7 +95,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
|
||||
let src = self.read_immediate(src)?;
|
||||
match cast_ty.kind() {
|
||||
ty::FnPtr(..) => {
|
||||
|
@ -105,7 +106,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => {
|
||||
// All reifications must be monomorphic, bail out otherwise.
|
||||
ensure_monomorphic_enough(*self.tcx, src.layout.ty)?;
|
||||
|
||||
|
@ -125,7 +126,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
CastKind::DynStar => {
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src.layout.ty, data)?;
|
||||
|
|
|
@ -22,36 +22,38 @@ use crate::errors;
|
|||
pub(crate) fn crate_inherent_impls(
|
||||
tcx: TyCtxt<'_>,
|
||||
(): (),
|
||||
) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> {
|
||||
) -> (&'_ CrateInherentImpls, Result<(), ErrorGuaranteed>) {
|
||||
let mut collect = InherentCollect { tcx, impls_map: Default::default() };
|
||||
|
||||
let mut res = Ok(());
|
||||
for id in tcx.hir().items() {
|
||||
res = res.and(collect.check_item(id));
|
||||
}
|
||||
res?;
|
||||
Ok(tcx.arena.alloc(collect.impls_map))
|
||||
|
||||
(tcx.arena.alloc(collect.impls_map), res)
|
||||
}
|
||||
|
||||
pub(crate) fn crate_incoherent_impls(
|
||||
pub(crate) fn crate_inherent_impls_validity_check(
|
||||
tcx: TyCtxt<'_>,
|
||||
simp: SimplifiedType,
|
||||
) -> Result<&[DefId], ErrorGuaranteed> {
|
||||
let crate_map = tcx.crate_inherent_impls(())?;
|
||||
Ok(tcx.arena.alloc_from_iter(
|
||||
(): (),
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
tcx.crate_inherent_impls(()).1
|
||||
}
|
||||
|
||||
pub(crate) fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
|
||||
let (crate_map, _) = tcx.crate_inherent_impls(());
|
||||
tcx.arena.alloc_from_iter(
|
||||
crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
/// On-demand query: yields a vector of the inherent impls for a specific type.
|
||||
pub(crate) fn inherent_impls(
|
||||
tcx: TyCtxt<'_>,
|
||||
ty_def_id: LocalDefId,
|
||||
) -> Result<&[DefId], ErrorGuaranteed> {
|
||||
let crate_map = tcx.crate_inherent_impls(())?;
|
||||
Ok(match crate_map.inherent_impls.get(&ty_def_id) {
|
||||
pub(crate) fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
|
||||
let (crate_map, _) = tcx.crate_inherent_impls(());
|
||||
match crate_map.inherent_impls.get(&ty_def_id) {
|
||||
Some(v) => &v[..],
|
||||
None => &[],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct InherentCollect<'tcx> {
|
||||
|
|
|
@ -177,8 +177,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let impls = self.tcx.inherent_impls(id.owner_id)?;
|
||||
|
||||
let impls = self.tcx.inherent_impls(id.owner_id);
|
||||
let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
|
||||
|
||||
let impls_items = impls
|
||||
|
|
|
@ -124,7 +124,10 @@ fn enforce_empty_impls_for_marker_traits(
|
|||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
use self::builtin::coerce_unsized_info;
|
||||
use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
|
||||
use self::inherent_impls::{
|
||||
crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check,
|
||||
inherent_impls,
|
||||
};
|
||||
use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
|
||||
use self::orphan::orphan_check_impl;
|
||||
|
||||
|
@ -133,6 +136,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
crate_inherent_impls,
|
||||
crate_incoherent_impls,
|
||||
inherent_impls,
|
||||
crate_inherent_impls_validity_check,
|
||||
crate_inherent_impls_overlap_check,
|
||||
coerce_unsized_info,
|
||||
orphan_check_impl,
|
||||
|
|
|
@ -1028,7 +1028,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
..
|
||||
}) = node
|
||||
&& let Some(ty_def_id) = qself_ty.ty_def_id()
|
||||
&& let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
|
||||
&& let [inherent_impl] = tcx.inherent_impls(ty_def_id)
|
||||
&& let name = format!("{ident2}_{ident3}")
|
||||
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
|
||||
.associated_items(inherent_impl)
|
||||
|
|
|
@ -1272,7 +1272,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
|
||||
let candidates: Vec<_> = tcx
|
||||
.inherent_impls(adt_did)?
|
||||
.inherent_impls(adt_did)
|
||||
.iter()
|
||||
.filter_map(|&impl_| {
|
||||
let (item, scope) =
|
||||
|
|
|
@ -170,7 +170,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
let _ = tcx.ensure().coherent_trait(trait_def_id);
|
||||
}
|
||||
// these queries are executed for side-effects (error reporting):
|
||||
let _ = tcx.ensure().crate_inherent_impls(());
|
||||
let _ = tcx.ensure().crate_inherent_impls_validity_check(());
|
||||
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
|
||||
});
|
||||
|
||||
|
|
|
@ -32,13 +32,14 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
||||
use rustc_hir::{self as hir, ExprKind};
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::Mutability;
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::cast::{CastKind, CastTy};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::symbol::sym;
|
||||
|
@ -152,12 +153,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum CastError {
|
||||
enum CastError<'tcx> {
|
||||
ErrorGuaranteed(ErrorGuaranteed),
|
||||
|
||||
CastToBool,
|
||||
CastToChar,
|
||||
DifferingKinds,
|
||||
DifferingKinds {
|
||||
src_kind: PointerKind<'tcx>,
|
||||
dst_kind: PointerKind<'tcx>,
|
||||
},
|
||||
/// Cast of thin to fat raw ptr (e.g., `*const () as *const [u8]`).
|
||||
SizedUnsizedCast,
|
||||
IllegalCast,
|
||||
|
@ -177,7 +181,7 @@ pub enum CastError {
|
|||
ForeignNonExhaustiveAdt,
|
||||
}
|
||||
|
||||
impl From<ErrorGuaranteed> for CastError {
|
||||
impl From<ErrorGuaranteed> for CastError<'_> {
|
||||
fn from(err: ErrorGuaranteed) -> Self {
|
||||
CastError::ErrorGuaranteed(err)
|
||||
}
|
||||
|
@ -251,7 +255,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
|
||||
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError<'tcx>) {
|
||||
match e {
|
||||
CastError::ErrorGuaranteed(_) => {
|
||||
// an error has already been reported
|
||||
|
@ -303,10 +307,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
CastError::IllegalCast => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx).emit();
|
||||
}
|
||||
CastError::DifferingKinds => {
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx)
|
||||
.with_note("vtable kinds may not match")
|
||||
.emit();
|
||||
CastError::DifferingKinds { src_kind, dst_kind } => {
|
||||
let mut err =
|
||||
make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx);
|
||||
|
||||
match (src_kind, dst_kind) {
|
||||
(PointerKind::VTable(_), PointerKind::VTable(_)) => {
|
||||
err.note("the trait objects may have different vtables");
|
||||
}
|
||||
(
|
||||
PointerKind::OfParam(_) | PointerKind::OfAlias(_),
|
||||
PointerKind::OfParam(_)
|
||||
| PointerKind::OfAlias(_)
|
||||
| PointerKind::VTable(_)
|
||||
| PointerKind::Length,
|
||||
)
|
||||
| (
|
||||
PointerKind::VTable(_) | PointerKind::Length,
|
||||
PointerKind::OfParam(_) | PointerKind::OfAlias(_),
|
||||
) => {
|
||||
err.note("the pointers may have different metadata");
|
||||
}
|
||||
(PointerKind::VTable(_), PointerKind::Length)
|
||||
| (PointerKind::Length, PointerKind::VTable(_)) => {
|
||||
err.note("the pointers have different metadata");
|
||||
}
|
||||
(
|
||||
PointerKind::Thin,
|
||||
PointerKind::Thin
|
||||
| PointerKind::VTable(_)
|
||||
| PointerKind::Length
|
||||
| PointerKind::OfParam(_)
|
||||
| PointerKind::OfAlias(_),
|
||||
)
|
||||
| (
|
||||
PointerKind::VTable(_)
|
||||
| PointerKind::Length
|
||||
| PointerKind::OfParam(_)
|
||||
| PointerKind::OfAlias(_),
|
||||
PointerKind::Thin,
|
||||
)
|
||||
| (PointerKind::Length, PointerKind::Length) => {
|
||||
span_bug!(self.span, "unexpected cast error: {e:?}")
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
CastError::CastToBool => {
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
|
@ -670,10 +716,20 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
/// Checks a cast, and report an error if one exists. In some cases, this
|
||||
/// can return Ok and create type errors in the fcx rather than returning
|
||||
/// directly. coercion-cast is handled in check instead of here.
|
||||
fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
|
||||
fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError<'tcx>> {
|
||||
use rustc_middle::ty::cast::CastTy::*;
|
||||
use rustc_middle::ty::cast::IntTy::*;
|
||||
|
||||
if self.cast_ty.is_dyn_star() {
|
||||
if fcx.tcx.features().dyn_star {
|
||||
span_bug!(self.span, "should be handled by `coerce`");
|
||||
} else {
|
||||
// Report "casting is invalid" rather than "non-primitive cast"
|
||||
// if the feature is not enabled.
|
||||
return Err(CastError::IllegalCast);
|
||||
}
|
||||
}
|
||||
|
||||
let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))
|
||||
{
|
||||
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
|
||||
|
@ -780,16 +836,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
||||
|
||||
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
||||
|
||||
(_, DynStar) => {
|
||||
if fcx.tcx.features().dyn_star {
|
||||
bug!("should be handled by `coerce`")
|
||||
} else {
|
||||
Err(CastError::IllegalCast)
|
||||
}
|
||||
}
|
||||
|
||||
(DynStar, _) => Err(CastError::IllegalCast),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -798,27 +844,34 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_src: ty::TypeAndMut<'tcx>,
|
||||
m_dst: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
debug!("check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}");
|
||||
// ptr-ptr cast. vtables must match.
|
||||
// ptr-ptr cast. metadata must match.
|
||||
|
||||
let src_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_src.ty, self.span)?);
|
||||
let dst_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_dst.ty, self.span)?);
|
||||
|
||||
match (src_kind, dst_kind) {
|
||||
// We can't cast if target pointer kind is unknown
|
||||
(_, None) => Err(CastError::UnknownCastPtrKind),
|
||||
let Some(dst_kind) = dst_kind else {
|
||||
return Err(CastError::UnknownCastPtrKind);
|
||||
};
|
||||
|
||||
// Cast to thin pointer is OK
|
||||
(_, Some(PointerKind::Thin)) => Ok(CastKind::PtrPtrCast),
|
||||
if dst_kind == PointerKind::Thin {
|
||||
return Ok(CastKind::PtrPtrCast);
|
||||
}
|
||||
|
||||
// We can't cast to fat pointer if source pointer kind is unknown
|
||||
(None, _) => Err(CastError::UnknownExprPtrKind),
|
||||
let Some(src_kind) = src_kind else {
|
||||
return Err(CastError::UnknownCastPtrKind);
|
||||
};
|
||||
|
||||
match (src_kind, dst_kind) {
|
||||
// thin -> fat? report invalid cast (don't complain about vtable kinds)
|
||||
(Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast),
|
||||
(PointerKind::Thin, _) => Err(CastError::SizedUnsizedCast),
|
||||
|
||||
// trait object -> trait object? need to do additional checks
|
||||
(Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
|
||||
(PointerKind::VTable(src_tty), PointerKind::VTable(dst_tty)) => {
|
||||
match (src_tty.principal(), dst_tty.principal()) {
|
||||
// A<dyn Src<...> + SrcAuto> -> B<dyn Dst<...> + DstAuto>. need to make sure
|
||||
// - `Src` and `Dst` traits are the same
|
||||
|
@ -834,7 +887,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
|
||||
// and is unaffected by this check.
|
||||
if src_principal.def_id() != dst_principal.def_id() {
|
||||
return Err(CastError::DifferingKinds);
|
||||
return Err(CastError::DifferingKinds { src_kind, dst_kind });
|
||||
}
|
||||
|
||||
// We need to reconstruct trait object types.
|
||||
|
@ -860,7 +913,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
));
|
||||
|
||||
// `dyn Src = dyn Dst`, this checks for matching traits/generics
|
||||
fcx.demand_eqtype(self.span, src_obj, dst_obj);
|
||||
// This is `demand_eqtype`, but inlined to give a better error.
|
||||
let cause = fcx.misc(self.span);
|
||||
if fcx
|
||||
.at(&cause, fcx.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, src_obj, dst_obj)
|
||||
.map(|infer_ok| fcx.register_infer_ok_obligations(infer_ok))
|
||||
.is_err()
|
||||
{
|
||||
return Err(CastError::DifferingKinds { src_kind, dst_kind });
|
||||
}
|
||||
|
||||
// Check that `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`.
|
||||
// Emit an FCW otherwise.
|
||||
|
@ -905,17 +967,17 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
|
||||
// dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
|
||||
// FIXME: allow this
|
||||
(Some(_), None) => Err(CastError::DifferingKinds),
|
||||
(Some(_), None) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
|
||||
|
||||
// dyn Auto -> dyn Trait? not ok.
|
||||
(None, Some(_)) => Err(CastError::DifferingKinds),
|
||||
(None, Some(_)) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
|
||||
}
|
||||
}
|
||||
|
||||
// fat -> fat? metadata kinds must match
|
||||
(Some(src_kind), Some(dst_kind)) if src_kind == dst_kind => Ok(CastKind::PtrPtrCast),
|
||||
(src_kind, dst_kind) if src_kind == dst_kind => Ok(CastKind::PtrPtrCast),
|
||||
|
||||
(_, _) => Err(CastError::DifferingKinds),
|
||||
(_, _) => Err(CastError::DifferingKinds { src_kind, dst_kind }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -923,7 +985,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_cast: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
// fptr-ptr cast. must be to thin ptr
|
||||
|
||||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||
|
@ -937,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_expr: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
// ptr-addr cast. must be from thin ptr
|
||||
|
||||
match fcx.pointer_kind(m_expr.ty, self.span)? {
|
||||
|
@ -952,7 +1014,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_expr: ty::TypeAndMut<'tcx>,
|
||||
m_cast: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
|
||||
if m_expr.mutbl >= m_cast.mutbl {
|
||||
if let ty::Array(ety, _) = m_expr.ty.kind() {
|
||||
|
@ -987,7 +1049,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_cast: TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError> {
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
// ptr-addr cast. pointer must be thin.
|
||||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||
None => Err(CastError::UnknownCastPtrKind),
|
||||
|
|
|
@ -769,7 +769,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
));
|
||||
|
||||
Ok(InferOk {
|
||||
value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
|
||||
value: (
|
||||
vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }],
|
||||
b,
|
||||
),
|
||||
obligations,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2126,7 +2126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.tcx
|
||||
.inherent_impls(def_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers.
|
||||
.filter(|item| {
|
||||
|
|
|
@ -759,9 +759,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
for adjustment in adjustments {
|
||||
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
|
||||
match adjustment.kind {
|
||||
adjustment::Adjust::NeverToAny
|
||||
| adjustment::Adjust::Pointer(_)
|
||||
| adjustment::Adjust::DynStar => {
|
||||
adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
|
||||
// Creating a closure/fn-pointer or unsizing consumes
|
||||
// the input and stores it into the resulting rvalue.
|
||||
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
|
||||
|
@ -1296,8 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
adjustment::Adjust::NeverToAny
|
||||
| adjustment::Adjust::Pointer(_)
|
||||
| adjustment::Adjust::Borrow(_)
|
||||
| adjustment::Adjust::ReborrowPin(..)
|
||||
| adjustment::Adjust::DynStar => {
|
||||
| adjustment::Adjust::ReborrowPin(..) => {
|
||||
// Result is an rvalue.
|
||||
Ok(self.cat_rvalue(expr.hir_id, target))
|
||||
}
|
||||
|
|
|
@ -728,13 +728,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
|
||||
bug!("unexpected incoherent type: {:?}", self_ty)
|
||||
};
|
||||
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
|
||||
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() {
|
||||
self.assemble_inherent_impl_probe(impl_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
|
||||
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
|
||||
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter();
|
||||
for &impl_def_id in impl_def_ids {
|
||||
self.assemble_inherent_impl_probe(impl_def_id);
|
||||
}
|
||||
|
|
|
@ -680,7 +680,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx
|
||||
.inherent_impls(adt_def.did())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.any(|def_id| self.associated_value(*def_id, item_name).is_some())
|
||||
} else {
|
||||
false
|
||||
|
@ -1438,7 +1437,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.tcx
|
||||
.inherent_impls(adt.did())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.copied()
|
||||
.filter(|def_id| {
|
||||
if let Some(assoc) = self.associated_value(*def_id, item_name) {
|
||||
|
@ -1900,7 +1898,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_args: Option<Vec<Ty<'tcx>>>,
|
||||
) -> Option<Symbol> {
|
||||
if let ty::Adt(adt, adt_args) = rcvr_ty.kind() {
|
||||
for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter().flatten() {
|
||||
for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter() {
|
||||
for inherent_method in
|
||||
self.tcx.associated_items(inherent_impl_did).in_definition_order()
|
||||
{
|
||||
|
@ -2114,9 +2112,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
|
||||
return;
|
||||
};
|
||||
// FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case.
|
||||
let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return };
|
||||
let mut items = impls
|
||||
let mut items = self
|
||||
.tcx
|
||||
.inherent_impls(adt_def.did())
|
||||
.iter()
|
||||
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers and only if
|
||||
|
@ -2495,7 +2493,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.and_then(|simp| {
|
||||
tcx.incoherent_impls(simp)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.find_map(|&id| self.associated_value(id, item_name))
|
||||
})
|
||||
.is_some()
|
||||
|
|
|
@ -347,7 +347,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
|
||||
}
|
||||
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
|
||||
inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) }
|
||||
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
|
||||
item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
|
||||
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
|
||||
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
|
||||
|
@ -393,7 +393,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
|
||||
trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
|
||||
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
|
||||
crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) }
|
||||
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
|
||||
|
||||
dep_kind => { cdata.dep_kind }
|
||||
module_children => {
|
||||
|
|
|
@ -1540,7 +1540,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
for (def_id, impls) in &tcx.crate_inherent_impls(()).unwrap().inherent_impls {
|
||||
for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
|
||||
record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
|
||||
assert!(def_id.is_local());
|
||||
def_id.index
|
||||
|
@ -2089,7 +2089,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
let all_impls: Vec<_> = tcx
|
||||
.crate_inherent_impls(())
|
||||
.unwrap()
|
||||
.0
|
||||
.incoherent_impls
|
||||
.iter()
|
||||
.map(|(&simp, impls)| IncoherentImpls {
|
||||
|
|
|
@ -234,7 +234,9 @@ pub enum ConstraintCategory<'tcx> {
|
|||
UseAsStatic,
|
||||
TypeAnnotation,
|
||||
Cast {
|
||||
/// Whether this is an unsizing cast and if yes, this contains the target type.
|
||||
/// Whether this cast is a coercion that was automatically inserted by the compiler.
|
||||
is_implicit_coercion: bool,
|
||||
/// Whether this is an unsizing coercion and if yes, this contains the target type.
|
||||
/// Region variables are erased to ReErased.
|
||||
#[derive_where(skip)]
|
||||
unsize_to: Option<Ty<'tcx>>,
|
||||
|
|
|
@ -432,9 +432,8 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
| CastKind::IntToFloat
|
||||
| CastKind::FnPtrToPtr
|
||||
| CastKind::PtrToPtr
|
||||
| CastKind::PointerCoercion(_)
|
||||
| CastKind::PointerCoercion(_, _)
|
||||
| CastKind::PointerWithExposedProvenance
|
||||
| CastKind::DynStar
|
||||
| CastKind::Transmute,
|
||||
_,
|
||||
_,
|
||||
|
|
|
@ -579,7 +579,8 @@ pub struct CopyNonOverlapping<'tcx> {
|
|||
pub count: Operand<'tcx>,
|
||||
}
|
||||
|
||||
/// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics
|
||||
/// Represents how a [`TerminatorKind::Call`] was constructed.
|
||||
/// Used only for diagnostics.
|
||||
#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum CallSource {
|
||||
|
@ -1403,9 +1404,7 @@ pub enum CastKind {
|
|||
/// * [`PointerCoercion::MutToConstPointer`]
|
||||
///
|
||||
/// Both are runtime nops, so should be [`CastKind::PtrToPtr`] instead in runtime MIR.
|
||||
PointerCoercion(PointerCoercion),
|
||||
/// Cast into a dyn* object.
|
||||
DynStar,
|
||||
PointerCoercion(PointerCoercion, CoercionSource),
|
||||
IntToInt,
|
||||
FloatToInt,
|
||||
FloatToFloat,
|
||||
|
@ -1421,6 +1420,16 @@ pub enum CastKind {
|
|||
Transmute,
|
||||
}
|
||||
|
||||
/// Represents how a [`CastKind::PointerCoercion`] was constructed.
|
||||
/// Used only for diagnostics.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
pub enum CoercionSource {
|
||||
/// The coercion was manually written by the user with an `as` cast.
|
||||
AsCast,
|
||||
/// The coercion was automatically inserted by the compiler.
|
||||
Implicit,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum AggregateKind<'tcx> {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::intrinsics::transmute_unchecked;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
use crate::query::CyclePlaceholder;
|
||||
use crate::ty::adjustment::CoerceUnsizedInfo;
|
||||
use crate::ty::{self, Ty};
|
||||
|
@ -216,6 +218,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
|
|||
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
|
||||
}
|
||||
|
||||
impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
|
||||
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
|
||||
}
|
||||
|
||||
macro_rules! trivial {
|
||||
($($ty:ty),+ $(,)?) => {
|
||||
$(
|
||||
|
|
|
@ -881,13 +881,13 @@ rustc_queries! {
|
|||
/// Maps a `DefId` of a type to a list of its inherent impls.
|
||||
/// Contains implementations of methods that are inherent to a type.
|
||||
/// Methods in these implementations don't need to be exported.
|
||||
query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> {
|
||||
query inherent_impls(key: DefId) -> &'tcx [DefId] {
|
||||
desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> {
|
||||
query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] {
|
||||
desc { |tcx| "collecting all inherent impls for `{:?}`", key }
|
||||
}
|
||||
|
||||
|
@ -1017,8 +1017,14 @@ rustc_queries! {
|
|||
|
||||
/// Gets a complete map from all types to their inherent impls.
|
||||
/// Not meant to be used directly outside of coherence.
|
||||
query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> {
|
||||
query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) {
|
||||
desc { "finding all inherent impls defined in crate" }
|
||||
}
|
||||
|
||||
/// Checks all types in the crate for overlap in their inherent impls. Reports errors.
|
||||
/// Not meant to be used directly outside of coherence.
|
||||
query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> {
|
||||
desc { "check for inherent impls that should not be defined in crate" }
|
||||
ensure_forwards_result_if_red
|
||||
}
|
||||
|
||||
|
@ -1715,7 +1721,7 @@ rustc_queries! {
|
|||
///
|
||||
/// Do not call this directly, but instead use the `incoherent_impls` query.
|
||||
/// This query is only used to get the data necessary for that query.
|
||||
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> {
|
||||
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] {
|
||||
desc { |tcx| "collecting all impls for a type in a crate" }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
|
|
@ -338,6 +338,8 @@ pub enum ExprKind<'tcx> {
|
|||
PointerCoercion {
|
||||
cast: PointerCoercion,
|
||||
source: ExprId,
|
||||
/// Whether this coercion is written with an `as` cast in the source code.
|
||||
is_from_as_cast: bool,
|
||||
},
|
||||
/// A `loop` expression.
|
||||
Loop {
|
||||
|
@ -453,12 +455,14 @@ pub enum ExprKind<'tcx> {
|
|||
source: ExprId,
|
||||
/// Type that the user gave to this expression
|
||||
user_ty: UserTy<'tcx>,
|
||||
user_ty_span: Span,
|
||||
},
|
||||
/// A type ascription on a value, e.g. `42: i32`.
|
||||
/// A type ascription on a value, e.g. `type_ascribe!(42, i32)` or `42 as i32`.
|
||||
ValueTypeAscription {
|
||||
source: ExprId,
|
||||
/// Type that the user gave to this expression
|
||||
user_ty: UserTy<'tcx>,
|
||||
user_ty_span: Span,
|
||||
},
|
||||
/// A closure definition.
|
||||
Closure(Box<ClosureExpr<'tcx>>),
|
||||
|
|
|
@ -68,7 +68,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||
Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
Use { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
PointerCoercion { source, cast: _, is_from_as_cast: _ } => {
|
||||
visitor.visit_expr(&visitor.thir()[source])
|
||||
}
|
||||
Let { expr, ref pat } => {
|
||||
visitor.visit_expr(&visitor.thir()[expr]);
|
||||
visitor.visit_pat(pat);
|
||||
|
@ -129,7 +131,8 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||
visitor.visit_expr(&visitor.thir()[base.base]);
|
||||
}
|
||||
}
|
||||
PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
|
||||
PlaceTypeAscription { source, user_ty: _, user_ty_span: _ }
|
||||
| ValueTypeAscription { source, user_ty: _, user_ty_span: _ } => {
|
||||
visitor.visit_expr(&visitor.thir()[source])
|
||||
}
|
||||
Closure(box ClosureExpr {
|
||||
|
|
|
@ -35,6 +35,9 @@ pub enum PointerCoercion {
|
|||
/// type. Codegen backends and miri figure out what has to be done
|
||||
/// based on the precise source/target type at hand.
|
||||
Unsize,
|
||||
|
||||
/// Go from a pointer-like type to a `dyn*` object.
|
||||
DynStar,
|
||||
}
|
||||
|
||||
/// Represents coercing a value to a different type of value.
|
||||
|
@ -102,9 +105,6 @@ pub enum Adjust<'tcx> {
|
|||
|
||||
Pointer(PointerCoercion),
|
||||
|
||||
/// Cast into a dyn* object.
|
||||
DynStar,
|
||||
|
||||
/// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
|
||||
ReborrowPin(ty::Region<'tcx>, hir::Mutability),
|
||||
}
|
||||
|
|
|
@ -34,15 +34,12 @@ pub enum CastTy<'tcx> {
|
|||
FnPtr,
|
||||
/// Raw pointers.
|
||||
Ptr(ty::TypeAndMut<'tcx>),
|
||||
/// Casting into a `dyn*` value.
|
||||
DynStar,
|
||||
}
|
||||
|
||||
/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
|
||||
/// (or rustc_hir_analysis/check/cast.rs).
|
||||
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum CastKind {
|
||||
CoercionCast,
|
||||
PtrPtrCast,
|
||||
PtrAddrCast,
|
||||
AddrPtrCast,
|
||||
|
@ -53,7 +50,6 @@ pub enum CastKind {
|
|||
ArrayPtrCast,
|
||||
FnPtrPtrCast,
|
||||
FnPtrAddrCast,
|
||||
DynStarCast,
|
||||
}
|
||||
|
||||
impl<'tcx> CastTy<'tcx> {
|
||||
|
@ -71,7 +67,6 @@ impl<'tcx> CastTy<'tcx> {
|
|||
ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
|
||||
ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })),
|
||||
ty::FnPtr(..) => Some(CastTy::FnPtr),
|
||||
ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +81,6 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin
|
|||
mir::CastKind::PointerExposeProvenance
|
||||
}
|
||||
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance,
|
||||
(_, Some(CastTy::DynStar)) => mir::CastKind::DynStar,
|
||||
(Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt,
|
||||
(Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr,
|
||||
|
||||
|
|
|
@ -253,30 +253,16 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
|
|||
}
|
||||
|
||||
/// Query provider for `incoherent_impls`.
|
||||
pub(super) fn incoherent_impls_provider(
|
||||
tcx: TyCtxt<'_>,
|
||||
simp: SimplifiedType,
|
||||
) -> Result<&[DefId], ErrorGuaranteed> {
|
||||
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
|
||||
let mut impls = Vec::new();
|
||||
|
||||
let mut res = Ok(());
|
||||
for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
|
||||
let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
|
||||
Ok(impls) => impls,
|
||||
Err(e) => {
|
||||
res = Err(e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
for &impl_def_id in incoherent_impls {
|
||||
for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
|
||||
impls.push(impl_def_id)
|
||||
}
|
||||
}
|
||||
|
||||
debug!(?impls);
|
||||
res?;
|
||||
|
||||
Ok(tcx.arena.alloc_slice(&impls))
|
||||
tcx.arena.alloc_slice(&impls)
|
||||
}
|
||||
|
||||
pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
|
||||
|
|
|
@ -470,21 +470,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
block.and(place_builder)
|
||||
}
|
||||
|
||||
ExprKind::PlaceTypeAscription { source, ref user_ty } => {
|
||||
ExprKind::PlaceTypeAscription { source, ref user_ty, user_ty_span } => {
|
||||
let place_builder = unpack!(
|
||||
block = this.expr_as_place(block, source, mutability, fake_borrow_temps,)
|
||||
);
|
||||
if let Some(user_ty) = user_ty {
|
||||
let ty_source_info = this.source_info(user_ty_span);
|
||||
let annotation_index =
|
||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||
span: source_info.span,
|
||||
span: user_ty_span,
|
||||
user_ty: user_ty.clone(),
|
||||
inferred_ty: expr.ty,
|
||||
});
|
||||
|
||||
let place = place_builder.to_place(this);
|
||||
this.cfg.push(block, Statement {
|
||||
source_info,
|
||||
source_info: ty_source_info,
|
||||
kind: StatementKind::AscribeUserType(
|
||||
Box::new((place, UserTypeProjection {
|
||||
base: annotation_index,
|
||||
|
@ -496,20 +497,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
block.and(place_builder)
|
||||
}
|
||||
ExprKind::ValueTypeAscription { source, ref user_ty } => {
|
||||
ExprKind::ValueTypeAscription { source, ref user_ty, user_ty_span } => {
|
||||
let source_expr = &this.thir[source];
|
||||
let temp = unpack!(
|
||||
block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
|
||||
);
|
||||
if let Some(user_ty) = user_ty {
|
||||
let ty_source_info = this.source_info(user_ty_span);
|
||||
let annotation_index =
|
||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||
span: source_info.span,
|
||||
span: user_ty_span,
|
||||
user_ty: user_ty.clone(),
|
||||
inferred_ty: expr.ty,
|
||||
});
|
||||
this.cfg.push(block, Statement {
|
||||
source_info,
|
||||
source_info: ty_source_info,
|
||||
kind: StatementKind::AscribeUserType(
|
||||
Box::new((Place::from(temp), UserTypeProjection {
|
||||
base: annotation_index,
|
||||
|
|
|
@ -292,7 +292,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let cast_kind = mir_cast_kind(ty, expr.ty);
|
||||
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
|
||||
}
|
||||
ExprKind::PointerCoercion { cast, source } => {
|
||||
ExprKind::PointerCoercion { cast, source, is_from_as_cast } => {
|
||||
let source = unpack!(
|
||||
block = this.as_operand(
|
||||
block,
|
||||
|
@ -302,7 +302,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
NeedsTemporary::No
|
||||
)
|
||||
);
|
||||
block.and(Rvalue::Cast(CastKind::PointerCoercion(cast), source, expr.ty))
|
||||
let origin =
|
||||
if is_from_as_cast { CoercionSource::AsCast } else { CoercionSource::Implicit };
|
||||
block.and(Rvalue::Cast(CastKind::PointerCoercion(cast, origin), source, expr.ty))
|
||||
}
|
||||
ExprKind::Array { ref fields } => {
|
||||
// (*) We would (maybe) be closer to codegen if we
|
||||
|
|
|
@ -407,7 +407,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
source_info,
|
||||
temp,
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::Unsize,
|
||||
CoercionSource::Implicit,
|
||||
),
|
||||
Operand::Copy(val),
|
||||
ty,
|
||||
),
|
||||
|
@ -421,7 +424,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
source_info,
|
||||
slice,
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(
|
||||
PointerCoercion::Unsize,
|
||||
CoercionSource::Implicit,
|
||||
),
|
||||
expect,
|
||||
ty,
|
||||
),
|
||||
|
|
|
@ -104,15 +104,28 @@ impl<'tcx> Cx<'tcx> {
|
|||
};
|
||||
|
||||
let kind = match adjustment.kind {
|
||||
Adjust::Pointer(PointerCoercion::Unsize) => {
|
||||
adjust_span(&mut expr);
|
||||
ExprKind::PointerCoercion {
|
||||
cast: PointerCoercion::Unsize,
|
||||
source: self.thir.exprs.push(expr),
|
||||
}
|
||||
}
|
||||
Adjust::Pointer(cast) => {
|
||||
ExprKind::PointerCoercion { cast, source: self.thir.exprs.push(expr) }
|
||||
if cast == PointerCoercion::Unsize {
|
||||
adjust_span(&mut expr);
|
||||
}
|
||||
|
||||
let is_from_as_cast = if let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Cast(..),
|
||||
span: cast_span,
|
||||
..
|
||||
}) = self.tcx.parent_hir_node(hir_expr.hir_id)
|
||||
{
|
||||
// Use the whole span of the `x as T` expression for the coercion.
|
||||
span = *cast_span;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
ExprKind::PointerCoercion {
|
||||
cast,
|
||||
source: self.thir.exprs.push(expr),
|
||||
is_from_as_cast,
|
||||
}
|
||||
}
|
||||
Adjust::NeverToAny if adjustment.target.is_never() => return expr,
|
||||
Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
|
||||
|
@ -146,7 +159,6 @@ impl<'tcx> Cx<'tcx> {
|
|||
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
|
||||
}
|
||||
Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
|
||||
Adjust::ReborrowPin(region, mutbl) => {
|
||||
debug!("apply ReborrowPin adjustment");
|
||||
// Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
|
||||
|
@ -236,6 +248,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
ExprKind::PointerCoercion {
|
||||
source: self.mirror_expr(source),
|
||||
cast: PointerCoercion::ArrayToPointer,
|
||||
is_from_as_cast: true,
|
||||
}
|
||||
} else if let hir::ExprKind::Path(ref qpath) = source.kind
|
||||
&& let res = self.typeck_results().qpath_res(qpath, source.hir_id)
|
||||
|
@ -841,6 +854,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
ExprKind::ValueTypeAscription {
|
||||
source: cast_expr,
|
||||
user_ty: Some(Box::new(*user_ty)),
|
||||
user_ty_span: cast_ty.span,
|
||||
}
|
||||
} else {
|
||||
cast
|
||||
|
@ -852,9 +866,17 @@ impl<'tcx> Cx<'tcx> {
|
|||
debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
|
||||
let mirrored = self.mirror_expr(source);
|
||||
if source.is_syntactic_place_expr() {
|
||||
ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
|
||||
ExprKind::PlaceTypeAscription {
|
||||
source: mirrored,
|
||||
user_ty,
|
||||
user_ty_span: ty.span,
|
||||
}
|
||||
} else {
|
||||
ExprKind::ValueTypeAscription { source: mirrored, user_ty }
|
||||
ExprKind::ValueTypeAscription {
|
||||
source: mirrored,
|
||||
user_ty,
|
||||
user_ty_span: ty.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) },
|
||||
|
|
|
@ -292,9 +292,14 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
self.print_expr(*source, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
PointerCoercion { cast, source } => {
|
||||
PointerCoercion { cast, is_from_as_cast, source } => {
|
||||
print_indented!(self, "Pointer {", depth_lvl);
|
||||
print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1);
|
||||
print_indented!(
|
||||
self,
|
||||
format!("is_from_as_cast: {:?}", is_from_as_cast),
|
||||
depth_lvl + 1
|
||||
);
|
||||
print_indented!(self, "source:", depth_lvl + 1);
|
||||
self.print_expr(*source, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
|
@ -454,16 +459,18 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
self.print_adt_expr(&**adt_expr, depth_lvl + 1);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
PlaceTypeAscription { source, user_ty } => {
|
||||
PlaceTypeAscription { source, user_ty, user_ty_span } => {
|
||||
print_indented!(self, "PlaceTypeAscription {", depth_lvl);
|
||||
print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
|
||||
print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
|
||||
print_indented!(self, "source:", depth_lvl + 1);
|
||||
self.print_expr(*source, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
ValueTypeAscription { source, user_ty } => {
|
||||
ValueTypeAscription { source, user_ty, user_ty_span } => {
|
||||
print_indented!(self, "ValueTypeAscription {", depth_lvl);
|
||||
print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
|
||||
print_indented!(self, format!("user_ty_span: {:?}", user_ty_span), depth_lvl + 1);
|
||||
print_indented!(self, "source:", depth_lvl + 1);
|
||||
self.print_expr(*source, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl);
|
||||
|
|
|
@ -42,6 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
|
|||
ref mut cast_kind @ CastKind::PointerCoercion(
|
||||
PointerCoercion::ArrayToPointer
|
||||
| PointerCoercion::MutToConstPointer,
|
||||
_,
|
||||
),
|
||||
..,
|
||||
),
|
||||
|
|
|
@ -189,7 +189,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
Rvalue::Cast(
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
|
||||
operand,
|
||||
_,
|
||||
) => {
|
||||
|
|
|
@ -576,7 +576,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
value.offset(Size::ZERO, to, &self.ecx).ok()?
|
||||
}
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) => {
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => {
|
||||
let src = self.evaluated[value].as_ref()?;
|
||||
let to = self.ecx.layout_of(to).ok()?;
|
||||
let dest = self.ecx.allocate(to, MemoryKind::Stack).ok()?;
|
||||
|
@ -593,7 +593,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
let ret = self.ecx.ptr_to_ptr(&src, to).ok()?;
|
||||
ret.into()
|
||||
}
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer) => {
|
||||
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer, _) => {
|
||||
let src = self.evaluated[value].as_ref()?;
|
||||
let src = self.ecx.read_immediate(src).ok()?;
|
||||
let to = self.ecx.layout_of(to).ok()?;
|
||||
|
@ -1138,7 +1138,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
(
|
||||
UnOp::PtrMetadata,
|
||||
Value::Cast {
|
||||
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize),
|
||||
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
|
||||
from,
|
||||
to,
|
||||
..
|
||||
|
@ -1342,7 +1342,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
return Some(value);
|
||||
}
|
||||
|
||||
if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_)) = kind {
|
||||
if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_), _) = kind {
|
||||
// Each reification of a generic fn may get a different pointer.
|
||||
// Do not try to merge them.
|
||||
return self.new_opaque();
|
||||
|
@ -1429,7 +1429,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
|
||||
// We have an unsizing cast, which assigns the length to fat pointer metadata.
|
||||
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
||||
&& let Some(from) = from.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = from.kind()
|
||||
&& let Some(to) = to.builtin_deref(true)
|
||||
|
|
|
@ -70,11 +70,11 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
match *rvalue {
|
||||
// We need to detect unsizing casts that required vtables.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
|
||||
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
ref operand,
|
||||
target_ty,
|
||||
)
|
||||
| mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
|
||||
) => {
|
||||
// This isn't monomorphized yet so we can't tell what the actual types are -- just
|
||||
// add everything that may involve a vtable.
|
||||
let source_ty = operand.ty(self.body, self.tcx);
|
||||
|
@ -96,7 +96,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
}
|
||||
// Similarly, record closures that are turned into function pointers.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
|
@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
}
|
||||
// And finally, function pointer reification casts.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
|
|
|
@ -7,9 +7,10 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::mir::{
|
||||
BasicBlock, BasicBlockData, Body, CallSource, CastKind, Const, ConstOperand, ConstValue, Local,
|
||||
LocalDecl, MirSource, Operand, Place, PlaceElem, RETURN_PLACE, Rvalue, SourceInfo, Statement,
|
||||
StatementKind, Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason,
|
||||
BasicBlock, BasicBlockData, Body, CallSource, CastKind, CoercionSource, Const, ConstOperand,
|
||||
ConstValue, Local, LocalDecl, MirSource, Operand, Place, PlaceElem, RETURN_PLACE, Rvalue,
|
||||
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnwindAction,
|
||||
UnwindTerminateReason,
|
||||
};
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::util::{AsyncDropGlueMorphology, Discr};
|
||||
|
@ -329,7 +330,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
|
|||
fn put_array_as_slice(&mut self, elem_ty: Ty<'tcx>) {
|
||||
let slice_ptr_ty = Ty::new_mut_ptr(self.tcx, Ty::new_slice(self.tcx, elem_ty));
|
||||
self.put_temp_rvalue(Rvalue::Cast(
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, CoercionSource::Implicit),
|
||||
Operand::Copy(Self::SELF_PTR.into()),
|
||||
slice_ptr_ty,
|
||||
))
|
||||
|
|
|
@ -1128,12 +1128,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
Rvalue::Cast(kind, operand, target_type) => {
|
||||
let op_ty = operand.ty(self.body, self.tcx);
|
||||
match kind {
|
||||
CastKind::DynStar => {
|
||||
// FIXME(dyn-star): make sure nothing needs to be done here.
|
||||
}
|
||||
// FIXME: Add Checks for these
|
||||
CastKind::PointerWithExposedProvenance | CastKind::PointerExposeProvenance => {}
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
|
||||
// FIXME: check signature compatibility.
|
||||
check_kinds!(
|
||||
op_ty,
|
||||
|
@ -1146,7 +1143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
ty::FnPtr(..)
|
||||
);
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
|
||||
// FIXME: check safety and signature compatibility.
|
||||
check_kinds!(
|
||||
op_ty,
|
||||
|
@ -1159,7 +1156,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
ty::FnPtr(..)
|
||||
);
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..)) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..), _) => {
|
||||
// FIXME: check safety, captures, and signature compatibility.
|
||||
check_kinds!(
|
||||
op_ty,
|
||||
|
@ -1172,7 +1169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
ty::FnPtr(..)
|
||||
);
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer, _) => {
|
||||
// FIXME: check same pointee?
|
||||
check_kinds!(
|
||||
op_ty,
|
||||
|
@ -1188,7 +1185,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
|
||||
}
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, _) => {
|
||||
// FIXME: Check pointee types
|
||||
check_kinds!(
|
||||
op_ty,
|
||||
|
@ -1204,10 +1201,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
|
||||
}
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
|
||||
CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
|
||||
// This is used for all `CoerceUnsized` types,
|
||||
// not just pointers/references, so is hard to check.
|
||||
}
|
||||
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
|
||||
// FIXME(dyn-star): make sure nothing needs to be done here.
|
||||
}
|
||||
CastKind::IntToInt | CastKind::IntToFloat => {
|
||||
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
|
||||
let target_valid = target_type.is_numeric() || target_type.is_char();
|
||||
|
|
|
@ -665,11 +665,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
// have to instantiate all methods of the trait being cast to, so we
|
||||
// can build the appropriate vtable.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
|
||||
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
||||
ref operand,
|
||||
target_ty,
|
||||
)
|
||||
| mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
|
||||
) => {
|
||||
let source_ty = operand.ty(self.body, self.tcx);
|
||||
// *Before* monomorphizing, record that we already handled this mention.
|
||||
self.used_mentioned_items
|
||||
|
@ -694,7 +694,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
|
@ -705,7 +705,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
visit_fn_use(self.tcx, fn_ty, false, span, self.used_items);
|
||||
}
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
|
@ -1183,7 +1183,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
|
|||
}
|
||||
|
||||
fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
|
||||
for impl_def_id in tcx.inherent_impls(def_id).ok()? {
|
||||
for impl_def_id in tcx.inherent_impls(def_id) {
|
||||
if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
|
||||
tcx,
|
||||
fn_ident,
|
||||
|
|
|
@ -1825,10 +1825,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
// Doing analysis on local `DefId`s would cause infinite recursion.
|
||||
return;
|
||||
}
|
||||
let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return };
|
||||
// Look at all the associated functions without receivers in the type's
|
||||
// inherent impls to look for builders that return `Self`
|
||||
let mut items = impls
|
||||
let mut items = self
|
||||
.r
|
||||
.tcx
|
||||
.inherent_impls(def_id)
|
||||
.iter()
|
||||
.flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
|
||||
// Only assoc fn with no receivers.
|
||||
|
|
|
@ -282,11 +282,12 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
|
|||
type T = stable_mir::mir::CastKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
use rustc_middle::mir::CastKind::*;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
match self {
|
||||
PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
|
||||
PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
|
||||
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
|
||||
DynStar => stable_mir::mir::CastKind::DynStar,
|
||||
PointerCoercion(PointerCoercion::DynStar, _) => stable_mir::mir::CastKind::DynStar,
|
||||
PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
|
||||
IntToInt => stable_mir::mir::CastKind::IntToInt,
|
||||
FloatToInt => stable_mir::mir::CastKind::FloatToInt,
|
||||
FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
|
||||
|
|
|
@ -119,6 +119,7 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
|
|||
}
|
||||
PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
|
||||
PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
|
||||
PointerCoercion::DynStar => unreachable!("represented as `CastKind::DynStar` in smir"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -960,6 +960,7 @@ pub enum CastKind {
|
|||
PointerExposeAddress,
|
||||
PointerWithExposedProvenance,
|
||||
PointerCoercion(PointerCoercion),
|
||||
// FIXME(smir-rename): change this to PointerCoercion(DynStar)
|
||||
DynStar,
|
||||
IntToInt,
|
||||
FloatToInt,
|
||||
|
|
|
@ -326,6 +326,7 @@ dependencies = [
|
|||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"memchr",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
|
|
|
@ -23,6 +23,10 @@ unwind = { path = "../unwind" }
|
|||
hashbrown = { version = "0.14", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
] }
|
||||
# FIXME(#127890): `object` depends on `memchr`, but `memchr` > v2.5 causes
|
||||
# issues with LTO. This dependency is not used directly, but pin it here so
|
||||
# it resolves to 2.5. To be removed once rust-lang/rust#127890 is fixed.
|
||||
memchr = { version = "=2.5.0", default-features = false, features = ["rustc-dep-of-std"] }
|
||||
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
] }
|
||||
|
|
|
@ -400,6 +400,11 @@ pub enum ErrorKind {
|
|||
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
|
||||
OutOfMemory,
|
||||
|
||||
/// The operation was partially successful and needs to be checked
|
||||
/// later on due to not blocking.
|
||||
#[unstable(feature = "io_error_inprogress", issue = "none")]
|
||||
InProgress,
|
||||
|
||||
// "Unusual" error kinds which do not correspond simply to (sets
|
||||
// of) OS error codes, should be added just above this comment.
|
||||
// `Other` and `Uncategorized` should remain at the end:
|
||||
|
@ -449,6 +454,7 @@ impl ErrorKind {
|
|||
FilesystemQuotaExceeded => "filesystem quota exceeded",
|
||||
HostUnreachable => "host unreachable",
|
||||
Interrupted => "operation interrupted",
|
||||
InProgress => "in progress",
|
||||
InvalidData => "invalid data",
|
||||
InvalidFilename => "invalid filename",
|
||||
InvalidInput => "invalid input parameter",
|
||||
|
|
|
@ -348,6 +348,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
|
|||
UnexpectedEof,
|
||||
Unsupported,
|
||||
OutOfMemory,
|
||||
InProgress,
|
||||
Uncategorized,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -279,6 +279,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
libc::ETIMEDOUT => TimedOut,
|
||||
libc::ETXTBSY => ExecutableFileBusy,
|
||||
libc::EXDEV => CrossesDevices,
|
||||
libc::EINPROGRESS => InProgress,
|
||||
|
||||
libc::EACCES | libc::EPERM => PermissionDenied,
|
||||
|
||||
|
|
|
@ -373,7 +373,7 @@ pub(crate) fn build_impls(
|
|||
let tcx = cx.tcx;
|
||||
|
||||
// for each implementation of an item represented by `did`, build the clean::Item for that impl
|
||||
for &did in tcx.inherent_impls(did).into_iter().flatten() {
|
||||
for &did in tcx.inherent_impls(did).into_iter() {
|
||||
cx.with_param_env(did, |cx| {
|
||||
build_impl(cx, did, attrs, ret);
|
||||
});
|
||||
|
@ -388,7 +388,7 @@ pub(crate) fn build_impls(
|
|||
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
|
||||
let type_ =
|
||||
if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
|
||||
for &did in tcx.incoherent_impls(type_).into_iter().flatten() {
|
||||
for &did in tcx.incoherent_impls(type_).into_iter() {
|
||||
cx.with_param_env(did, |cx| {
|
||||
build_impl(cx, did, attrs, ret);
|
||||
});
|
||||
|
|
|
@ -384,7 +384,45 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||
|
||||
impl Item {
|
||||
pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> {
|
||||
self.def_id().and_then(|did| tcx.lookup_stability(did))
|
||||
let (mut def_id, mut stability) = if let Some(inlined) = self.inline_stmt_id {
|
||||
let inlined_def_id = inlined.to_def_id();
|
||||
if let Some(stability) = tcx.lookup_stability(inlined_def_id) {
|
||||
(inlined_def_id, stability)
|
||||
} else {
|
||||
// For re-exports into crates without `staged_api`, reuse the original stability.
|
||||
// This is necessary, because we always want to mark unstable items.
|
||||
let def_id = self.def_id()?;
|
||||
return tcx.lookup_stability(def_id);
|
||||
}
|
||||
} else {
|
||||
let def_id = self.def_id()?;
|
||||
let stability = tcx.lookup_stability(def_id)?;
|
||||
(def_id, stability)
|
||||
};
|
||||
|
||||
let StabilityLevel::Stable { mut since, allowed_through_unstable_modules: false } =
|
||||
stability.level
|
||||
else {
|
||||
return Some(stability);
|
||||
};
|
||||
|
||||
// If any of the item's ancestors was stabilized later or is still unstable,
|
||||
// then report the ancestor's stability instead.
|
||||
while let Some(parent_def_id) = tcx.opt_parent(def_id) {
|
||||
if let Some(parent_stability) = tcx.lookup_stability(parent_def_id) {
|
||||
match parent_stability.level {
|
||||
StabilityLevel::Unstable { .. } => return Some(parent_stability),
|
||||
StabilityLevel::Stable { since: parent_since, .. } => {
|
||||
if parent_since > since {
|
||||
stability = parent_stability;
|
||||
since = parent_since;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
def_id = parent_def_id;
|
||||
}
|
||||
Some(stability)
|
||||
}
|
||||
|
||||
pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> {
|
||||
|
@ -1863,7 +1901,7 @@ impl PrimitiveType {
|
|||
.get(self)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten())
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter())
|
||||
.copied()
|
||||
}
|
||||
|
||||
|
@ -1871,7 +1909,7 @@ impl PrimitiveType {
|
|||
Self::simplified_types()
|
||||
.values()
|
||||
.flatten()
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten())
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter())
|
||||
.copied()
|
||||
}
|
||||
|
||||
|
|
|
@ -608,7 +608,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
let mut assoc_items: Vec<_> = tcx
|
||||
.inherent_impls(did)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&imp| {
|
||||
filter_assoc_items_by_name_and_namespace(
|
||||
tcx,
|
||||
|
|
|
@ -386,7 +386,6 @@ fn check_unsafe_derive_deserialize<'tcx>(
|
|||
.tcx
|
||||
.inherent_impls(def.did())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
|
||||
.any(|imp| has_unsafe(cx, imp))
|
||||
{
|
||||
|
|
|
@ -51,9 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
|
|||
// List of spans to lint. (lint_span, first_span)
|
||||
let mut lint_spans = Vec::new();
|
||||
|
||||
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
|
||||
return;
|
||||
};
|
||||
let (impls, _) = cx.tcx.crate_inherent_impls(());
|
||||
|
||||
for (&id, impl_ids) in &impls.inherent_impls {
|
||||
if impl_ids.len() < 2
|
||||
|
|
|
@ -448,7 +448,6 @@ fn check_for_is_empty(
|
|||
.tcx
|
||||
.inherent_impls(impl_ty)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
|
||||
.find(|item| item.kind == AssocKind::Fn);
|
||||
|
||||
|
@ -616,7 +615,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
/// Checks the inherent impl's items for an `is_empty(self)` method.
|
||||
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
|
||||
let is_empty = sym!(is_empty);
|
||||
cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| {
|
||||
cx.tcx.inherent_impls(id).into_iter().any(|imp| {
|
||||
cx.tcx
|
||||
.associated_items(*imp)
|
||||
.filter_by_name_unhygienic(is_empty)
|
||||
|
|
|
@ -78,7 +78,6 @@ pub(super) fn check<'tcx>(
|
|||
cx.tcx
|
||||
.inherent_impls(adt_def.did())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
|
||||
.find_map(|assoc| {
|
||||
if assoc.fn_has_self_parameter
|
||||
|
|
|
@ -589,14 +589,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
|
|||
"f32" => SimplifiedType::Float(FloatTy::F32),
|
||||
"f64" => SimplifiedType::Float(FloatTy::F64),
|
||||
_ => {
|
||||
return Result::<&[_], rustc_errors::ErrorGuaranteed>::Ok(&[])
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.copied();
|
||||
return [].iter().copied();
|
||||
},
|
||||
};
|
||||
|
||||
tcx.incoherent_impls(ty).into_iter().flatten().copied()
|
||||
tcx.incoherent_impls(ty).into_iter().copied()
|
||||
}
|
||||
|
||||
fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
|
||||
|
@ -721,7 +718,6 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
|
|||
let inherent_impl_children = tcx
|
||||
.inherent_impls(def_id)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
|
||||
|
||||
let direct_children = item_children_by_name(tcx, def_id, segment);
|
||||
|
|
|
@ -123,7 +123,7 @@ fn check_rvalue<'tcx>(
|
|||
| CastKind::FloatToFloat
|
||||
| CastKind::FnPtrToPtr
|
||||
| CastKind::PtrToPtr
|
||||
| CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer),
|
||||
| CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _),
|
||||
operand,
|
||||
_,
|
||||
) => check_operand(tcx, operand, span, body, msrv),
|
||||
|
@ -131,12 +131,12 @@ fn check_rvalue<'tcx>(
|
|||
CastKind::PointerCoercion(
|
||||
PointerCoercion::UnsafeFnPointer
|
||||
| PointerCoercion::ClosureFnPointer(_)
|
||||
| PointerCoercion::ReifyFnPointer,
|
||||
| PointerCoercion::ReifyFnPointer, _
|
||||
),
|
||||
_,
|
||||
_,
|
||||
) => Err((span, "function pointer casts are not allowed in const fn".into())),
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => {
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize, _), op, cast_ty) => {
|
||||
let Some(pointee_ty) = cast_ty.builtin_deref(true) else {
|
||||
// We cannot allow this for now.
|
||||
return Err((span, "unsizing casts are only allowed for references right now".into()));
|
||||
|
@ -154,7 +154,7 @@ fn check_rvalue<'tcx>(
|
|||
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
|
||||
Err((span, "casting pointers to ints is unstable in const fn".into()))
|
||||
},
|
||||
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::DynStar, _), _, _) => {
|
||||
// FIXME(dyn-star)
|
||||
unimplemented!()
|
||||
},
|
||||
|
|
|
@ -1316,7 +1316,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl
|
|||
/// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`.
|
||||
pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> {
|
||||
if let Some(ty_did) = ty.ty_adt_def().map(AdtDef::did) {
|
||||
cx.tcx.inherent_impls(ty_did).into_iter().flatten().find_map(|&did| {
|
||||
cx.tcx.inherent_impls(ty_did).into_iter().find_map(|&did| {
|
||||
cx.tcx
|
||||
.associated_items(did)
|
||||
.filter_by_name_unhygienic(method_name)
|
||||
|
|
|
@ -15,10 +15,11 @@ impl TestCx<'_> {
|
|||
// if a test does not crash, consider it an error
|
||||
if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) {
|
||||
self.fatal(&format!(
|
||||
"crashtest no longer crashes/triggers ICE, horray! Please give it a meaningful name, \
|
||||
add a doc-comment to the start of the test explaining why it exists and \
|
||||
move it to tests/ui or wherever you see fit. Adding 'Fixes #<issueNr>' to your PR description \
|
||||
ensures that the corresponding ticket is auto-closed upon merge."
|
||||
"crashtest no longer crashes/triggers ICE, horray! Please give it a meaningful \
|
||||
name, add a doc-comment to the start of the test explaining why it exists and \
|
||||
move it to tests/ui or wherever you see fit. Adding 'Fixes #<issueNr>' to your PR \
|
||||
description ensures that the corresponding ticket is auto-closed upon merge. \
|
||||
If you want to see verbose output, set `COMPILETEST_VERBOSE_CRASHES=1`."
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ error: Undefined Behavior: using vtable for `Baz` but `Bar` was expected
|
|||
--> tests/fail/dyn-upcast-trait-mismatch.rs:LL:CC
|
||||
|
|
||||
LL | let _err = baz_fake as *const dyn Foo;
|
||||
| ^^^^^^^^ using vtable for `Baz` but `Bar` was expected
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ using vtable for `Baz` but `Bar` was expected
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//@ revisions: hard soft
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
|
||||
//@ needs-llvm-components: arm
|
||||
//@ [hard] compile-flags: --target thumbv8m.main-none-eabihf --crate-type lib -Copt-level=1
|
||||
//@ [soft] compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
|
||||
//@ [hard] needs-llvm-components: arm
|
||||
//@ [soft] needs-llvm-components: arm
|
||||
#![crate_type = "lib"]
|
||||
#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
@ -9,15 +12,88 @@ pub trait Sized {}
|
|||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
|
||||
// CHECK-LABEL: __acle_se_entry_point
|
||||
// CHECK: bxns
|
||||
// CHECK-LABEL: __acle_se_entry_point:
|
||||
// CHECK-NEXT: entry_point:
|
||||
//
|
||||
// Write return argument (two registers since 64bit integer)
|
||||
// CHECK: movs r0, #0
|
||||
// CHECK: movs r1, #0
|
||||
//
|
||||
// If we are using hard-float:
|
||||
// * Check if the float registers were touched (bit 3 in CONTROL)
|
||||
// hard: mrs [[REG:r[0-9]+]], control
|
||||
// hard: tst.w [[REG]], #8
|
||||
// hard: beq [[LABEL:[\.a-zA-Z0-9_]+]]
|
||||
//
|
||||
// * If touched clear all float registers (d0..=d7)
|
||||
// hard: vmov d0,
|
||||
// hard: vmov d1,
|
||||
// hard: vmov d2,
|
||||
// hard: vmov d3,
|
||||
// hard: vmov d4,
|
||||
// hard: vmov d5,
|
||||
// hard: vmov d6,
|
||||
// hard: vmov d7,
|
||||
//
|
||||
// * If touched clear FPU status register
|
||||
// hard: vmrs [[REG:r[0-9]+]], fpscr
|
||||
// hard: bic [[REG]], [[REG]], #159
|
||||
// hard: bic [[REG]], [[REG]], #4026531840
|
||||
// hard: vmsr fpscr, [[REG]]
|
||||
// hard: [[LABEL]]:
|
||||
//
|
||||
// Clear all other registers that might have been used
|
||||
// CHECK: mov r2,
|
||||
// CHECK: mov r3,
|
||||
// CHECK: mov r12,
|
||||
//
|
||||
// Clear the flags
|
||||
// CHECK: msr apsr_nzcvq,
|
||||
//
|
||||
// Branch back to non-secure side
|
||||
// CHECK: bxns lr
|
||||
#[no_mangle]
|
||||
pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
|
||||
0
|
||||
}
|
||||
|
||||
// NOTE for future codegen changes:
|
||||
// The specific register assignment is not important, however:
|
||||
// * all registers must be cleared before `blxns` is executed
|
||||
// (either by writing arguments or any other value)
|
||||
// * the lowest bit on the address of the callee must be cleared
|
||||
// * the flags need to be overwritten
|
||||
// * `blxns` needs to be called with the callee address
|
||||
// (with the lowest bit cleared)
|
||||
//
|
||||
// CHECK-LABEL: call_nonsecure
|
||||
// CHECK: blxns
|
||||
// Save callee pointer
|
||||
// CHECK: mov r12, r0
|
||||
//
|
||||
// All arguments are written to (writes r0..=r3)
|
||||
// CHECK: movs r0, #0
|
||||
// CHECK: movs r1, #1
|
||||
// CHECK: movs r2, #2
|
||||
// CHECK: movs r3, #3
|
||||
//
|
||||
// Lowest bit gets cleared on callee address
|
||||
// CHECK: bic r12, r12, #1
|
||||
//
|
||||
// Ununsed registers get cleared (r4..=r11)
|
||||
// CHECK: mov r4,
|
||||
// CHECK: mov r5,
|
||||
// CHECK: mov r6,
|
||||
// CHECK: mov r7,
|
||||
// CHECK: mov r8,
|
||||
// CHECK: mov r9,
|
||||
// CHECK: mov r10,
|
||||
// CHECK: mov r11,
|
||||
//
|
||||
// Flags get cleared
|
||||
// CHECK: msr apsr_nzcvq,
|
||||
//
|
||||
// Call to non-secure
|
||||
// CHECK: blxns r12
|
||||
#[no_mangle]
|
||||
pub fn call_nonsecure(
|
||||
f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// MIR for `address_of_reborrow` after SimplifyCfg-initial
|
||||
|
||||
| User Type Annotations
|
||||
| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:8:5: 8:18, inferred_ty: *const [i32; 10]
|
||||
| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:10:5: 10:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
|
||||
| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
|
||||
|
@ -11,8 +11,8 @@
|
|||
| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
|
||||
| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
|
||||
| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:19:5: 19:18, inferred_ty: *const [i32; 10]
|
||||
| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:21:5: 21:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
|
||||
| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
|
||||
|
@ -21,8 +21,8 @@
|
|||
| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
|
||||
| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
|
||||
| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:29:5: 29:16, inferred_ty: *mut [i32; 10]
|
||||
| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:31:5: 31:23, inferred_ty: *mut dyn std::marker::Send
|
||||
| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
|
||||
| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
|
||||
| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
|
||||
|
@ -150,7 +150,7 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_9);
|
||||
StorageLive(_10);
|
||||
_10 = &raw const (*_1);
|
||||
_9 = move _10 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_9 = move _10 as *const dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_10);
|
||||
AscribeUserType(_9, o, UserTypeProjection { base: UserType(1), projs: [] });
|
||||
_8 = copy _9;
|
||||
|
@ -159,13 +159,13 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
_12 = &raw const (*_1);
|
||||
_11 = move _12 as *const [i32] (PointerCoercion(Unsize));
|
||||
_11 = move _12 as *const [i32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
StorageLive(_13);
|
||||
StorageLive(_14);
|
||||
_14 = &raw const (*_1);
|
||||
_13 = move _14 as *const i32 (PointerCoercion(ArrayToPointer));
|
||||
_13 = move _14 as *const i32 (PointerCoercion(ArrayToPointer, AsCast));
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageLive(_15);
|
||||
|
@ -179,14 +179,14 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_17);
|
||||
StorageLive(_18);
|
||||
_18 = &raw const (*_1);
|
||||
_17 = move _18 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_17 = move _18 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_18);
|
||||
FakeRead(ForLet(None), _17);
|
||||
AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] });
|
||||
StorageLive(_19);
|
||||
StorageLive(_20);
|
||||
_20 = &raw const (*_1);
|
||||
_19 = move _20 as *const [i32] (PointerCoercion(Unsize));
|
||||
_19 = move _20 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_20);
|
||||
FakeRead(ForLet(None), _19);
|
||||
AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] });
|
||||
|
@ -204,7 +204,7 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_25);
|
||||
StorageLive(_26);
|
||||
_26 = &raw const (*_3);
|
||||
_25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_26);
|
||||
AscribeUserType(_25, o, UserTypeProjection { base: UserType(11), projs: [] });
|
||||
_24 = copy _25;
|
||||
|
@ -213,7 +213,7 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_27);
|
||||
StorageLive(_28);
|
||||
_28 = &raw const (*_3);
|
||||
_27 = move _28 as *const [i32] (PointerCoercion(Unsize));
|
||||
_27 = move _28 as *const [i32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_28);
|
||||
StorageDead(_27);
|
||||
StorageLive(_29);
|
||||
|
@ -227,14 +227,14 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_31);
|
||||
StorageLive(_32);
|
||||
_32 = &raw const (*_3);
|
||||
_31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_32);
|
||||
FakeRead(ForLet(None), _31);
|
||||
AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] });
|
||||
StorageLive(_33);
|
||||
StorageLive(_34);
|
||||
_34 = &raw const (*_3);
|
||||
_33 = move _34 as *const [i32] (PointerCoercion(Unsize));
|
||||
_33 = move _34 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_34);
|
||||
FakeRead(ForLet(None), _33);
|
||||
AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] });
|
||||
|
@ -252,7 +252,7 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_39);
|
||||
StorageLive(_40);
|
||||
_40 = &raw mut (*_3);
|
||||
_39 = move _40 as *mut dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_39 = move _40 as *mut dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_40);
|
||||
AscribeUserType(_39, o, UserTypeProjection { base: UserType(21), projs: [] });
|
||||
_38 = copy _39;
|
||||
|
@ -261,7 +261,7 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_41);
|
||||
StorageLive(_42);
|
||||
_42 = &raw mut (*_3);
|
||||
_41 = move _42 as *mut [i32] (PointerCoercion(Unsize));
|
||||
_41 = move _42 as *mut [i32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_42);
|
||||
StorageDead(_41);
|
||||
StorageLive(_43);
|
||||
|
@ -275,14 +275,14 @@ fn address_of_reborrow() -> () {
|
|||
StorageLive(_45);
|
||||
StorageLive(_46);
|
||||
_46 = &raw mut (*_3);
|
||||
_45 = move _46 as *mut dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_45 = move _46 as *mut dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_46);
|
||||
FakeRead(ForLet(None), _45);
|
||||
AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] });
|
||||
StorageLive(_47);
|
||||
StorageLive(_48);
|
||||
_48 = &raw mut (*_3);
|
||||
_47 = move _48 as *mut [i32] (PointerCoercion(Unsize));
|
||||
_47 = move _48 as *mut [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_48);
|
||||
FakeRead(ForLet(None), _47);
|
||||
AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] });
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() -> () {
|
|||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = foo as for<'a> fn(&'a (), &'a ()) (PointerCoercion(ReifyFnPointer));
|
||||
_1 = foo as for<'a> fn(&'a (), &'a ()) (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
FakeRead(ForLet(None), _1);
|
||||
_0 = const ();
|
||||
StorageDead(_1);
|
||||
|
|
|
@ -39,7 +39,7 @@ fn main() -> () {
|
|||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = copy _1;
|
||||
_3 = move _4 as *const Test (PointerCoercion(MutToConstPointer));
|
||||
_3 = move _4 as *const Test (PointerCoercion(MutToConstPointer, Implicit));
|
||||
StorageDead(_4);
|
||||
_2 = Test::x(move _3) -> [return: bb2, unwind: bb4];
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ fn main() -> () {
|
|||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
_12 = copy (*(*(*(*_5))));
|
||||
_11 = move _12 as *const Test (PointerCoercion(MutToConstPointer));
|
||||
_11 = move _12 as *const Test (PointerCoercion(MutToConstPointer, Implicit));
|
||||
StorageDead(_12);
|
||||
_10 = Test::x(move _11) -> [return: bb3, unwind: bb4];
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ static XXX: &Foo = {
|
|||
StorageDead(_7);
|
||||
_5 = &_6;
|
||||
_4 = &(*_5);
|
||||
_3 = move _4 as &[(u32, u32)] (PointerCoercion(Unsize));
|
||||
_3 = move _4 as &[(u32, u32)] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_4);
|
||||
_2 = Foo { tup: const "hi", data: move _3 };
|
||||
StorageDead(_3);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
- _2 = &_3;
|
||||
+ _6 = const BAR::promoted[0];
|
||||
+ _2 = &(*_6);
|
||||
_1 = move _2 as &[&i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as &[&i32] (PointerCoercion(Unsize, Implicit));
|
||||
- StorageDead(_4);
|
||||
StorageDead(_2);
|
||||
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2];
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
- _2 = &_3;
|
||||
+ _6 = const FOO::promoted[0];
|
||||
+ _2 = &(*_6);
|
||||
_1 = move _2 as &[&i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as &[&i32] (PointerCoercion(Unsize, Implicit));
|
||||
- StorageDead(_4);
|
||||
StorageDead(_2);
|
||||
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2];
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
_9 = const main::promoted[0];
|
||||
_3 = &(*_9);
|
||||
_2 = &raw const (*_3);
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_2);
|
||||
StorageDead(_3);
|
||||
StorageLive(_5);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
_9 = const main::promoted[0];
|
||||
_3 = &(*_9);
|
||||
_2 = &raw const (*_3);
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_2);
|
||||
StorageDead(_3);
|
||||
StorageLive(_5);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
_9 = const main::promoted[0];
|
||||
_3 = &(*_9);
|
||||
_2 = &raw const (*_3);
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_2);
|
||||
StorageDead(_3);
|
||||
StorageLive(_5);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
_9 = const main::promoted[0];
|
||||
_3 = &(*_9);
|
||||
_2 = &raw const (*_3);
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize));
|
||||
_1 = move _2 as *const [i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_2);
|
||||
StorageDead(_3);
|
||||
StorageLive(_5);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = main as fn() (PointerCoercion(ReifyFnPointer));
|
||||
_3 = main as fn() (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
_2 = move _3 as usize (PointerExposeProvenance);
|
||||
StorageDead(_3);
|
||||
_1 = move _2 as *const fn() (PointerWithExposedProvenance);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
fn main() {
|
||||
// CHECK-LABEL: fn main(
|
||||
// CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer));
|
||||
// CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
// CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeProvenance);
|
||||
// CHECK: [[back:_.*]] = move [[addr]] as *const fn() (PointerWithExposedProvenance);
|
||||
let _ = main as usize as *const fn();
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
_9 = const main::promoted[0];
|
||||
_4 = copy _9;
|
||||
- _3 = copy _4;
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
+ _3 = copy _9;
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize));
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
_9 = const main::promoted[0];
|
||||
_4 = copy _9;
|
||||
- _3 = copy _4;
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
+ _3 = copy _9;
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize));
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
_9 = const main::promoted[0];
|
||||
_4 = copy _9;
|
||||
- _3 = copy _4;
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
+ _3 = copy _9;
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize));
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
_9 = const main::promoted[0];
|
||||
_4 = copy _9;
|
||||
- _3 = copy _4;
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
- _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
+ _3 = copy _9;
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize));
|
||||
+ _2 = copy _9 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
fn main() {
|
||||
// CHECK-LABEL: fn main(
|
||||
// CHECK: debug a => [[a:_.*]];
|
||||
// CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize));
|
||||
// CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
// CHECK: assert(const true,
|
||||
// CHECK: [[a]] = const 2_u32;
|
||||
let a = (&[1u32, 2, 3] as &[u32])[1];
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &_2;
|
||||
_6 = move _7 as &[i32] (PointerCoercion(Unsize));
|
||||
_6 = move _7 as &[i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_7);
|
||||
_5 = core::slice::<impl [i32]>::len(move _6) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
_7 = &_2;
|
||||
_6 = move _7 as &[i32] (PointerCoercion(Unsize));
|
||||
_6 = move _7 as &[i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_7);
|
||||
_5 = core::slice::<impl [i32]>::len(move _6) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
|
||||
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
|
||||
StorageDead(_5);
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
|
||||
+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
|
||||
StorageDead(_4);
|
||||
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
|
||||
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
|
||||
StorageDead(_5);
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
|
||||
+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
|
||||
StorageDead(_4);
|
||||
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
|
||||
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
|
||||
StorageDead(_5);
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
|
||||
+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
|
||||
StorageDead(_4);
|
||||
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
- _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
|
||||
+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
|
||||
StorageDead(_5);
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
|
||||
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
|
||||
+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
|
||||
StorageDead(_4);
|
||||
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
_14 = const main::promoted[0];
|
||||
_4 = copy _14;
|
||||
_3 = copy _4;
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
_14 = const main::promoted[0];
|
||||
_4 = copy _14;
|
||||
_3 = copy _4;
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
_14 = const main::promoted[0];
|
||||
_4 = copy _14;
|
||||
_3 = copy _4;
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
_14 = const main::promoted[0];
|
||||
_4 = copy _14;
|
||||
_3 = copy _4;
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_3);
|
||||
StorageLive(_6);
|
||||
_6 = const 1_usize;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
+ nop;
|
||||
StorageLive(_3);
|
||||
_3 = &(*_1);
|
||||
_2 = move _3 as &[i32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_3);
|
||||
StorageLive(_4);
|
||||
_4 = &raw const (*_2);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
+ nop;
|
||||
StorageLive(_3);
|
||||
_3 = &(*_1);
|
||||
_2 = move _3 as &[i32] (PointerCoercion(Unsize));
|
||||
_2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit));
|
||||
StorageDead(_3);
|
||||
StorageLive(_4);
|
||||
_4 = &raw const (*_2);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
bb0: {
|
||||
- StorageLive(_1);
|
||||
+ nop;
|
||||
_1 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer));
|
||||
_1 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = copy _1;
|
||||
|
@ -50,7 +50,7 @@
|
|||
StorageDead(_2);
|
||||
- StorageLive(_4);
|
||||
+ nop;
|
||||
_4 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer));
|
||||
_4 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
StorageLive(_5);
|
||||
StorageLive(_6);
|
||||
_6 = copy _4;
|
||||
|
@ -69,9 +69,9 @@
|
|||
+ nop;
|
||||
StorageLive(_9);
|
||||
- _9 = copy _7;
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
StorageDead(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
|
@ -87,9 +87,9 @@
|
|||
+ nop;
|
||||
StorageLive(_13);
|
||||
- _13 = copy _7;
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
StorageDead(_13);
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
bb0: {
|
||||
- StorageLive(_1);
|
||||
+ nop;
|
||||
_1 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer));
|
||||
_1 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = copy _1;
|
||||
|
@ -50,7 +50,7 @@
|
|||
StorageDead(_2);
|
||||
- StorageLive(_4);
|
||||
+ nop;
|
||||
_4 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer));
|
||||
_4 = identity::<u8> as fn(u8) -> u8 (PointerCoercion(ReifyFnPointer, AsCast));
|
||||
StorageLive(_5);
|
||||
StorageLive(_6);
|
||||
_6 = copy _4;
|
||||
|
@ -69,9 +69,9 @@
|
|||
+ nop;
|
||||
StorageLive(_9);
|
||||
- _9 = copy _7;
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
- _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21};
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
StorageDead(_9);
|
||||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
|
@ -87,9 +87,9 @@
|
|||
+ nop;
|
||||
StorageLive(_13);
|
||||
- _13 = copy _7;
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
- _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21};
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe)));
|
||||
+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:614:19: 614:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast));
|
||||
StorageDead(_13);
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
|
|
|
@ -64,10 +64,10 @@
|
|||
_44 = const wide_ptr_provenance::promoted[1];
|
||||
_5 = &(*_44);
|
||||
_4 = &(*_5);
|
||||
_3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_4);
|
||||
_2 = &raw const (*_3);
|
||||
- _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
- StorageDead(_2);
|
||||
+ _1 = copy _2;
|
||||
+ nop;
|
||||
|
@ -82,10 +82,10 @@
|
|||
_43 = const wide_ptr_provenance::promoted[0];
|
||||
_11 = &(*_43);
|
||||
_10 = &(*_11);
|
||||
_9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
_9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
|
||||
StorageDead(_10);
|
||||
_8 = &raw const (*_9);
|
||||
- _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
- StorageDead(_8);
|
||||
+ _7 = copy _8;
|
||||
+ nop;
|
||||
|
@ -99,7 +99,7 @@
|
|||
StorageLive(_16);
|
||||
StorageLive(_17);
|
||||
- _17 = copy _7;
|
||||
- _16 = move _17 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _16 = move _17 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _17 = copy _8;
|
||||
+ _16 = copy _8;
|
||||
StorageDead(_17);
|
||||
|
@ -121,7 +121,7 @@
|
|||
StorageLive(_21);
|
||||
StorageLive(_22);
|
||||
- _22 = copy _7;
|
||||
- _21 = move _22 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _21 = move _22 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _22 = copy _8;
|
||||
+ _21 = copy _8;
|
||||
StorageDead(_22);
|
||||
|
@ -143,7 +143,7 @@
|
|||
StorageLive(_26);
|
||||
StorageLive(_27);
|
||||
- _27 = copy _7;
|
||||
- _26 = move _27 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _26 = move _27 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _27 = copy _8;
|
||||
+ _26 = copy _8;
|
||||
StorageDead(_27);
|
||||
|
@ -165,7 +165,7 @@
|
|||
StorageLive(_31);
|
||||
StorageLive(_32);
|
||||
- _32 = copy _7;
|
||||
- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _32 = copy _8;
|
||||
+ _31 = copy _8;
|
||||
StorageDead(_32);
|
||||
|
@ -187,7 +187,7 @@
|
|||
StorageLive(_36);
|
||||
StorageLive(_37);
|
||||
- _37 = copy _7;
|
||||
- _36 = move _37 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _36 = move _37 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _37 = copy _8;
|
||||
+ _36 = copy _8;
|
||||
StorageDead(_37);
|
||||
|
@ -209,7 +209,7 @@
|
|||
StorageLive(_41);
|
||||
StorageLive(_42);
|
||||
- _42 = copy _7;
|
||||
- _41 = move _42 as *const dyn std::marker::Send (PointerCoercion(Unsize));
|
||||
- _41 = move _42 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
|
||||
+ _42 = copy _8;
|
||||
+ _41 = copy _8;
|
||||
StorageDead(_42);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue