Auto merge of #108587 - matthiaskrgr:rollup-rw6po59, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #108376 (compiler/rustc_session: fix sysroot detection logic) - #108400 (add llvm cgu instructions stats to perf) - #108496 (fix #108495, postfix decrement and prefix decrement has no warning) - #108505 (Further unify validity intrinsics) - #108520 (Small cleanup to `one_bound_for_assoc_type`) - #108560 (Some `infer/mod.rs` cleanups) - #108563 (Make mailmap more correct) - #108564 (Fix `x clean` with specific paths) - #108571 (Add contains_key to SortedIndexMultiMap) - #108578 (Update Fuchsia platform team members) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
bcb610da7f
29 changed files with 342 additions and 226 deletions
2
.mailmap
2
.mailmap
|
@ -15,7 +15,7 @@ Adrien Tétar <adri-from-59@hotmail.fr>
|
||||||
Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
|
Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
|
||||||
Alan Egerton <eggyal@gmail.com>
|
Alan Egerton <eggyal@gmail.com>
|
||||||
Alan Stoate <alan.stoate@gmail.com>
|
Alan Stoate <alan.stoate@gmail.com>
|
||||||
Albert Larsan <albert.larsan@gmail.com> Albert Larsan <74931857+albertlarsan68@users.noreply.github.com>
|
Albert Larsan <albert.larsan@gmail.com> <74931857+albertlarsan68@users.noreply.github.com>
|
||||||
Alessandro Decina <alessandro.d@gmail.com>
|
Alessandro Decina <alessandro.d@gmail.com>
|
||||||
Alex Burka <durka42+github@gmail.com> Alex Burka <aburka@seas.upenn.edu>
|
Alex Burka <durka42+github@gmail.com> Alex Burka <aburka@seas.upenn.edu>
|
||||||
Alex Hansen <ahansen2@trinity.edu>
|
Alex Hansen <ahansen2@trinity.edu>
|
||||||
|
|
|
@ -3801,6 +3801,8 @@ dependencies = [
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_symbol_mangling",
|
"rustc_symbol_mangling",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) use cpuid::codegen_cpuid_call;
|
||||||
pub(crate) use llvm::codegen_llvm_intrinsic_call;
|
pub(crate) use llvm::codegen_llvm_intrinsic_call;
|
||||||
|
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::layout::{HasParamEnv, InitKind};
|
use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
|
@ -628,57 +628,39 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||||
intrinsic_args!(fx, args => (); intrinsic);
|
intrinsic_args!(fx, args => (); intrinsic);
|
||||||
|
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
let layout = fx.layout_of(ty);
|
|
||||||
if layout.abi.is_uninhabited() {
|
|
||||||
with_no_trimmed_paths!({
|
|
||||||
crate::base::codegen_panic_nounwind(
|
|
||||||
fx,
|
|
||||||
&format!("attempted to instantiate uninhabited type `{}`", layout.ty),
|
|
||||||
source_info,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if intrinsic == sym::assert_zero_valid
|
let requirement = ValidityRequirement::from_intrinsic(intrinsic);
|
||||||
&& !fx
|
|
||||||
.tcx
|
|
||||||
.check_validity_of_init((InitKind::Zero, fx.param_env().and(ty)))
|
|
||||||
.expect("expected to have layout during codegen")
|
|
||||||
{
|
|
||||||
with_no_trimmed_paths!({
|
|
||||||
crate::base::codegen_panic_nounwind(
|
|
||||||
fx,
|
|
||||||
&format!(
|
|
||||||
"attempted to zero-initialize type `{}`, which is invalid",
|
|
||||||
layout.ty
|
|
||||||
),
|
|
||||||
source_info,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if intrinsic == sym::assert_mem_uninitialized_valid
|
if let Some(requirement) = requirement {
|
||||||
&& !fx
|
let do_panic = !fx
|
||||||
.tcx
|
.tcx
|
||||||
.check_validity_of_init((
|
.check_validity_requirement((requirement, fx.param_env().and(ty)))
|
||||||
InitKind::UninitMitigated0x01Fill,
|
.expect("expect to have layout during codegen");
|
||||||
fx.param_env().and(ty),
|
|
||||||
))
|
if do_panic {
|
||||||
.expect("expected to have layout during codegen")
|
let layout = fx.layout_of(ty);
|
||||||
{
|
|
||||||
with_no_trimmed_paths!({
|
with_no_trimmed_paths!({
|
||||||
crate::base::codegen_panic_nounwind(
|
crate::base::codegen_panic_nounwind(
|
||||||
fx,
|
fx,
|
||||||
&format!(
|
&if layout.abi.is_uninhabited() {
|
||||||
"attempted to leave type `{}` uninitialized, which is invalid",
|
format!("attempted to instantiate uninhabited type `{}`", layout.ty)
|
||||||
layout.ty
|
} else if requirement == ValidityRequirement::Zero {
|
||||||
),
|
format!(
|
||||||
source_info,
|
"attempted to zero-initialize type `{}`, which is invalid",
|
||||||
)
|
layout.ty
|
||||||
});
|
)
|
||||||
return;
|
} else {
|
||||||
|
format!(
|
||||||
|
"attempted to leave type `{}` uninitialized, which is invalid",
|
||||||
|
layout.ty
|
||||||
|
)
|
||||||
|
},
|
||||||
|
source_info,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,3 +36,5 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||||
rustc_ast = { path = "../rustc_ast" }
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
rustc_span = { path = "../rustc_span" }
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
|
serde = { version = "1", features = [ "derive" ]}
|
||||||
|
serde_json = "1"
|
||||||
|
|
|
@ -761,6 +761,7 @@ pub(crate) unsafe fn codegen(
|
||||||
EmitObj::None => {}
|
EmitObj::None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record_llvm_cgu_instructions_stats(&cgcx.prof, llmod);
|
||||||
drop(handlers);
|
drop(handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,3 +975,23 @@ fn record_artifact_size(
|
||||||
self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
|
self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, llmod: &llvm::Module) {
|
||||||
|
if !prof.enabled() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_stats =
|
||||||
|
llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(&llmod, s) })
|
||||||
|
.expect("cannot get module instruction stats");
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
struct InstructionsStats {
|
||||||
|
module: String,
|
||||||
|
total: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
let InstructionsStats { module, total } =
|
||||||
|
serde_json::from_str(&raw_stats).expect("cannot parse llvm cgu instructions stats");
|
||||||
|
prof.artifact_size("cgu_instructions", module, total);
|
||||||
|
}
|
||||||
|
|
|
@ -2410,6 +2410,8 @@ extern "C" {
|
||||||
pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
|
pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
|
||||||
pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
|
pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
|
||||||
pub fn LLVMRustModuleCost(M: &Module) -> u64;
|
pub fn LLVMRustModuleCost(M: &Module) -> u64;
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
|
pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
|
||||||
|
|
||||||
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
|
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
|
||||||
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
|
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
|
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, InitKind, LayoutOf};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
|
||||||
use rustc_session::config::OptLevel;
|
use rustc_session::config::OptLevel;
|
||||||
|
@ -655,44 +655,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
// Emit a panic or a no-op for `assert_*` intrinsics.
|
// Emit a panic or a no-op for `assert_*` intrinsics.
|
||||||
// These are intrinsics that compile to panics so that we can get a message
|
// These are intrinsics that compile to panics so that we can get a message
|
||||||
// which mentions the offending type, even from a const context.
|
// which mentions the offending type, even from a const context.
|
||||||
#[derive(Debug, PartialEq)]
|
let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
|
||||||
enum AssertIntrinsic {
|
if let Some(requirement) = panic_intrinsic {
|
||||||
Inhabited,
|
|
||||||
ZeroValid,
|
|
||||||
MemUninitializedValid,
|
|
||||||
}
|
|
||||||
let panic_intrinsic = intrinsic.and_then(|i| match i {
|
|
||||||
sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
|
|
||||||
sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
|
|
||||||
sym::assert_mem_uninitialized_valid => Some(AssertIntrinsic::MemUninitializedValid),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
if let Some(intrinsic) = panic_intrinsic {
|
|
||||||
use AssertIntrinsic::*;
|
|
||||||
|
|
||||||
let ty = instance.unwrap().substs.type_at(0);
|
let ty = instance.unwrap().substs.type_at(0);
|
||||||
|
|
||||||
|
let do_panic = !bx
|
||||||
|
.tcx()
|
||||||
|
.check_validity_requirement((requirement, bx.param_env().and(ty)))
|
||||||
|
.expect("expect to have layout during codegen");
|
||||||
|
|
||||||
let layout = bx.layout_of(ty);
|
let layout = bx.layout_of(ty);
|
||||||
let do_panic = match intrinsic {
|
|
||||||
Inhabited => layout.abi.is_uninhabited(),
|
|
||||||
ZeroValid => !bx
|
|
||||||
.tcx()
|
|
||||||
.check_validity_of_init((InitKind::Zero, bx.param_env().and(ty)))
|
|
||||||
.expect("expected to have layout during codegen"),
|
|
||||||
MemUninitializedValid => !bx
|
|
||||||
.tcx()
|
|
||||||
.check_validity_of_init((
|
|
||||||
InitKind::UninitMitigated0x01Fill,
|
|
||||||
bx.param_env().and(ty),
|
|
||||||
))
|
|
||||||
.expect("expected to have layout during codegen"),
|
|
||||||
};
|
|
||||||
Some(if do_panic {
|
Some(if do_panic {
|
||||||
let msg_str = with_no_visible_paths!({
|
let msg_str = with_no_visible_paths!({
|
||||||
with_no_trimmed_paths!({
|
with_no_trimmed_paths!({
|
||||||
if layout.abi.is_uninhabited() {
|
if layout.abi.is_uninhabited() {
|
||||||
// Use this error even for the other intrinsics as it is more precise.
|
// Use this error even for the other intrinsics as it is more precise.
|
||||||
format!("attempted to instantiate uninhabited type `{}`", ty)
|
format!("attempted to instantiate uninhabited type `{}`", ty)
|
||||||
} else if intrinsic == ZeroValid {
|
} else if requirement == ValidityRequirement::Zero {
|
||||||
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
|
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::mir::{
|
||||||
BinOp, NonDivergingIntrinsic,
|
BinOp, NonDivergingIntrinsic,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::layout::{InitKind, LayoutOf as _};
|
use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
@ -418,57 +418,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
| sym::assert_zero_valid
|
| sym::assert_zero_valid
|
||||||
| sym::assert_mem_uninitialized_valid => {
|
| sym::assert_mem_uninitialized_valid => {
|
||||||
let ty = instance.substs.type_at(0);
|
let ty = instance.substs.type_at(0);
|
||||||
let layout = self.layout_of(ty)?;
|
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
|
||||||
|
|
||||||
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
|
let should_panic = !self
|
||||||
// error message.
|
.tcx
|
||||||
if layout.abi.is_uninhabited() {
|
.check_validity_requirement((requirement, self.param_env.and(ty)))
|
||||||
// The run-time intrinsic panics just to get a good backtrace; here we abort
|
.map_err(|_| err_inval!(TooGeneric))?;
|
||||||
// since there is no problem showing a backtrace even for aborts.
|
|
||||||
M::abort(
|
if should_panic {
|
||||||
self,
|
let layout = self.layout_of(ty)?;
|
||||||
format!(
|
|
||||||
|
let msg = match requirement {
|
||||||
|
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
|
||||||
|
// error message.
|
||||||
|
_ if layout.abi.is_uninhabited() => format!(
|
||||||
"aborted execution: attempted to instantiate uninhabited type `{}`",
|
"aborted execution: attempted to instantiate uninhabited type `{}`",
|
||||||
ty
|
ty
|
||||||
),
|
),
|
||||||
)?;
|
ValidityRequirement::Inhabited => bug!("handled earlier"),
|
||||||
}
|
ValidityRequirement::Zero => format!(
|
||||||
|
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
|
||||||
|
ty
|
||||||
|
),
|
||||||
|
ValidityRequirement::UninitMitigated0x01Fill => format!(
|
||||||
|
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
|
||||||
|
ty
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
if intrinsic_name == sym::assert_zero_valid {
|
M::abort(self, msg)?;
|
||||||
let should_panic = !self
|
|
||||||
.tcx
|
|
||||||
.check_validity_of_init((InitKind::Zero, self.param_env.and(ty)))
|
|
||||||
.map_err(|_| err_inval!(TooGeneric))?;
|
|
||||||
|
|
||||||
if should_panic {
|
|
||||||
M::abort(
|
|
||||||
self,
|
|
||||||
format!(
|
|
||||||
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
|
|
||||||
ty
|
|
||||||
),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if intrinsic_name == sym::assert_mem_uninitialized_valid {
|
|
||||||
let should_panic = !self
|
|
||||||
.tcx
|
|
||||||
.check_validity_of_init((
|
|
||||||
InitKind::UninitMitigated0x01Fill,
|
|
||||||
self.param_env.and(ty),
|
|
||||||
))
|
|
||||||
.map_err(|_| err_inval!(TooGeneric))?;
|
|
||||||
|
|
||||||
if should_panic {
|
|
||||||
M::abort(
|
|
||||||
self,
|
|
||||||
format!(
|
|
||||||
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
|
|
||||||
ty
|
|
||||||
),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::simd_insert => {
|
sym::simd_insert => {
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
let (param_env, value) = param_env_and_value.into_parts();
|
let (param_env, value) = param_env_and_value.into_parts();
|
||||||
const_eval::deref_mir_constant(tcx, param_env, value)
|
const_eval::deref_mir_constant(tcx, param_env, value)
|
||||||
};
|
};
|
||||||
providers.check_validity_of_init = |tcx, (init_kind, param_env_and_ty)| {
|
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
|
||||||
util::might_permit_raw_init(tcx, init_kind, param_env_and_ty)
|
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustc_middle::ty::layout::{InitKind, LayoutCx, LayoutError, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
|
||||||
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
|
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
|
||||||
|
@ -18,16 +18,23 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
|
||||||
/// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to
|
/// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to
|
||||||
/// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and
|
/// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and
|
||||||
/// to the full uninit check).
|
/// to the full uninit check).
|
||||||
pub fn might_permit_raw_init<'tcx>(
|
pub fn check_validity_requirement<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
kind: InitKind,
|
kind: ValidityRequirement,
|
||||||
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||||
) -> Result<bool, LayoutError<'tcx>> {
|
) -> Result<bool, LayoutError<'tcx>> {
|
||||||
|
let layout = tcx.layout_of(param_env_and_ty)?;
|
||||||
|
|
||||||
|
// There is nothing strict or lax about inhabitedness.
|
||||||
|
if kind == ValidityRequirement::Inhabited {
|
||||||
|
return Ok(!layout.abi.is_uninhabited());
|
||||||
|
}
|
||||||
|
|
||||||
if tcx.sess.opts.unstable_opts.strict_init_checks {
|
if tcx.sess.opts.unstable_opts.strict_init_checks {
|
||||||
might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind)
|
might_permit_raw_init_strict(layout, tcx, kind)
|
||||||
} else {
|
} else {
|
||||||
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
|
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
|
||||||
might_permit_raw_init_lax(tcx.layout_of(param_env_and_ty)?, &layout_cx, kind)
|
might_permit_raw_init_lax(layout, &layout_cx, kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +43,7 @@ pub fn might_permit_raw_init<'tcx>(
|
||||||
fn might_permit_raw_init_strict<'tcx>(
|
fn might_permit_raw_init_strict<'tcx>(
|
||||||
ty: TyAndLayout<'tcx>,
|
ty: TyAndLayout<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
kind: InitKind,
|
kind: ValidityRequirement,
|
||||||
) -> Result<bool, LayoutError<'tcx>> {
|
) -> Result<bool, LayoutError<'tcx>> {
|
||||||
let machine = CompileTimeInterpreter::new(
|
let machine = CompileTimeInterpreter::new(
|
||||||
Limit::new(0),
|
Limit::new(0),
|
||||||
|
@ -50,7 +57,7 @@ fn might_permit_raw_init_strict<'tcx>(
|
||||||
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
|
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
|
||||||
.expect("OOM: failed to allocate for uninit check");
|
.expect("OOM: failed to allocate for uninit check");
|
||||||
|
|
||||||
if kind == InitKind::Zero {
|
if kind == ValidityRequirement::Zero {
|
||||||
cx.write_bytes_ptr(
|
cx.write_bytes_ptr(
|
||||||
allocated.ptr,
|
allocated.ptr,
|
||||||
std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
|
std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
|
||||||
|
@ -72,15 +79,18 @@ fn might_permit_raw_init_strict<'tcx>(
|
||||||
fn might_permit_raw_init_lax<'tcx>(
|
fn might_permit_raw_init_lax<'tcx>(
|
||||||
this: TyAndLayout<'tcx>,
|
this: TyAndLayout<'tcx>,
|
||||||
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
|
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
|
||||||
init_kind: InitKind,
|
init_kind: ValidityRequirement,
|
||||||
) -> Result<bool, LayoutError<'tcx>> {
|
) -> Result<bool, LayoutError<'tcx>> {
|
||||||
let scalar_allows_raw_init = move |s: Scalar| -> bool {
|
let scalar_allows_raw_init = move |s: Scalar| -> bool {
|
||||||
match init_kind {
|
match init_kind {
|
||||||
InitKind::Zero => {
|
ValidityRequirement::Inhabited => {
|
||||||
|
bug!("ValidityRequirement::Inhabited should have been handled above")
|
||||||
|
}
|
||||||
|
ValidityRequirement::Zero => {
|
||||||
// The range must contain 0.
|
// The range must contain 0.
|
||||||
s.valid_range(cx).contains(0)
|
s.valid_range(cx).contains(0)
|
||||||
}
|
}
|
||||||
InitKind::UninitMitigated0x01Fill => {
|
ValidityRequirement::UninitMitigated0x01Fill => {
|
||||||
// The range must include an 0x01-filled buffer.
|
// The range must include an 0x01-filled buffer.
|
||||||
let mut val: u128 = 0x01;
|
let mut val: u128 = 0x01;
|
||||||
for _ in 1..s.size(cx).bytes() {
|
for _ in 1..s.size(cx).bytes() {
|
|
@ -1,14 +1,14 @@
|
||||||
mod alignment;
|
mod alignment;
|
||||||
mod call_kind;
|
mod call_kind;
|
||||||
|
mod check_validity_requirement;
|
||||||
pub mod collect_writes;
|
pub mod collect_writes;
|
||||||
mod compare_types;
|
mod compare_types;
|
||||||
mod find_self_call;
|
mod find_self_call;
|
||||||
mod might_permit_raw_init;
|
|
||||||
mod type_name;
|
mod type_name;
|
||||||
|
|
||||||
pub use self::alignment::is_disaligned;
|
pub use self::alignment::is_disaligned;
|
||||||
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
|
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
|
||||||
|
pub use self::check_validity_requirement::check_validity_requirement;
|
||||||
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
|
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
|
||||||
pub use self::find_self_call::find_self_call;
|
pub use self::find_self_call::find_self_call;
|
||||||
pub use self::might_permit_raw_init::might_permit_raw_init;
|
|
||||||
pub use self::type_name::type_name;
|
pub use self::type_name::type_name;
|
||||||
|
|
|
@ -100,6 +100,11 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
|
||||||
(k == &key).then_some((i, v))
|
(k == &key).then_some((i, v))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_key(&self, key: K) -> bool {
|
||||||
|
self.get_by_key(key).next().is_some()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}
|
impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}
|
||||||
|
|
|
@ -17,6 +17,10 @@ fn test_sorted_index_multi_map() {
|
||||||
assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
|
assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
|
||||||
assert!(set.get_by_key(4).next().is_none());
|
assert!(set.get_by_key(4).next().is_none());
|
||||||
|
|
||||||
|
// `contains_key` works
|
||||||
|
assert!(set.contains_key(3));
|
||||||
|
assert!(!set.contains_key(4));
|
||||||
|
|
||||||
// `get_by_key` returns items in insertion order.
|
// `get_by_key` returns items in insertion order.
|
||||||
let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
|
let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
|
||||||
let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
|
let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
|
||||||
|
|
|
@ -50,6 +50,7 @@ use rustc_trait_selection::traits::{self, astconv_object_safety_violations, Obli
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1095,11 +1096,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
// those that do.
|
// those that do.
|
||||||
self.one_bound_for_assoc_type(
|
self.one_bound_for_assoc_type(
|
||||||
|| traits::supertraits(tcx, trait_ref),
|
|| traits::supertraits(tcx, trait_ref),
|
||||||
|| trait_ref.print_only_trait_path().to_string(),
|
trait_ref.print_only_trait_path(),
|
||||||
binding.item_name,
|
binding.item_name,
|
||||||
path_span,
|
path_span,
|
||||||
|| match binding.kind {
|
match binding.kind {
|
||||||
ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
|
ConvertedBindingKind::Equality(term) => Some(term),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
)?
|
)?
|
||||||
|
@ -1789,10 +1790,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
assoc_name,
|
assoc_name,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|| param_name.to_string(),
|
param_name,
|
||||||
assoc_name,
|
assoc_name,
|
||||||
span,
|
span,
|
||||||
|| None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1802,10 +1803,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
fn one_bound_for_assoc_type<I>(
|
fn one_bound_for_assoc_type<I>(
|
||||||
&self,
|
&self,
|
||||||
all_candidates: impl Fn() -> I,
|
all_candidates: impl Fn() -> I,
|
||||||
ty_param_name: impl Fn() -> String,
|
ty_param_name: impl Display,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
span: Span,
|
span: Span,
|
||||||
is_equality: impl Fn() -> Option<String>,
|
is_equality: Option<ty::Term<'tcx>>,
|
||||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
|
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
|
@ -1821,7 +1822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
let reported = self.complain_about_assoc_type_not_found(
|
let reported = self.complain_about_assoc_type_not_found(
|
||||||
all_candidates,
|
all_candidates,
|
||||||
&ty_param_name(),
|
&ty_param_name.to_string(),
|
||||||
assoc_name,
|
assoc_name,
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
|
@ -1833,7 +1834,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
if let Some(bound2) = next_cand {
|
if let Some(bound2) = next_cand {
|
||||||
debug!(?bound2);
|
debug!(?bound2);
|
||||||
|
|
||||||
let is_equality = is_equality();
|
|
||||||
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
|
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
|
||||||
let mut err = if is_equality.is_some() {
|
let mut err = if is_equality.is_some() {
|
||||||
// More specific Error Index entry.
|
// More specific Error Index entry.
|
||||||
|
@ -1843,7 +1843,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
E0222,
|
E0222,
|
||||||
"ambiguous associated type `{}` in bounds of `{}`",
|
"ambiguous associated type `{}` in bounds of `{}`",
|
||||||
assoc_name,
|
assoc_name,
|
||||||
ty_param_name()
|
ty_param_name
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
|
@ -1852,7 +1852,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
E0221,
|
E0221,
|
||||||
"ambiguous associated type `{}` in bounds of `{}`",
|
"ambiguous associated type `{}` in bounds of `{}`",
|
||||||
assoc_name,
|
assoc_name,
|
||||||
ty_param_name()
|
ty_param_name
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
|
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
|
||||||
|
@ -1886,18 +1886,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span.with_hi(assoc_name.span.lo()),
|
span.with_hi(assoc_name.span.lo()),
|
||||||
"use fully qualified syntax to disambiguate",
|
"use fully qualified syntax to disambiguate",
|
||||||
format!(
|
format!("<{} as {}>::", ty_param_name, bound.print_only_trait_path()),
|
||||||
"<{} as {}>::",
|
|
||||||
ty_param_name(),
|
|
||||||
bound.print_only_trait_path(),
|
|
||||||
),
|
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err.note(&format!(
|
err.note(&format!(
|
||||||
"associated type `{}` could derive from `{}`",
|
"associated type `{}` could derive from `{}`",
|
||||||
ty_param_name(),
|
ty_param_name,
|
||||||
bound.print_only_trait_path(),
|
bound.print_only_trait_path(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1906,7 +1902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
err.help(&format!(
|
err.help(&format!(
|
||||||
"consider introducing a new type parameter `T` and adding `where` constraints:\
|
"consider introducing a new type parameter `T` and adding `where` constraints:\
|
||||||
\n where\n T: {},\n{}",
|
\n where\n T: {},\n{}",
|
||||||
ty_param_name(),
|
ty_param_name,
|
||||||
where_bounds.join(",\n"),
|
where_bounds.join(",\n"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -2070,10 +2066,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
|
|
||||||
self.one_bound_for_assoc_type(
|
self.one_bound_for_assoc_type(
|
||||||
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
|
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
|
||||||
|| "Self".to_string(),
|
kw::SelfUpper,
|
||||||
assoc_ident,
|
assoc_ident,
|
||||||
span,
|
span,
|
||||||
|| None,
|
None,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
|
@ -156,7 +156,7 @@ pub struct InferCtxtInner<'tcx> {
|
||||||
undo_log: InferCtxtUndoLogs<'tcx>,
|
undo_log: InferCtxtUndoLogs<'tcx>,
|
||||||
|
|
||||||
/// Caches for opaque type inference.
|
/// Caches for opaque type inference.
|
||||||
pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
|
opaque_type_storage: OpaqueTypeStorage<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> InferCtxtInner<'tcx> {
|
impl<'tcx> InferCtxtInner<'tcx> {
|
||||||
|
@ -195,41 +195,17 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn int_unification_table(
|
fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
|
||||||
&mut self,
|
|
||||||
) -> ut::UnificationTable<
|
|
||||||
ut::InPlace<
|
|
||||||
ty::IntVid,
|
|
||||||
&mut ut::UnificationStorage<ty::IntVid>,
|
|
||||||
&mut InferCtxtUndoLogs<'tcx>,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
self.int_unification_storage.with_log(&mut self.undo_log)
|
self.int_unification_storage.with_log(&mut self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn float_unification_table(
|
fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
|
||||||
&mut self,
|
|
||||||
) -> ut::UnificationTable<
|
|
||||||
ut::InPlace<
|
|
||||||
ty::FloatVid,
|
|
||||||
&mut ut::UnificationStorage<ty::FloatVid>,
|
|
||||||
&mut InferCtxtUndoLogs<'tcx>,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
self.float_unification_storage.with_log(&mut self.undo_log)
|
self.float_unification_storage.with_log(&mut self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn const_unification_table(
|
fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::ConstVid<'tcx>> {
|
||||||
&mut self,
|
|
||||||
) -> ut::UnificationTable<
|
|
||||||
ut::InPlace<
|
|
||||||
ty::ConstVid<'tcx>,
|
|
||||||
&mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
|
|
||||||
&mut InferCtxtUndoLogs<'tcx>,
|
|
||||||
>,
|
|
||||||
> {
|
|
||||||
self.const_unification_storage.with_log(&mut self.undo_log)
|
self.const_unification_storage.with_log(&mut self.undo_log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,17 +1405,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to resolve all type/region/const variables in
|
||||||
|
/// `value`. Region inference must have been run already (e.g.,
|
||||||
|
/// by calling `resolve_regions_and_report_errors`). If some
|
||||||
|
/// variable was never unified, an `Err` results.
|
||||||
|
///
|
||||||
|
/// This method is idempotent, but it not typically not invoked
|
||||||
|
/// except during the writeback phase.
|
||||||
pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<'tcx, T> {
|
pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<'tcx, T> {
|
||||||
/*!
|
|
||||||
* Attempts to resolve all type/region/const variables in
|
|
||||||
* `value`. Region inference must have been run already (e.g.,
|
|
||||||
* by calling `resolve_regions_and_report_errors`). If some
|
|
||||||
* variable was never unified, an `Err` results.
|
|
||||||
*
|
|
||||||
* This method is idempotent, but it not typically not invoked
|
|
||||||
* except during the writeback phase.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let value = resolve::fully_resolve(self, value);
|
let value = resolve::fully_resolve(self, value);
|
||||||
assert!(
|
assert!(
|
||||||
value.as_ref().map_or(true, |value| !value.needs_infer()),
|
value.as_ref().map_or(true, |value| !value.needs_infer()),
|
||||||
|
@ -1754,7 +1727,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
// in this case. The typechecker should only ever report type errors involving mismatched
|
// in this case. The typechecker should only ever report type errors involving mismatched
|
||||||
// types using one of these methods, and should not call span_err directly for such
|
// types using one of these methods, and should not call span_err directly for such
|
||||||
// errors.
|
// errors.
|
||||||
|
|
||||||
pub fn type_error_struct_with_diag<M>(
|
pub fn type_error_struct_with_diag<M>(
|
||||||
&self,
|
&self,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
|
#include "llvm/Support/JSON.h"
|
||||||
#include "llvm/Support/Host.h"
|
#include "llvm/Support/Host.h"
|
||||||
#include "llvm/Support/Memory.h"
|
#include "llvm/Support/Memory.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
|
|
@ -1751,6 +1751,19 @@ LLVMRustModuleCost(LLVMModuleRef M) {
|
||||||
return std::distance(std::begin(f), std::end(f));
|
return std::distance(std::begin(f), std::end(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str)
|
||||||
|
{
|
||||||
|
RawRustStringOstream OS(Str);
|
||||||
|
llvm::json::OStream JOS(OS);
|
||||||
|
auto Module = unwrap(M);
|
||||||
|
|
||||||
|
JOS.object([&] {
|
||||||
|
JOS.attribute("module", Module->getName());
|
||||||
|
JOS.attribute("total", Module->getInstructionCount());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Vector reductions:
|
// Vector reductions:
|
||||||
extern "C" LLVMValueRef
|
extern "C" LLVMValueRef
|
||||||
LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
|
LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::infer::canonical::Canonical;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
use crate::ty::fast_reject::SimplifiedType;
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use crate::ty::layout::{InitKind, TyAndLayout};
|
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
|
||||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||||
|
@ -698,7 +698,7 @@ impl Key for HirId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
|
impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
|
||||||
type CacheSelector = DefaultCacheSelector<Self>;
|
type CacheSelector = DefaultCacheSelector<Self>;
|
||||||
|
|
||||||
// Just forward to `Ty<'tcx>`
|
// Just forward to `Ty<'tcx>`
|
||||||
|
|
|
@ -2166,8 +2166,8 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
query check_validity_of_init(key: (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
|
query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
|
||||||
desc { "checking to see if `{}` permits being left {}", key.1.value, key.0 }
|
desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
query compare_impl_const(
|
query compare_impl_const(
|
||||||
|
|
|
@ -7,6 +7,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_session::config::OptLevel;
|
use rustc_session::config::OptLevel;
|
||||||
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::abi::*;
|
use rustc_target::abi::*;
|
||||||
|
@ -172,16 +173,29 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
|
||||||
/// Used in `might_permit_raw_init` to indicate the kind of initialisation
|
/// Used in `might_permit_raw_init` to indicate the kind of initialisation
|
||||||
/// that is checked to be valid
|
/// that is checked to be valid
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||||
pub enum InitKind {
|
pub enum ValidityRequirement {
|
||||||
|
Inhabited,
|
||||||
Zero,
|
Zero,
|
||||||
UninitMitigated0x01Fill,
|
UninitMitigated0x01Fill,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for InitKind {
|
impl ValidityRequirement {
|
||||||
|
pub fn from_intrinsic(intrinsic: Symbol) -> Option<Self> {
|
||||||
|
match intrinsic {
|
||||||
|
sym::assert_inhabited => Some(Self::Inhabited),
|
||||||
|
sym::assert_zero_valid => Some(Self::Zero),
|
||||||
|
sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ValidityRequirement {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Zero => f.write_str("zeroed"),
|
Self::Inhabited => f.write_str("is inhabited"),
|
||||||
Self::UninitMitigated0x01Fill => f.write_str("filled with 0x01"),
|
Self::Zero => f.write_str("allows being left zeroed"),
|
||||||
|
Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::traits::specialization_graph;
|
||||||
use crate::traits::{self, ImplSource};
|
use crate::traits::{self, ImplSource};
|
||||||
use crate::ty::context::TyCtxtFeed;
|
use crate::ty::context::TyCtxtFeed;
|
||||||
use crate::ty::fast_reject::SimplifiedType;
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use crate::ty::layout::InitKind;
|
use crate::ty::layout::ValidityRequirement;
|
||||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::util::AlwaysRequiresDrop;
|
use crate::ty::util::AlwaysRequiresDrop;
|
||||||
use crate::ty::GeneratorDiagnosticData;
|
use crate::ty::GeneratorDiagnosticData;
|
||||||
|
|
|
@ -6,9 +6,9 @@ use rustc_middle::mir::{
|
||||||
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
|
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
|
||||||
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
|
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::InitKind;
|
use rustc_middle::ty::layout::ValidityRequirement;
|
||||||
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
|
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::Symbol;
|
||||||
|
|
||||||
pub struct InstCombine;
|
pub struct InstCombine;
|
||||||
|
|
||||||
|
@ -256,16 +256,8 @@ fn intrinsic_assert_panics<'tcx>(
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
intrinsic_name: Symbol,
|
intrinsic_name: Symbol,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
Some(match intrinsic_name {
|
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
|
||||||
sym::assert_inhabited => tcx.layout_of(param_env.and(ty)).ok()?.abi.is_uninhabited(),
|
Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
|
||||||
sym::assert_zero_valid => {
|
|
||||||
!tcx.check_validity_of_init((InitKind::Zero, param_env.and(ty))).ok()?
|
|
||||||
}
|
|
||||||
sym::assert_mem_uninitialized_valid => !tcx
|
|
||||||
.check_validity_of_init((InitKind::UninitMitigated0x01Fill, param_env.and(ty)))
|
|
||||||
.ok()?,
|
|
||||||
_ => return None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_rust_intrinsic<'tcx>(
|
fn resolve_rust_intrinsic<'tcx>(
|
||||||
|
|
|
@ -165,8 +165,6 @@ enum IsStandalone {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
enum IncOrDec {
|
enum IncOrDec {
|
||||||
Inc,
|
Inc,
|
||||||
// FIXME: `i--` recovery isn't implemented yet
|
|
||||||
#[allow(dead_code)]
|
|
||||||
Dec,
|
Dec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,6 +1355,20 @@ impl<'a> Parser<'a> {
|
||||||
self.recover_from_inc_dec(operand_expr, kind, op_span)
|
self.recover_from_inc_dec(operand_expr, kind, op_span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn recover_from_postfix_decrement(
|
||||||
|
&mut self,
|
||||||
|
operand_expr: P<Expr>,
|
||||||
|
op_span: Span,
|
||||||
|
start_stmt: bool,
|
||||||
|
) -> PResult<'a, P<Expr>> {
|
||||||
|
let kind = IncDecRecovery {
|
||||||
|
standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
|
||||||
|
op: IncOrDec::Dec,
|
||||||
|
fixity: UnaryFixity::Post,
|
||||||
|
};
|
||||||
|
self.recover_from_inc_dec(operand_expr, kind, op_span)
|
||||||
|
}
|
||||||
|
|
||||||
fn recover_from_inc_dec(
|
fn recover_from_inc_dec(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: P<Expr>,
|
base: P<Expr>,
|
||||||
|
|
|
@ -282,6 +282,18 @@ impl<'a> Parser<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.prev_token == token::BinOp(token::Minus)
|
||||||
|
&& self.token == token::BinOp(token::Minus)
|
||||||
|
&& self.prev_token.span.between(self.token.span).is_empty()
|
||||||
|
&& !self.look_ahead(1, |tok| tok.can_begin_expr())
|
||||||
|
{
|
||||||
|
let op_span = self.prev_token.span.to(self.token.span);
|
||||||
|
// Eat the second `-`
|
||||||
|
self.bump();
|
||||||
|
lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let op = op.node;
|
let op = op.node;
|
||||||
// Special cases:
|
// Special cases:
|
||||||
if op == AssocOp::As {
|
if op == AssocOp::As {
|
||||||
|
|
|
@ -182,7 +182,17 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
|
||||||
if dir.ends_with(crate::config::host_triple()) {
|
if dir.ends_with(crate::config::host_triple()) {
|
||||||
dir.parent() // chop off `$target`
|
dir.parent() // chop off `$target`
|
||||||
.and_then(|p| p.parent()) // chop off `rustlib`
|
.and_then(|p| p.parent()) // chop off `rustlib`
|
||||||
.and_then(|p| p.parent()) // chop off `lib`
|
.and_then(|p| {
|
||||||
|
// chop off `lib` (this could be also $arch dir if the host sysroot uses a
|
||||||
|
// multi-arch layout like Debian or Ubuntu)
|
||||||
|
match p.parent() {
|
||||||
|
Some(p) => match p.file_name() {
|
||||||
|
Some(f) if f == "lib" => p.parent(), // first chop went for $arch, so chop again for `lib`
|
||||||
|
_ => Some(p),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(|s| s.to_owned())
|
.map(|s| s.to_owned())
|
||||||
.ok_or(format!(
|
.ok_or(format!(
|
||||||
"Could not move 3 levels upper using `parent()` on {}",
|
"Could not move 3 levels upper using `parent()` on {}",
|
||||||
|
|
|
@ -62,6 +62,7 @@ macro_rules! clean_crate_tree {
|
||||||
let target = compiler.host;
|
let target = compiler.host;
|
||||||
let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean");
|
let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean");
|
||||||
for krate in &*self.crates {
|
for krate in &*self.crates {
|
||||||
|
cargo.arg("-p");
|
||||||
cargo.arg(krate);
|
cargo.arg(krate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ The [Fuchsia team]:
|
||||||
- Tyler Mandry ([@tmandry](https://github.com/tmandry))
|
- Tyler Mandry ([@tmandry](https://github.com/tmandry))
|
||||||
- Dan Johnson ([@computerdruid](https://github.com/computerdruid))
|
- Dan Johnson ([@computerdruid](https://github.com/computerdruid))
|
||||||
- David Koloski ([@djkoloski](https://github.com/djkoloski))
|
- David Koloski ([@djkoloski](https://github.com/djkoloski))
|
||||||
- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
|
|
||||||
- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
|
- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
|
||||||
|
|
||||||
As the team evolves over time, the specific members listed here may differ from
|
As the team evolves over time, the specific members listed here may differ from
|
||||||
|
|
39
tests/ui/parser/issue-108495-dec.rs
Normal file
39
tests/ui/parser/issue-108495-dec.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
fn test0() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = i + i--; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
// won't suggest since we can not handle the precedences
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test1() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = i-- + i--; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = --i + i--; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test3() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = i-- + --i; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test4() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = (1 + 2 + i)--; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test5() {
|
||||||
|
let mut i = 0;
|
||||||
|
let _ = (i-- + 1) + 2; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test6(){
|
||||||
|
let i=10;
|
||||||
|
while i != 0 {
|
||||||
|
i--; //~ ERROR Rust has no postfix decrement operator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
69
tests/ui/parser/issue-108495-dec.stderr
Normal file
69
tests/ui/parser/issue-108495-dec.stderr
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:3:18
|
||||||
|
|
|
||||||
|
LL | let _ = i + i--;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:9:14
|
||||||
|
|
|
||||||
|
LL | let _ = i-- + i--;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
|
||||||
|
help: use `-= 1` instead
|
||||||
|
|
|
||||||
|
LL | let _ = { let tmp = i; i -= 1; tmp } + i--;
|
||||||
|
| +++++++++++ ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:14:20
|
||||||
|
|
|
||||||
|
LL | let _ = --i + i--;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:19:14
|
||||||
|
|
|
||||||
|
LL | let _ = i-- + --i;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
|
||||||
|
help: use `-= 1` instead
|
||||||
|
|
|
||||||
|
LL | let _ = { let tmp = i; i -= 1; tmp } + --i;
|
||||||
|
| +++++++++++ ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:24:24
|
||||||
|
|
|
||||||
|
LL | let _ = (1 + 2 + i)--;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
|
||||||
|
help: use `-= 1` instead
|
||||||
|
|
|
||||||
|
LL | let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) -= 1; tmp };
|
||||||
|
| +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:29:15
|
||||||
|
|
|
||||||
|
LL | let _ = (i-- + 1) + 2;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
|
||||||
|
help: use `-= 1` instead
|
||||||
|
|
|
||||||
|
LL | let _ = ({ let tmp = i; i -= 1; tmp } + 1) + 2;
|
||||||
|
| +++++++++++ ~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: Rust has no postfix decrement operator
|
||||||
|
--> $DIR/issue-108495-dec.rs:35:10
|
||||||
|
|
|
||||||
|
LL | i--;
|
||||||
|
| ^^ not a valid postfix operator
|
||||||
|
|
|
||||||
|
help: use `-= 1` instead
|
||||||
|
|
|
||||||
|
LL | i -= 1;
|
||||||
|
| ~~~~
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue