1
Fork 0

Auto merge of #96369 - matthiaskrgr:rollup-q18w4v2, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #95395 (Better error message for `_` in function signature in `impl Trait for Ty`)
 - #96090 (Implement MIR opt unit tests)
 - #96107 ([test] Add test cases for untested functions for VecDeque)
 - #96212 (Use revisions instead of nll compare mode for `/regions/` ui tests)
 - #96215 (Drop support for legacy PM with LLVM 15)
 - #96366 (bootstrap: Remove dead code in rustdoc shim)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-04-24 22:20:56 +00:00
commit 1f631e8e93
206 changed files with 1602 additions and 621 deletions

View file

@ -625,7 +625,7 @@ pub(crate) fn run_pass_manager(
if thin { if thin {
llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm); llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
} else { } else {
llvm::LLVMPassManagerBuilderPopulateLTOPassManager( llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager(
b, pm, /* Internalize = */ False, /* RunInliner = */ True, b, pm, /* Internalize = */ False, /* RunInliner = */ True,
); );
} }

View file

@ -523,6 +523,12 @@ pub(crate) unsafe fn optimize(
let module_name = module.name.clone(); let module_name = module.name.clone();
let module_name = Some(&module_name[..]); let module_name = Some(&module_name[..]);
if let Some(false) = config.new_llvm_pass_manager && llvm_util::get_version() >= (15, 0, 0) {
diag_handler.warn(
"ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported with LLVM 15",
);
}
if config.emit_no_opt_bc { if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
let out = path_to_c_string(&out); let out = path_to_c_string(&out);
@ -628,8 +634,8 @@ pub(crate) unsafe fn optimize(
extra_passes.as_ptr(), extra_passes.as_ptr(),
extra_passes.len() as size_t, extra_passes.len() as size_t,
); );
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); llvm::LLVMRustPassManagerBuilderPopulateFunctionPassManager(b, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); llvm::LLVMRustPassManagerBuilderPopulateModulePassManager(b, mpm);
}); });
have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto; have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
@ -1085,7 +1091,7 @@ pub unsafe fn with_llvm_pmb(
// Create the PassManagerBuilder for LLVM. We configure it with // Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass // reasonable defaults and prepare it to actually populate the pass
// manager. // manager.
let builder = llvm::LLVMPassManagerBuilderCreate(); let builder = llvm::LLVMRustPassManagerBuilderCreate();
let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1); let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1);
let inline_threshold = config.inline_threshold; let inline_threshold = config.inline_threshold;
let pgo_gen_path = get_pgo_gen_path(config); let pgo_gen_path = get_pgo_gen_path(config);
@ -1102,14 +1108,9 @@ pub unsafe fn with_llvm_pmb(
pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
opt_size as c_int,
); );
llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32);
if opt_size != llvm::CodeGenOptSizeNone {
llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(builder, 1);
}
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins); llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
// Here we match what clang does (kinda). For O0 we only inline // Here we match what clang does (kinda). For O0 we only inline
@ -1118,16 +1119,16 @@ pub unsafe fn with_llvm_pmb(
// thresholds copied from clang. // thresholds copied from clang.
match (opt_level, opt_size, inline_threshold) { match (opt_level, opt_size, inline_threshold) {
(.., Some(t)) => { (.., Some(t)) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t); llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, t);
} }
(llvm::CodeGenOptLevel::Aggressive, ..) => { (llvm::CodeGenOptLevel::Aggressive, ..) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 275);
} }
(_, llvm::CodeGenOptSizeDefault, _) => { (_, llvm::CodeGenOptSizeDefault, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 75); llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 75);
} }
(_, llvm::CodeGenOptSizeAggressive, _) => { (_, llvm::CodeGenOptSizeAggressive, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25); llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 25);
} }
(llvm::CodeGenOptLevel::None, ..) => { (llvm::CodeGenOptLevel::None, ..) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
@ -1136,12 +1137,12 @@ pub unsafe fn with_llvm_pmb(
llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
} }
(llvm::CodeGenOptLevel::Default, ..) => { (llvm::CodeGenOptLevel::Default, ..) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225); llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 225);
} }
} }
f(builder); f(builder);
llvm::LLVMPassManagerBuilderDispose(builder); llvm::LLVMRustPassManagerBuilderDispose(builder);
} }
// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`. // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.

View file

@ -1825,24 +1825,22 @@ extern "C" {
pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);
pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; pub fn LLVMRustPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); pub fn LLVMRustPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder);
pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool); pub fn LLVMRustPassManagerBuilderUseInlinerWithThreshold(
pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: &PassManagerBuilder, Value: Bool);
pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(
PMB: &PassManagerBuilder, PMB: &PassManagerBuilder,
threshold: c_uint, threshold: c_uint,
); );
pub fn LLVMPassManagerBuilderPopulateModulePassManager( pub fn LLVMRustPassManagerBuilderPopulateModulePassManager(
PMB: &PassManagerBuilder, PMB: &PassManagerBuilder,
PM: &PassManager<'_>, PM: &PassManager<'_>,
); );
pub fn LLVMPassManagerBuilderPopulateFunctionPassManager( pub fn LLVMRustPassManagerBuilderPopulateFunctionPassManager(
PMB: &PassManagerBuilder, PMB: &PassManagerBuilder,
PM: &PassManager<'_>, PM: &PassManager<'_>,
); );
pub fn LLVMPassManagerBuilderPopulateLTOPassManager( pub fn LLVMRustPassManagerBuilderPopulateLTOPassManager(
PMB: &PassManagerBuilder, PMB: &PassManagerBuilder,
PM: &PassManager<'_>, PM: &PassManager<'_>,
Internalize: Bool, Internalize: Bool,
@ -2308,6 +2306,7 @@ extern "C" {
PGOGenPath: *const c_char, PGOGenPath: *const c_char,
PGOUsePath: *const c_char, PGOUsePath: *const c_char,
PGOSampleUsePath: *const c_char, PGOSampleUsePath: *const c_char,
SizeLevel: c_int,
); );
pub fn LLVMRustAddLibraryInfo<'a>( pub fn LLVMRustAddLibraryInfo<'a>(
PM: &PassManager<'a>, PM: &PassManager<'a>,

View file

@ -542,6 +542,11 @@ pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option<bool>, target_a
// The new pass manager is enabled by default for LLVM >= 13. // The new pass manager is enabled by default for LLVM >= 13.
// This matches Clang, which also enables it since Clang 13. // This matches Clang, which also enables it since Clang 13.
// Since LLVM 15, the legacy pass manager is no longer supported.
if llvm_util::get_version() >= (15, 0, 0) {
return true;
}
// There are some perf issues with the new pass manager when targeting // There are some perf issues with the new pass manager when targeting
// s390x with LLVM 13, so enable the new pass manager only with LLVM 14. // s390x with LLVM 13, so enable the new pass manager only with LLVM 14.
// See https://github.com/rust-lang/rust/issues/89609. // See https://github.com/rust-lang/rust/issues/89609.

View file

@ -752,6 +752,7 @@ fn test_debugging_options_tracking_hash() {
tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true); tracked!(mir_emit_retag, true);
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
tracked!(mir_opt_level, Some(4)); tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096)); tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, Some(true)); tracked!(mutable_noalias, Some(true));

View file

@ -107,6 +107,7 @@ static LLVMRustPassKind toRust(PassKind Kind) {
} }
extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
#if LLVM_VERSION_LT(15, 0)
StringRef SR(PassName); StringRef SR(PassName);
PassRegistry *PR = PassRegistry::getPassRegistry(); PassRegistry *PR = PassRegistry::getPassRegistry();
@ -115,36 +116,59 @@ extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
return wrap(PI->createPass()); return wrap(PI->createPass());
} }
return nullptr; return nullptr;
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) { extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
#if LLVM_VERSION_LT(15, 0)
const bool CompileKernel = false; const bool CompileKernel = false;
const bool UseAfterScope = true; const bool UseAfterScope = true;
return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope)); return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) { extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
#if LLVM_VERSION_LT(15, 0)
const bool CompileKernel = false; const bool CompileKernel = false;
return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover)); return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) { extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
#if LLVM_VERSION_LT(15, 0)
const bool CompileKernel = false; const bool CompileKernel = false;
return wrap(createMemorySanitizerLegacyPassPass( return wrap(createMemorySanitizerLegacyPassPass(
MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel})); MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}));
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
#if LLVM_VERSION_LT(15, 0)
return wrap(createThreadSanitizerLegacyPassPass()); return wrap(createThreadSanitizerLegacyPassPass());
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
#if LLVM_VERSION_LT(15, 0)
const bool CompileKernel = false; const bool CompileKernel = false;
return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover)); return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) { extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
@ -154,10 +178,57 @@ extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
} }
extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
#if LLVM_VERSION_LT(15, 0)
assert(RustPass); assert(RustPass);
Pass *Pass = unwrap(RustPass); Pass *Pass = unwrap(RustPass);
PassManagerBase *PMB = unwrap(PMR); PassManagerBase *PMB = unwrap(PMR);
PMB->add(Pass); PMB->add(Pass);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() {
#if LLVM_VERSION_LT(15, 0)
return LLVMPassManagerBuilderCreate();
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
#if LLVM_VERSION_LT(15, 0)
LLVMPassManagerBuilderDispose(PMB);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager(
LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
#if LLVM_VERSION_LT(15, 0)
LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager(
LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
#if LLVM_VERSION_LT(15, 0)
LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager(
LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) {
#if LLVM_VERSION_LT(15, 0)
LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" extern "C"
@ -165,12 +236,26 @@ void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
LLVMPassManagerBuilderRef PMBR, LLVMPassManagerBuilderRef PMBR,
LLVMPassManagerRef PMR LLVMPassManagerRef PMR
) { ) {
#if LLVM_VERSION_LT(15, 0)
unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR)); unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
}
extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold(
LLVMPassManagerBuilderRef PMB, unsigned Threshold) {
#if LLVM_VERSION_LT(15, 0)
LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
extern "C" extern "C"
void LLVMRustAddLastExtensionPasses( void LLVMRustAddLastExtensionPasses(
LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) { LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
#if LLVM_VERSION_LT(15, 0)
auto AddExtensionPasses = [Passes, NumPasses]( auto AddExtensionPasses = [Passes, NumPasses](
const PassManagerBuilder &Builder, PassManagerBase &PM) { const PassManagerBuilder &Builder, PassManagerBase &PM) {
for (size_t I = 0; I < NumPasses; I++) { for (size_t I = 0; I < NumPasses; I++) {
@ -183,6 +268,9 @@ void LLVMRustAddLastExtensionPasses(
AddExtensionPasses); AddExtensionPasses);
unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
AddExtensionPasses); AddExtensionPasses);
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
#ifdef LLVM_COMPONENT_X86 #ifdef LLVM_COMPONENT_X86
@ -533,12 +621,16 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
extern "C" void LLVMRustConfigurePassManagerBuilder( extern "C" void LLVMRustConfigurePassManagerBuilder(
LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO, bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath) { const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath,
int SizeLevel) {
#if LLVM_VERSION_LT(15, 0)
unwrap(PMBR)->MergeFunctions = MergeFunctions; unwrap(PMBR)->MergeFunctions = MergeFunctions;
unwrap(PMBR)->SLPVectorize = SLPVectorize; unwrap(PMBR)->SLPVectorize = SLPVectorize;
unwrap(PMBR)->OptLevel = fromRust(OptLevel); unwrap(PMBR)->OptLevel = fromRust(OptLevel);
unwrap(PMBR)->LoopVectorize = LoopVectorize; unwrap(PMBR)->LoopVectorize = LoopVectorize;
unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO; unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
unwrap(PMBR)->SizeLevel = SizeLevel;
unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0;
if (PGOGenPath) { if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath); assert(!PGOUsePath && !PGOSampleUsePath);
@ -550,6 +642,9 @@ extern "C" void LLVMRustConfigurePassManagerBuilder(
} else if (PGOSampleUsePath) { } else if (PGOSampleUsePath) {
unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath; unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath;
} }
#else
report_fatal_error("Legacy PM not supported with LLVM 15");
#endif
} }
// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`

View file

@ -6,6 +6,7 @@
#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Object/Archive.h" #include "llvm/Object/Archive.h"
#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"

View file

@ -77,17 +77,30 @@ pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn
let mut cnt = 0; let mut cnt = 0;
let validate = tcx.sess.opts.debugging_opts.validate_mir; let validate = tcx.sess.opts.debugging_opts.validate_mir;
let overridden_passes = &tcx.sess.opts.debugging_opts.mir_enable_passes;
trace!(?overridden_passes);
if validate { if validate {
validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase)); validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase));
} }
for pass in passes { for pass in passes {
let name = pass.name();
if let Some((_, polarity)) = overridden_passes.iter().rev().find(|(s, _)| s == &*name) {
trace!(
pass = %name,
"{} as requested by flag",
if *polarity { "Running" } else { "Not running" },
);
if !polarity {
continue;
}
} else {
if !pass.is_enabled(&tcx.sess) { if !pass.is_enabled(&tcx.sess) {
continue; continue;
} }
}
let name = pass.name();
let dump_enabled = pass.is_mir_dump_enabled(); let dump_enabled = pass.is_mir_dump_enabled();
if dump_enabled { if dump_enabled {

View file

@ -368,6 +368,8 @@ mod desc {
pub const parse_opt_langid: &str = "a language identifier"; pub const parse_opt_langid: &str = "a language identifier";
pub const parse_opt_pathbuf: &str = "a path"; pub const parse_opt_pathbuf: &str = "a path";
pub const parse_list: &str = "a space-separated list of strings"; pub const parse_list: &str = "a space-separated list of strings";
pub const parse_list_with_polarity: &str =
"a comma-separated list of strings, with elements beginning with + or -";
pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
pub const parse_number: &str = "a number"; pub const parse_number: &str = "a number";
pub const parse_opt_number: &str = parse_number; pub const parse_opt_number: &str = parse_number;
@ -529,6 +531,19 @@ mod parse {
} }
} }
crate fn parse_list_with_polarity(slot: &mut Vec<(String, bool)>, v: Option<&str>) -> bool {
match v {
Some(s) => {
for s in s.split(",") {
let Some(pass_name) = s.strip_prefix(&['+', '-'][..]) else { return false };
slot.push((pass_name.to_string(), &s[..1] == "+"));
}
true
}
None => false,
}
}
crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool { crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
if let Some(v) = v { if let Some(v) = v {
ld.line = false; ld.line = false;
@ -1318,6 +1333,10 @@ options! {
mir_emit_retag: bool = (false, parse_bool, [TRACKED], mir_emit_retag: bool = (false, parse_bool, [TRACKED],
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
(default: no)"), (default: no)"),
mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED],
"use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \
enabled, overriding all other checks. Passes that are not specified are enabled or \
disabled by other flags as usual."),
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED], mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED], move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],

View file

@ -2563,40 +2563,77 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// We proactively collect all the inferred type params to emit a single error per fn def. // We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();
for ty in decl.inputs { let mut infer_replacements = vec![];
visitor.visit_ty(ty);
}
walk_generics(&mut visitor, generics); walk_generics(&mut visitor, generics);
let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let input_tys: Vec<_> = decl
.inputs
.iter()
.enumerate()
.map(|(i, a)| {
if let hir::TyKind::Infer = a.kind && !self.allow_ty_infer() {
if let Some(suggested_ty) =
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
{
infer_replacements.push((a.span, suggested_ty.to_string()));
return suggested_ty;
}
}
// Only visit the type looking for `_` if we didn't fix the type above
visitor.visit_ty(a);
self.ty_of_arg(a, None)
})
.collect();
let output_ty = match decl.output { let output_ty = match decl.output {
hir::FnRetTy::Return(output) => { hir::FnRetTy::Return(output) => {
if let hir::TyKind::Infer = output.kind
&& !self.allow_ty_infer()
&& let Some(suggested_ty) =
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
{
infer_replacements.push((output.span, suggested_ty.to_string()));
suggested_ty
} else {
visitor.visit_ty(output); visitor.visit_ty(output);
self.ast_ty_to_ty(output) self.ast_ty_to_ty(output)
} }
}
hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
}; };
debug!("ty_of_fn: output_ty={:?}", output_ty); debug!("ty_of_fn: output_ty={:?}", output_ty);
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
if !self.allow_ty_infer() { if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
// We always collect the spans for placeholder types when evaluating `fn`s, but we // We always collect the spans for placeholder types when evaluating `fn`s, but we
// only want to emit an error complaining about them if infer types (`_`) are not // only want to emit an error complaining about them if infer types (`_`) are not
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
crate::collect::placeholder_type_error( let mut diag = crate::collect::placeholder_type_error_diag(
tcx, tcx,
ident_span.map(|sp| sp.shrink_to_hi()), ident_span.map(|sp| sp.shrink_to_hi()),
generics.params, generics.params,
visitor.0, visitor.0,
infer_replacements.iter().map(|(s, _)| *s).collect(),
true, true,
hir_ty, hir_ty,
"function", "function",
); );
if !infer_replacements.is_empty() {
diag.multipart_suggestion(&format!(
"try replacing `_` with the type{} in the corresponding trait method signature",
rustc_errors::pluralize!(infer_replacements.len()),
), infer_replacements, Applicability::MachineApplicable);
}
diag.emit();
} }
// Find any late-bound regions declared in return type that do // Find any late-bound regions declared in return type that do
@ -2624,6 +2661,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
bare_fn_ty bare_fn_ty
} }
/// Given a fn_hir_id for a impl function, suggest the type that is found on the
/// corresponding function in the trait that the impl implements, if it exists.
/// If arg_idx is Some, then it corresponds to an input type index, otherwise it
/// corresponds to the return type.
fn suggest_trait_fn_ty_for_impl_fn_infer(
&self,
fn_hir_id: hir::HirId,
arg_idx: Option<usize>,
) -> Option<Ty<'tcx>> {
let tcx = self.tcx();
let hir = tcx.hir();
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
hir.get(fn_hir_id) else { return None };
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
let trait_ref =
self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
let x: &ty::AssocItem = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
tcx,
*ident,
ty::AssocKind::Fn,
trait_ref.def_id,
)?;
let fn_sig = tcx.fn_sig(x.def_id).subst(
tcx,
trait_ref.substs.extend_to(tcx, x.def_id, |param, _| tcx.mk_param_from_def(param)),
);
let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
Some(tcx.erase_late_bound_regions(ty))
}
fn validate_late_bound_regions( fn validate_late_bound_regions(
&self, &self,
constrained_regions: FxHashSet<ty::BoundRegionKind>, constrained_regions: FxHashSet<ty::BoundRegionKind>,

View file

@ -160,6 +160,33 @@ crate fn placeholder_type_error<'tcx>(
return; return;
} }
placeholder_type_error_diag(
tcx,
span,
generics,
placeholder_types,
vec![],
suggest,
hir_ty,
kind,
)
.emit();
}
crate fn placeholder_type_error_diag<'tcx>(
tcx: TyCtxt<'tcx>,
span: Option<Span>,
generics: &[hir::GenericParam<'_>],
placeholder_types: Vec<Span>,
additional_spans: Vec<Span>,
suggest: bool,
hir_ty: Option<&hir::Ty<'_>>,
kind: &'static str,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
if placeholder_types.is_empty() {
return bad_placeholder(tcx, additional_spans, kind);
}
let type_name = generics.next_type_param_name(None); let type_name = generics.next_type_param_name(None);
let mut sugg: Vec<_> = let mut sugg: Vec<_> =
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
@ -182,7 +209,8 @@ crate fn placeholder_type_error<'tcx>(
sugg.push((span, format!(", {}", type_name))); sugg.push((span, format!(", {}", type_name)));
} }
let mut err = bad_placeholder(tcx, placeholder_types, kind); let mut err =
bad_placeholder(tcx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
// Suggest, but only if it is not a function in const or static // Suggest, but only if it is not a function in const or static
if suggest { if suggest {
@ -218,7 +246,8 @@ crate fn placeholder_type_error<'tcx>(
); );
} }
} }
err.emit();
err
} }
fn reject_placeholder_type_signatures_in_item<'tcx>( fn reject_placeholder_type_signatures_in_item<'tcx>(
@ -1868,50 +1897,17 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
generics, generics,
.. ..
}) })
| ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. })
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
match get_infer_ret_ty(&sig.decl.output) { infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
Some(ty) => { }
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
// Typeck doesn't expect erased regions to be returned from `type_of`.
let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
});
let fn_sig = ty::Binder::dummy(fn_sig);
let mut visitor = HirPlaceholderCollector::default(); ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) => {
visitor.visit_ty(ty); // Do not try to inference the return type for a impl method coming from a trait
let mut diag = bad_placeholder(tcx, visitor.0, "return type"); if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
let ret_ty = fn_sig.skip_binder().output(); tcx.hir().get(tcx.hir().get_parent_node(hir_id))
if !ret_ty.references_error() { && i.of_trait.is_some()
if !ret_ty.is_closure() { {
let ret_ty_str = match ret_ty.kind() { <dyn AstConv<'_>>::ty_of_fn(
// Suggest a function pointer return type instead of a unique function definition
// (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
// syntax)
ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
_ => ret_ty.to_string(),
};
diag.span_suggestion(
ty.span,
"replace with the correct return type",
ret_ty_str,
Applicability::MaybeIncorrect,
);
} else {
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
// to prevent the user from getting a papercut while trying to use the unique closure
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
}
}
diag.emit();
fn_sig
}
None => <dyn AstConv<'_>>::ty_of_fn(
&icx, &icx,
hir_id, hir_id,
sig.header.unsafety, sig.header.unsafety,
@ -1920,7 +1916,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
generics, generics,
Some(ident.span), Some(ident.span),
None, None,
), )
} else {
infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
} }
} }
@ -1982,6 +1980,70 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
} }
} }
fn infer_return_ty_for_fn_sig<'tcx>(
tcx: TyCtxt<'tcx>,
sig: &hir::FnSig<'_>,
ident: Ident,
generics: &hir::Generics<'_>,
def_id: LocalDefId,
icx: &ItemCtxt<'tcx>,
) -> ty::PolyFnSig<'tcx> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
match get_infer_ret_ty(&sig.decl.output) {
Some(ty) => {
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
// Typeck doesn't expect erased regions to be returned from `type_of`.
let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
});
let fn_sig = ty::Binder::dummy(fn_sig);
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.skip_binder().output();
if !ret_ty.references_error() {
if !ret_ty.is_closure() {
let ret_ty_str = match ret_ty.kind() {
// Suggest a function pointer return type instead of a unique function definition
// (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
// syntax)
ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
_ => ret_ty.to_string(),
};
diag.span_suggestion(
ty.span,
"replace with the correct return type",
ret_ty_str,
Applicability::MaybeIncorrect,
);
} else {
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
// to prevent the user from getting a papercut while trying to use the unique closure
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
}
}
diag.emit();
fn_sig
}
None => <dyn AstConv<'_>>::ty_of_fn(
icx,
hir_id,
sig.header.unsafety,
sig.header.abi,
sig.decl,
generics,
Some(ident.span),
None,
),
}
}
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id); let icx = ItemCtxt::new(tcx, def_id);
match tcx.hir().expect_item(def_id.expect_local()).kind { match tcx.hir().expect_item(def_id.expect_local()).kind {

View file

@ -162,6 +162,300 @@ fn test_insert() {
} }
} }
#[test]
fn test_get() {
let mut tester = VecDeque::new();
tester.push_back(1);
tester.push_back(2);
tester.push_back(3);
assert_eq!(tester.len(), 3);
assert_eq!(tester.get(1), Some(&2));
assert_eq!(tester.get(2), Some(&3));
assert_eq!(tester.get(0), Some(&1));
assert_eq!(tester.get(3), None);
tester.remove(0);
assert_eq!(tester.len(), 2);
assert_eq!(tester.get(0), Some(&2));
assert_eq!(tester.get(1), Some(&3));
assert_eq!(tester.get(2), None);
}
#[test]
fn test_get_mut() {
let mut tester = VecDeque::new();
tester.push_back(1);
tester.push_back(2);
tester.push_back(3);
assert_eq!(tester.len(), 3);
if let Some(elem) = tester.get_mut(0) {
assert_eq!(*elem, 1);
*elem = 10;
}
if let Some(elem) = tester.get_mut(2) {
assert_eq!(*elem, 3);
*elem = 30;
}
assert_eq!(tester.get(0), Some(&10));
assert_eq!(tester.get(2), Some(&30));
assert_eq!(tester.get_mut(3), None);
tester.remove(2);
assert_eq!(tester.len(), 2);
assert_eq!(tester.get(0), Some(&10));
assert_eq!(tester.get(1), Some(&2));
assert_eq!(tester.get(2), None);
}
#[test]
fn test_swap() {
let mut tester = VecDeque::new();
tester.push_back(1);
tester.push_back(2);
tester.push_back(3);
assert_eq!(tester, [1, 2, 3]);
tester.swap(0, 0);
assert_eq!(tester, [1, 2, 3]);
tester.swap(0, 1);
assert_eq!(tester, [2, 1, 3]);
tester.swap(2, 1);
assert_eq!(tester, [2, 3, 1]);
tester.swap(1, 2);
assert_eq!(tester, [2, 1, 3]);
tester.swap(0, 2);
assert_eq!(tester, [3, 1, 2]);
tester.swap(2, 2);
assert_eq!(tester, [3, 1, 2]);
}
#[test]
#[should_panic = "assertion failed: j < self.len()"]
fn test_swap_panic() {
let mut tester = VecDeque::new();
tester.push_back(1);
tester.push_back(2);
tester.push_back(3);
tester.swap(2, 3);
}
#[test]
fn test_reserve_exact() {
let mut tester: VecDeque<i32> = VecDeque::with_capacity(1);
assert!(tester.capacity() == 1);
tester.reserve_exact(50);
assert!(tester.capacity() >= 51);
tester.reserve_exact(40);
assert!(tester.capacity() >= 51);
tester.reserve_exact(200);
assert!(tester.capacity() >= 200);
}
#[test]
#[should_panic = "capacity overflow"]
fn test_reserve_exact_panic() {
let mut tester: VecDeque<i32> = VecDeque::new();
tester.reserve_exact(usize::MAX);
}
#[test]
fn test_try_reserve_exact() {
let mut tester: VecDeque<i32> = VecDeque::with_capacity(1);
assert!(tester.capacity() == 1);
assert_eq!(tester.try_reserve_exact(100), Ok(()));
assert!(tester.capacity() >= 100);
assert_eq!(tester.try_reserve_exact(50), Ok(()));
assert!(tester.capacity() >= 100);
assert_eq!(tester.try_reserve_exact(200), Ok(()));
assert!(tester.capacity() >= 200);
assert_eq!(tester.try_reserve_exact(0), Ok(()));
assert!(tester.capacity() >= 200);
assert!(tester.try_reserve_exact(usize::MAX).is_err());
}
#[test]
fn test_try_reserve() {
let mut tester: VecDeque<i32> = VecDeque::with_capacity(1);
assert!(tester.capacity() == 1);
assert_eq!(tester.try_reserve(100), Ok(()));
assert!(tester.capacity() >= 100);
assert_eq!(tester.try_reserve(50), Ok(()));
assert!(tester.capacity() >= 100);
assert_eq!(tester.try_reserve(200), Ok(()));
assert!(tester.capacity() >= 200);
assert_eq!(tester.try_reserve(0), Ok(()));
assert!(tester.capacity() >= 200);
assert!(tester.try_reserve(usize::MAX).is_err());
}
#[test]
fn test_contains() {
let mut tester = VecDeque::new();
tester.push_back(1);
tester.push_back(2);
tester.push_back(3);
assert!(tester.contains(&1));
assert!(tester.contains(&3));
assert!(!tester.contains(&0));
assert!(!tester.contains(&4));
tester.remove(0);
assert!(!tester.contains(&1));
assert!(tester.contains(&2));
assert!(tester.contains(&3));
}
#[test]
fn test_rotate_left_right() {
let mut tester: VecDeque<_> = (1..=10).collect();
assert_eq!(tester.len(), 10);
tester.rotate_left(0);
assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
tester.rotate_right(0);
assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
tester.rotate_left(3);
assert_eq!(tester, [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]);
tester.rotate_right(5);
assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]);
tester.rotate_left(tester.len());
assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]);
tester.rotate_right(tester.len());
assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]);
tester.rotate_left(1);
assert_eq!(tester, [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
#[test]
#[should_panic = "assertion failed: mid <= self.len()"]
fn test_rotate_left_panic() {
let mut tester: VecDeque<_> = (1..=10).collect();
tester.rotate_left(tester.len() + 1);
}
#[test]
#[should_panic = "assertion failed: k <= self.len()"]
fn test_rotate_right_panic() {
let mut tester: VecDeque<_> = (1..=10).collect();
tester.rotate_right(tester.len() + 1);
}
#[test]
fn test_binary_search() {
// If the givin VecDeque is not sorted, the returned result is unspecified and meaningless,
// as this method performs a binary search.
let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
assert_eq!(tester.binary_search(&0), Ok(0));
assert_eq!(tester.binary_search(&5), Ok(5));
assert_eq!(tester.binary_search(&55), Ok(10));
assert_eq!(tester.binary_search(&4), Err(5));
assert_eq!(tester.binary_search(&-1), Err(0));
assert!(matches!(tester.binary_search(&1), Ok(1..=2)));
let tester: VecDeque<_> = [1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3].into();
assert_eq!(tester.binary_search(&1), Ok(0));
assert!(matches!(tester.binary_search(&2), Ok(1..=4)));
assert!(matches!(tester.binary_search(&3), Ok(5..=13)));
assert_eq!(tester.binary_search(&-2), Err(0));
assert_eq!(tester.binary_search(&0), Err(0));
assert_eq!(tester.binary_search(&4), Err(14));
assert_eq!(tester.binary_search(&5), Err(14));
}
#[test]
fn test_binary_search_by() {
// If the givin VecDeque is not sorted, the returned result is unspecified and meaningless,
// as this method performs a binary search.
let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
assert_eq!(tester.binary_search_by(|x| x.cmp(&0)), Ok(0));
assert_eq!(tester.binary_search_by(|x| x.cmp(&5)), Ok(5));
assert_eq!(tester.binary_search_by(|x| x.cmp(&55)), Ok(10));
assert_eq!(tester.binary_search_by(|x| x.cmp(&4)), Err(5));
assert_eq!(tester.binary_search_by(|x| x.cmp(&-1)), Err(0));
assert!(matches!(tester.binary_search_by(|x| x.cmp(&1)), Ok(1..=2)));
}
#[test]
fn test_binary_search_key() {
// If the givin VecDeque is not sorted, the returned result is unspecified and meaningless,
// as this method performs a binary search.
let tester: VecDeque<_> = [
(-1, 0),
(2, 10),
(6, 5),
(7, 1),
(8, 10),
(10, 2),
(20, 3),
(24, 5),
(25, 18),
(28, 13),
(31, 21),
(32, 4),
(54, 25),
]
.into();
assert_eq!(tester.binary_search_by_key(&-1, |&(a, _b)| a), Ok(0));
assert_eq!(tester.binary_search_by_key(&8, |&(a, _b)| a), Ok(4));
assert_eq!(tester.binary_search_by_key(&25, |&(a, _b)| a), Ok(8));
assert_eq!(tester.binary_search_by_key(&54, |&(a, _b)| a), Ok(12));
assert_eq!(tester.binary_search_by_key(&-2, |&(a, _b)| a), Err(0));
assert_eq!(tester.binary_search_by_key(&1, |&(a, _b)| a), Err(1));
assert_eq!(tester.binary_search_by_key(&4, |&(a, _b)| a), Err(2));
assert_eq!(tester.binary_search_by_key(&13, |&(a, _b)| a), Err(6));
assert_eq!(tester.binary_search_by_key(&55, |&(a, _b)| a), Err(13));
assert_eq!(tester.binary_search_by_key(&100, |&(a, _b)| a), Err(13));
let tester: VecDeque<_> = [
(0, 0),
(2, 1),
(6, 1),
(5, 1),
(3, 1),
(1, 2),
(2, 3),
(4, 5),
(5, 8),
(8, 13),
(1, 21),
(2, 34),
(4, 55),
]
.into();
assert_eq!(tester.binary_search_by_key(&0, |&(_a, b)| b), Ok(0));
assert!(matches!(tester.binary_search_by_key(&1, |&(_a, b)| b), Ok(1..=4)));
assert_eq!(tester.binary_search_by_key(&8, |&(_a, b)| b), Ok(8));
assert_eq!(tester.binary_search_by_key(&13, |&(_a, b)| b), Ok(9));
assert_eq!(tester.binary_search_by_key(&55, |&(_a, b)| b), Ok(12));
assert_eq!(tester.binary_search_by_key(&-1, |&(_a, b)| b), Err(0));
assert_eq!(tester.binary_search_by_key(&4, |&(_a, b)| b), Err(7));
assert_eq!(tester.binary_search_by_key(&56, |&(_a, b)| b), Err(13));
assert_eq!(tester.binary_search_by_key(&100, |&(_a, b)| b), Err(13));
}
#[test] #[test]
fn make_contiguous_big_tail() { fn make_contiguous_big_tail() {
let mut tester = VecDeque::with_capacity(15); let mut tester = VecDeque::with_capacity(15);

View file

@ -31,8 +31,8 @@ fn main() {
let mut cmd = Command::new(rustdoc); let mut cmd = Command::new(rustdoc);
// I am not actually sure why it's necessary to pass the sysroot for `--test`, // cfg(bootstrap)
// but `test --doc --stage 0` is broken without it :( // NOTE: the `--test` special-casing can be removed when https://github.com/rust-lang/cargo/pull/10594 lands on beta.
if target.is_some() || args.iter().any(|x| x == "--test") { if target.is_some() || args.iter().any(|x| x == "--test") {
// The stage0 compiler has a special sysroot distinct from what we // The stage0 compiler has a special sysroot distinct from what we
// actually downloaded, so we just always pass the `--sysroot` option, // actually downloaded, so we just always pass the `--sysroot` option,
@ -65,13 +65,6 @@ fn main() {
} }
} }
// Needed to be able to run all rustdoc tests.
if let Some(ref x) = env::var_os("RUSTDOC_RESOURCE_SUFFIX") {
// This "unstable-options" can be removed when `--resource-suffix` is stabilized
cmd.arg("-Z").arg("unstable-options");
cmd.arg("--resource-suffix").arg(x);
}
if verbose > 1 { if verbose > 1 {
eprintln!( eprintln!(
"rustdoc command: {:?}={:?} {:?}", "rustdoc command: {:?}={:?} {:?}",

View file

@ -1,14 +1,12 @@
// compile-flags: -Z panic-in-drop=abort -O -Z new-llvm-pass-manager=no // compile-flags: -Z panic-in-drop=abort -O
// ignore-msvc
// Ensure that unwinding code paths are eliminated from the output after // Ensure that unwinding code paths are eliminated from the output after
// optimization. // optimization.
// This test uses -Z new-llvm-pass-manager=no, because the expected optimization does not happen // This test uses ignore-msvc, because the expected optimization does not happen on targets using
// on targets using SEH exceptions (i.e. MSVC) anymore. The core issue is that Rust promises that // SEH exceptions with the new LLVM pass manager anymore, see
// the drop_in_place() function can't unwind, but implements it in a way that *can*, because we // https://github.com/llvm/llvm-project/issues/51311.
// currently go out of our way to allow longjmps, which also use the unwinding mechanism on MSVC
// targets. We should either forbid longjmps, or not assume nounwind, making this optimization
// incompatible with the current behavior of running cleanuppads on longjmp unwinding.
// CHECK-NOT: {{(call|invoke).*}}should_not_appear_in_output // CHECK-NOT: {{(call|invoke).*}}should_not_appear_in_output

View file

@ -1,4 +1,4 @@
// compile-flags: -C opt-level=0 -Z inline_mir=no // unit-test: InstCombine
// ignore-wasm32 compiled with panic=abort by default // ignore-wasm32 compiled with panic=abort by default
// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff // EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff

View file

@ -23,9 +23,15 @@
} }
bb0: { bb0: {
StorageLive(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
_2 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 _2 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
_3 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 _3 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
_4 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 _4 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
StorageLive(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
StorageLive(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
StorageLive(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
- _7 = &(*_2); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _7 = &(*_2); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
- _6 = &(*_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - _6 = &(*_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+ _7 = _2; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 + _7 = _2; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
@ -37,6 +43,10 @@
} }
bb1: { bb1: {
StorageDead(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9
StorageLive(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
StorageLive(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
StorageLive(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _10 = &(*_3); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - _10 = &(*_3); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _9 = &(*_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - _9 = &(*_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
@ -50,6 +60,10 @@
} }
bb2: { bb2: {
StorageDead(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11
StorageLive(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
StorageLive(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
StorageLive(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _13 = &(*_4); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - _13 = &(*_4); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _12 = &(*_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - _12 = &(*_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
@ -63,10 +77,20 @@
} }
bb3: { bb3: {
StorageDead(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
Deinit(_0); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 Deinit(_0); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.0: T) = move _5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 (_0.0: T) = move _5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.1: u64) = move _8; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 (_0.1: u64) = move _8; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.2: [f32; 3]) = move _11; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15 (_0.2: [f32; 3]) = move _11; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
StorageDead(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
return; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15 return; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15
} }

View file

@ -68,8 +68,10 @@
+ bb3: { + bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2 return; // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2
+ } }
+
- bb5 (cleanup): {
- resume; // scope 0 at $DIR/early_otherwise_branch.rs:3:1: 8:2
+ bb4: { + bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17 + StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17 + switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17

View file

@ -32,7 +32,7 @@
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17 _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb7]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 - switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
@ -84,8 +84,8 @@
return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2 return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2
} }
- bb7: { - bb7 (cleanup): {
- unreachable; // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15 - resume; // scope 0 at $DIR/early_otherwise_branch.rs:11:1: 17:2
+ bb5: { + bb5: {
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17

View file

@ -68,8 +68,10 @@
+ bb3: { + bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:26:1: 26:2 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:26:1: 26:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:26:2: 26:2 return; // scope 0 at $DIR/early_otherwise_branch.rs:26:2: 26:2
+ } }
+
- bb5 (cleanup): {
- resume; // scope 0 at $DIR/early_otherwise_branch.rs:21:1: 26:2
+ bb4: { + bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17 + StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17 + switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17

View file

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts // unit-test: EarlyOtherwiseBranch
// EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>) -> u32 { fn opt1(x: Option<u32>, y: Option<u32>) -> u32 {
match (x, y) { match (x, y) {

View file

@ -90,8 +90,10 @@
+ bb4: { + bb4: {
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:1: 9:2 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:1: 9:2
return; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:2: 9:2 return; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:2: 9:2
+ } }
+
- bb6 (cleanup): {
- resume; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:4:1: 9:2
+ bb5: { + bb5: {
+ StorageDead(_15); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20 + StorageDead(_15); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
+ switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20 + switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20

View file

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts // unit-test: EarlyOtherwiseBranch
// EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 { fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 {

View file

@ -38,25 +38,29 @@
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17 _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17 switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
} }
bb1: { bb1: {
_6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17 _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17 switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
} }
bb2: { bb2: {
_0 = const 3_u32; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26 _0 = const 3_u32; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26 goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
} }
bb3: { bb3: {
_7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17 unreachable; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
} }
bb4: { bb4: {
_7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
}
bb5: {
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16 StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16 _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:24: 9:25 StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:24: 9:25
@ -64,28 +68,32 @@
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32 _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32 StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32 StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32 goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
} }
bb5: { bb6: {
StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16 StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
_11 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16 _11 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
_0 = const 1_u32; // scope 2 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29 _0 = const 1_u32; // scope 2 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29 StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29 goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
} }
bb6: { bb7: {
StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22 StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
_12 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22 _12 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
_0 = const 2_u32; // scope 3 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29 _0 = const 2_u32; // scope 3 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29 StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29 goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
} }
bb7: { bb8: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:1: 14:2 StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:1: 14:2
return; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:2: 14:2 return; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:2: 14:2
} }
bb9 (cleanup): {
resume; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:7:1: 14:2
}
} }

View file

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts // unit-test: EarlyOtherwiseBranch
// must not optimize as it does not follow the pattern of // must not optimize as it does not follow the pattern of
// left and right hand side being the same variant // left and right hand side being the same variant

View file

@ -19,7 +19,7 @@
bb1: { bb1: {
_0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15 _0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15 goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
} }
bb2: { bb2: {
@ -29,7 +29,7 @@
bb3: { bb3: {
_0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19 _0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19 goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
} }
bb4: { bb4: {
@ -37,7 +37,15 @@
_5 = (((*_2) as Some).0: i32); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:18: 22:19 _5 = (((*_2) as Some).0: i32); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:18: 22:19
_0 = _5; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25 _0 = _5; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25 goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
}
bb5: {
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:27:2: 27:2
}
bb6 (cleanup): {
resume; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:18:1: 27:2
} }
} }

View file

@ -19,12 +19,20 @@
bb2: { bb2: {
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39 _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52 goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
} }
bb3: { bb3: {
_0 = const 2_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:49: 13:50 _0 = const 2_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:49: 13:50
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52 goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
}
bb4: {
return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:14:2: 14:2
}
bb5 (cleanup): {
resume; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:12:1: 14:2
} }
} }

View file

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts // unit-test: EarlyOtherwiseBranch
// Tests various cases that the `early_otherwise_branch` opt should *not* optimize // Tests various cases that the `early_otherwise_branch` opt should *not* optimize

View file

@ -1,4 +1,4 @@
// compile-flags: -O // unit-test: SimplifyComparisonIntegral
// EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff // EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
// EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff // EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
// EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff // EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff

View file

@ -26,5 +26,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:17:25: 17:26 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:17:25: 17:26
return; // scope 0 at $DIR/if-condition-int.rs:18:2: 18:2 return; // scope 0 at $DIR/if-condition-int.rs:18:2: 18:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:16:1: 18:2
}
} }

View file

@ -30,5 +30,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:53:34: 53:35 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:53:34: 53:35
return; // scope 0 at $DIR/if-condition-int.rs:54:2: 54:2 return; // scope 0 at $DIR/if-condition-int.rs:54:2: 54:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:52:1: 54:2
}
} }

View file

@ -54,5 +54,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:49:1: 49:2 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:49:1: 49:2
return; // scope 0 at $DIR/if-condition-int.rs:49:2: 49:2 return; // scope 0 at $DIR/if-condition-int.rs:49:2: 49:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:43:1: 49:2
}
} }

View file

@ -35,5 +35,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:21:32: 21:33 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:21:32: 21:33
return; // scope 0 at $DIR/if-condition-int.rs:22:2: 22:2 return; // scope 0 at $DIR/if-condition-int.rs:22:2: 22:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:20:1: 22:2
}
} }

View file

@ -35,5 +35,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:25:31: 25:32 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:25:31: 25:32
return; // scope 0 at $DIR/if-condition-int.rs:26:2: 26:2 return; // scope 0 at $DIR/if-condition-int.rs:26:2: 26:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:24:1: 26:2
}
} }

View file

@ -61,5 +61,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:39:5: 39:6 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:39:5: 39:6
return; // scope 0 at $DIR/if-condition-int.rs:40:2: 40:2 return; // scope 0 at $DIR/if-condition-int.rs:40:2: 40:2
} }
bb7 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:32:1: 40:2
}
} }

View file

@ -35,5 +35,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:29:32: 29:33 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:29:32: 29:33
return; // scope 0 at $DIR/if-condition-int.rs:30:2: 30:2 return; // scope 0 at $DIR/if-condition-int.rs:30:2: 30:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:28:1: 30:2
}
} }

View file

@ -35,5 +35,9 @@
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:12:31: 12:32 StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:12:31: 12:32
return; // scope 0 at $DIR/if-condition-int.rs:13:2: 13:2 return; // scope 0 at $DIR/if-condition-int.rs:13:2: 13:2
} }
bb4 (cleanup): {
resume; // scope 0 at $DIR/if-condition-int.rs:11:1: 13:2
}
} }

View file

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=3 // unit-test: LowerSliceLenCalls
// EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff // EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
pub fn bound(index: usize, slice: &[u8]) -> u8 { pub fn bound(index: usize, slice: &[u8]) -> u8 {

View file

@ -1,4 +1,4 @@
// compile-flags: -Zmir-opt-level=1 // unit-test: RenameReturnPlace
// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {

View file

@ -39,5 +39,9 @@
- StorageDead(_2); // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2 - StorageDead(_2); // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2
return; // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2 return; // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2
} }
bb2 (cleanup): {
resume; // scope 0 at $DIR/nrvo-simple.rs:4:1: 8:2
}
} }

View file

@ -0,0 +1,15 @@
// run-rustfix
#![allow(unused)]
trait Foo<T>: Sized {
fn bar(i: i32, t: T, s: &Self) -> (T, i32);
}
impl Foo<usize> for () {
fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
(1, 2)
}
}
fn main() {}

View file

@ -0,0 +1,15 @@
// run-rustfix
#![allow(unused)]
trait Foo<T>: Sized {
fn bar(i: i32, t: T, s: &Self) -> (T, i32);
}
impl Foo<usize> for () {
fn bar(i: _, t: _, s: _) -> _ {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
(1, 2)
}
}
fn main() {}

View file

@ -0,0 +1,18 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/replace-impl-infer-ty-from-trait.rs:9:15
|
LL | fn bar(i: _, t: _, s: _) -> _ {
| ^ ^ ^ ^ not allowed in type signatures
| | | |
| | | not allowed in type signatures
| | not allowed in type signatures
| not allowed in type signatures
|
help: try replacing `_` with the types in the corresponding trait method signature
|
LL | fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
| ~~~ ~~~~~ ~~~ ~~~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0121`.

View file

@ -1,16 +1,16 @@
error[E0478]: lifetime bound not satisfied error[E0478]: lifetime bound not satisfied
--> $DIR/issue-28848.rs:10:5 --> $DIR/issue-28848.rs:14:5
| |
LL | Foo::<'a, 'b>::xmute(u) LL | Foo::<'a, 'b>::xmute(u)
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
| |
note: lifetime parameter instantiated with the lifetime `'b` as defined here note: lifetime parameter instantiated with the lifetime `'b` as defined here
--> $DIR/issue-28848.rs:9:16 --> $DIR/issue-28848.rs:13:16
| |
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
| ^^ | ^^
note: but lifetime parameter must outlive the lifetime `'a` as defined here note: but lifetime parameter must outlive the lifetime `'a` as defined here
--> $DIR/issue-28848.rs:9:12 --> $DIR/issue-28848.rs:13:12
| |
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
| ^^ | ^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/issue-28848.rs:10:5 --> $DIR/issue-28848.rs:14:5
| |
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct Foo<'a, 'b: 'a>(&'a &'b ()); struct Foo<'a, 'b: 'a>(&'a &'b ());
impl<'a, 'b> Foo<'a, 'b> { impl<'a, 'b> Foo<'a, 'b> {
@ -7,7 +11,9 @@ impl<'a, 'b> Foo<'a, 'b> {
} }
pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
Foo::<'a, 'b>::xmute(u) //~ ERROR lifetime bound not satisfied Foo::<'a, 'b>::xmute(u)
//[base]~^ ERROR lifetime bound not satisfied
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0308]: `if` and `else` have incompatible types error[E0308]: `if` and `else` have incompatible types
--> $DIR/region-invariant-static-error-reporting.rs:17:9 --> $DIR/region-invariant-static-error-reporting.rs:21:9
| |
LL | let bad = if x.is_some() { LL | let bad = if x.is_some() {
| _______________- | _______________-
@ -14,7 +14,7 @@ LL | | };
= note: expected struct `Invariant<'a>` = note: expected struct `Invariant<'a>`
found struct `Invariant<'static>` found struct `Invariant<'static>`
note: the lifetime `'a` as defined here... note: the lifetime `'a` as defined here...
--> $DIR/region-invariant-static-error-reporting.rs:13:10 --> $DIR/region-invariant-static-error-reporting.rs:17:10
| |
LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) { LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
| ^^ | ^^

View file

@ -1,5 +1,5 @@
error[E0521]: borrowed data escapes outside of function error[E0521]: borrowed data escapes outside of function
--> $DIR/region-invariant-static-error-reporting.rs:15:9 --> $DIR/region-invariant-static-error-reporting.rs:19:9
| |
LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) { LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
| -- - `x` is a reference that is only valid in the function body | -- - `x` is a reference that is only valid in the function body

View file

@ -3,8 +3,12 @@
// over time, but this test used to exhibit some pretty bogus messages // over time, but this test used to exhibit some pretty bogus messages
// that were not remotely helpful. // that were not remotely helpful.
// error-pattern:the lifetime `'a` // revisions: base nll
// error-pattern:the static lifetime // ignore-compare-mode-nll
//[base] error-pattern:the lifetime `'a`
//[base] error-pattern:the static lifetime
//[nll] compile-flags: -Z borrowck=mir
//[nll] error-pattern:argument requires that `'a` must outlive `'static`
struct Invariant<'a>(Option<&'a mut &'a mut ()>); struct Invariant<'a>(Option<&'a mut &'a mut ()>);
@ -12,9 +16,9 @@ fn mk_static() -> Invariant<'static> { Invariant(None) }
fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) { fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
let bad = if x.is_some() { let bad = if x.is_some() {
x.unwrap() x.unwrap() //[nll]~ ERROR borrowed data escapes outside of function [E0521]
} else { } else {
mk_static() mk_static() //[base]~ ERROR `if` and `else` have incompatible types [E0308]
}; };
f(bad); f(bad);
} }

View file

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:10 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:12:10
| |
LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
| --------- --------- these two types are declared with different lifetimes... | --------- --------- these two types are declared with different lifetimes...
@ -8,7 +8,7 @@ LL | *x = *y;
| ^^ ...but data from `y` flows into `x` here | ^^ ...but data from `y` flows into `x` here
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:7 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:7
| |
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
| --------- --------- these two types are declared with different lifetimes... | --------- --------- these two types are declared with different lifetimes...
@ -17,7 +17,7 @@ LL | a(x, y);
| ^ ...but data from `y` flows into `x` here | ^ ...but data from `y` flows into `x` here
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:43
| |
LL | let _: fn(&mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^ one type is more general than the other | ^ one type is more general than the other

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:12:5
| |
LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -12,7 +12,7 @@ LL | *x = *y;
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:5
| |
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -28,7 +28,7 @@ LL | a(x, y);
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:12
| |
LL | let _: fn(&mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@ -37,7 +37,7 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:12
| |
LL | let _: fn(&mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a { fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a {
// Note: this is legal because of the `'b:'a` declaration. // Note: this is legal because of the `'b:'a` declaration.
*x = *y; *x = *y;
@ -5,19 +9,25 @@ fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a {
fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
// Illegal now because there is no `'b:'a` declaration. // Illegal now because there is no `'b:'a` declaration.
*x = *y; //~ ERROR E0623 *x = *y;
//[base]~^ ERROR E0623
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
// Here we try to call `foo` but do not know that `'a` and `'b` are // Here we try to call `foo` but do not know that `'a` and `'b` are
// related as required. // related as required.
a(x, y); //~ ERROR lifetime mismatch [E0623] a(x, y);
//[base]~^ ERROR lifetime mismatch [E0623]
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn d() { fn d() {
// 'a and 'b are early bound in the function `a` because they appear // 'a and 'b are early bound in the function `a` because they appear
// inconstraints: // inconstraints:
let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types let _: fn(&mut &isize, &mut &isize) = a;
//~^ ERROR mismatched types [E0308]
//[nll]~^^ ERROR mismatched types [E0308]
} }
fn e() { fn e() {

View file

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:10 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:13:10
| |
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| --------- --------- these two types are declared with different lifetimes... | --------- --------- these two types are declared with different lifetimes...
@ -8,7 +8,7 @@ LL | *x = *y;
| ^^ ...but data from `y` flows into `x` here | ^^ ...but data from `y` flows into `x` here
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:10:10 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:10
| |
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| --------- --------- | --------- ---------
@ -19,7 +19,7 @@ LL | *z = *y;
| ^^ ...but data from `y` flows into `z` here | ^^ ...but data from `y` flows into `z` here
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:7 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:7
| |
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| --------- --------- these two types are declared with different lifetimes... | --------- --------- these two types are declared with different lifetimes...
@ -28,7 +28,7 @@ LL | a(x, y, z);
| ^ ...but data from `y` flows into `x` here | ^ ...but data from `y` flows into `x` here
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:56
| |
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^ one type is more general than the other | ^ one type is more general than the other

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:13:5
| |
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -12,7 +12,7 @@ LL | *x = *y;
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:5
| |
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -28,7 +28,7 @@ LL | a(x, y, z);
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
| |
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@ -37,7 +37,7 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
| |
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@ -46,7 +46,7 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
| |
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other

View file

@ -1,82 +0,0 @@
error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5
|
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | // Illegal now because there is no `'b:'a` declaration.
LL | *x = *y;
| ^^^^^^^ assignment requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:10:5
|
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'c` defined here
| |
| lifetime `'b` defined here
...
LL | *z = *y;
| ^^^^^^^ assignment requires that `'b` must outlive `'c`
|
= help: consider adding the following bound: `'b: 'c`
help: add bound `'b: 'a + 'c`
error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5
|
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
LL | a(x, y, z);
| ^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to &isize
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5
|
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
| -- -- lifetime `'c` defined here
| |
| lifetime `'b` defined here
...
LL | a(x, y, z);
| ^^^^^^^^^^ argument requires that `'b` must outlive `'c`
|
= help: consider adding the following bound: `'b: 'c`
= note: requirement occurs because of a mutable reference to &isize
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: add bound `'b: 'a + 'c`
error: higher-ranked subtype error
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where 'b: 'a + 'c { fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where 'b: 'a + 'c {
// Note: this is legal because of the `'b:'a` declaration. // Note: this is legal because of the `'b:'a` declaration.
*x = *y; *x = *y;
@ -6,20 +10,27 @@ fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where
fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
// Illegal now because there is no `'b:'a` declaration. // Illegal now because there is no `'b:'a` declaration.
*x = *y; //~ ERROR E0623 *x = *y;
*z = *y; //~ ERROR E0623 //[base]~^ ERROR E0623
//[nll]~^^ ERROR lifetime may not live long enough
*z = *y; //[base]~ ERROR E0623
} }
fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
// Here we try to call `foo` but do not know that `'a` and `'b` are // Here we try to call `foo` but do not know that `'a` and `'b` are
// related as required. // related as required.
a(x, y, z); //~ ERROR lifetime mismatch [E0623] a(x, y, z);
//[base]~^ ERROR lifetime mismatch [E0623]
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn d() { fn d() {
// 'a and 'b are early bound in the function `a` because they appear // 'a and 'b are early bound in the function `a` because they appear
// inconstraints: // inconstraints:
let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
//~^ ERROR E0308
//[nll]~^^ ERROR mismatched types [E0308]
//[nll]~| ERROR mismatched types [E0308]
} }
fn e() { fn e() {

View file

@ -1,26 +1,26 @@
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> $DIR/region-object-lifetime-2.rs:10:7 --> $DIR/region-object-lifetime-2.rs:14:7
| |
LL | x.borrowed() LL | x.borrowed()
| ^^^^^^^^ | ^^^^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here... note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/region-object-lifetime-2.rs:9:42 --> $DIR/region-object-lifetime-2.rs:13:42
| |
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| ^^ | ^^
note: ...so that reference does not outlive borrowed content note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-2.rs:10:5 --> $DIR/region-object-lifetime-2.rs:14:5
| |
LL | x.borrowed() LL | x.borrowed()
| ^ | ^
note: but, the lifetime must be valid for the lifetime `'b` as defined here... note: but, the lifetime must be valid for the lifetime `'b` as defined here...
--> $DIR/region-object-lifetime-2.rs:9:45 --> $DIR/region-object-lifetime-2.rs:13:45
| |
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| ^^ | ^^
note: ...so that reference does not outlive borrowed content note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-2.rs:10:5 --> $DIR/region-object-lifetime-2.rs:14:5
| |
LL | x.borrowed() LL | x.borrowed()
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-2.rs:10:5 --> $DIR/region-object-lifetime-2.rs:14:5
| |
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -1,13 +1,19 @@
// Various tests related to testing how region inference works // Various tests related to testing how region inference works
// with respect to the object receivers. // with respect to the object receivers.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait Foo { trait Foo {
fn borrowed<'a>(&'a self) -> &'a (); fn borrowed<'a>(&'a self) -> &'a ();
} }
// Borrowed receiver but two distinct lifetimes, we get an error. // Borrowed receiver but two distinct lifetimes, we get an error.
fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer x.borrowed()
//[base]~^ ERROR cannot infer
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() {} fn main() {}

View file

@ -1,26 +1,26 @@
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> $DIR/region-object-lifetime-4.rs:12:7 --> $DIR/region-object-lifetime-4.rs:16:7
| |
LL | x.borrowed() LL | x.borrowed()
| ^^^^^^^^ | ^^^^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here... note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/region-object-lifetime-4.rs:11:41 --> $DIR/region-object-lifetime-4.rs:15:41
| |
LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| ^^ | ^^
note: ...so that reference does not outlive borrowed content note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-4.rs:12:5 --> $DIR/region-object-lifetime-4.rs:16:5
| |
LL | x.borrowed() LL | x.borrowed()
| ^ | ^
note: but, the lifetime must be valid for the lifetime `'b` as defined here... note: but, the lifetime must be valid for the lifetime `'b` as defined here...
--> $DIR/region-object-lifetime-4.rs:11:44 --> $DIR/region-object-lifetime-4.rs:15:44
| |
LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| ^^ | ^^
note: ...so that reference does not outlive borrowed content note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-4.rs:12:5 --> $DIR/region-object-lifetime-4.rs:16:5
| |
LL | x.borrowed() LL | x.borrowed()
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-4.rs:12:5 --> $DIR/region-object-lifetime-4.rs:16:5
| |
LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -1,6 +1,10 @@
// Various tests related to testing how region inference works // Various tests related to testing how region inference works
// with respect to the object receivers. // with respect to the object receivers.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait Foo { trait Foo {
fn borrowed<'a>(&'a self) -> &'a (); fn borrowed<'a>(&'a self) -> &'a ();
} }
@ -9,7 +13,9 @@ trait Foo {
// with the longer lifetime when (from the signature) we only know // with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error. // that it lives as long as the shorter lifetime. Therefore, error.
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer x.borrowed()
//[base]~^ ERROR cannot infer
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/region-object-lifetime-in-coercion.rs:8:46 --> $DIR/region-object-lifetime-in-coercion.rs:12:46
| |
LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> { LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
@ -16,7 +16,7 @@ LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
| ~~~~~~~~~~~~~ | ~~~~~~~~~~~~~
error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/region-object-lifetime-in-coercion.rs:13:14 --> $DIR/region-object-lifetime-in-coercion.rs:19:14
| |
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> { LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
@ -24,7 +24,7 @@ LL | Box::new(v)
| ^ ...is used and required to live as long as `'static` here | ^ ...is used and required to live as long as `'static` here
| |
note: `'static` lifetime requirement introduced by the return type note: `'static` lifetime requirement introduced by the return type
--> $DIR/region-object-lifetime-in-coercion.rs:12:33 --> $DIR/region-object-lifetime-in-coercion.rs:18:33
| |
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> { LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| ^^^^^^^ `'static` requirement introduced here | ^^^^^^^ `'static` requirement introduced here
@ -40,7 +40,7 @@ LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
| ~~~~~~~~~~~~~ | ~~~~~~~~~~~~~
error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/region-object-lifetime-in-coercion.rs:19:14 --> $DIR/region-object-lifetime-in-coercion.rs:27:14
| |
LL | fn c(v: &[u8]) -> Box<dyn Foo> { LL | fn c(v: &[u8]) -> Box<dyn Foo> {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
@ -49,7 +49,7 @@ LL | Box::new(v)
| ^ ...is used and required to live as long as `'static` here | ^ ...is used and required to live as long as `'static` here
| |
note: `'static` lifetime requirement introduced by the return type note: `'static` lifetime requirement introduced by the return type
--> $DIR/region-object-lifetime-in-coercion.rs:16:23 --> $DIR/region-object-lifetime-in-coercion.rs:24:23
| |
LL | fn c(v: &[u8]) -> Box<dyn Foo> { LL | fn c(v: &[u8]) -> Box<dyn Foo> {
| ^^^^^^^ `'static` requirement introduced here | ^^^^^^^ `'static` requirement introduced here
@ -62,30 +62,30 @@ LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {
| ++++ | ++++
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/region-object-lifetime-in-coercion.rs:23:14 --> $DIR/region-object-lifetime-in-coercion.rs:33:14
| |
LL | Box::new(v) LL | Box::new(v)
| ^ | ^
| |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here... note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/region-object-lifetime-in-coercion.rs:22:6 --> $DIR/region-object-lifetime-in-coercion.rs:32:6
| |
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^ | ^^
note: ...so that the expression is assignable note: ...so that the expression is assignable
--> $DIR/region-object-lifetime-in-coercion.rs:23:14 --> $DIR/region-object-lifetime-in-coercion.rs:33:14
| |
LL | Box::new(v) LL | Box::new(v)
| ^ | ^
= note: expected `&[u8]` = note: expected `&[u8]`
found `&'a [u8]` found `&'a [u8]`
note: but, the lifetime must be valid for the lifetime `'b` as defined here... note: but, the lifetime must be valid for the lifetime `'b` as defined here...
--> $DIR/region-object-lifetime-in-coercion.rs:22:9 --> $DIR/region-object-lifetime-in-coercion.rs:32:9
| |
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^ | ^^
note: ...so that the types are compatible note: ...so that the types are compatible
--> $DIR/region-object-lifetime-in-coercion.rs:23:5 --> $DIR/region-object-lifetime-in-coercion.rs:33:5
| |
LL | Box::new(v) LL | Box::new(v)
| ^^^^^^^^^^^ | ^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:8:12 --> $DIR/region-object-lifetime-in-coercion.rs:12:12
| |
LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> { LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
@ -7,7 +7,7 @@ LL | let x: Box<dyn Foo + 'static> = Box::new(v);
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:13:5 --> $DIR/region-object-lifetime-in-coercion.rs:19:5
| |
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> { LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
@ -15,7 +15,7 @@ LL | Box::new(v)
| ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:19:5 --> $DIR/region-object-lifetime-in-coercion.rs:27:5
| |
LL | fn c(v: &[u8]) -> Box<dyn Foo> { LL | fn c(v: &[u8]) -> Box<dyn Foo> {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
@ -24,7 +24,7 @@ LL | Box::new(v)
| ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:23:5 --> $DIR/region-object-lifetime-in-coercion.rs:33:5
| |
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -1,26 +1,38 @@
// Test that attempts to implicitly coerce a value into an // Test that attempts to implicitly coerce a value into an
// object respect the lifetime bound on the object type. // object respect the lifetime bound on the object type.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait Foo {} trait Foo {}
impl<'a> Foo for &'a [u8] {} impl<'a> Foo for &'a [u8] {}
fn a(v: &[u8]) -> Box<dyn Foo + 'static> { fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR E0759 let x: Box<dyn Foo + 'static> = Box::new(v);
//[base]~^ ERROR E0759
//[nll]~^^ ERROR lifetime may not live long enough
x x
} }
fn b(v: &[u8]) -> Box<dyn Foo + 'static> { fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
Box::new(v) //~ ERROR E0759 Box::new(v)
//[base]~^ ERROR E0759
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn c(v: &[u8]) -> Box<dyn Foo> { fn c(v: &[u8]) -> Box<dyn Foo> {
// same as previous case due to RFC 599 // same as previous case due to RFC 599
Box::new(v) //~ ERROR E0759 Box::new(v)
//[base]~^ ERROR E0759
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
Box::new(v) //~ ERROR cannot infer an appropriate lifetime due to conflicting Box::new(v)
//[base]~^ ERROR cannot infer an appropriate lifetime due to conflicting
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn e<'a:'b,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> { fn e<'a:'b,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {

View file

@ -1,5 +1,5 @@
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/regions-addr-of-self.rs:7:37 --> $DIR/regions-addr-of-self.rs:11:37
| |
LL | pub fn chase_cat(&mut self) { LL | pub fn chase_cat(&mut self) {
| --------- this data with an anonymous lifetime `'_`... | --------- this data with an anonymous lifetime `'_`...

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-addr-of-self.rs:7:16 --> $DIR/regions-addr-of-self.rs:11:16
| |
LL | pub fn chase_cat(&mut self) { LL | pub fn chase_cat(&mut self) {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`

View file

@ -1,10 +1,16 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct Dog { struct Dog {
cats_chased: usize, cats_chased: usize,
} }
impl Dog { impl Dog {
pub fn chase_cat(&mut self) { pub fn chase_cat(&mut self) {
let p: &'static mut usize = &mut self.cats_chased; //~ ERROR E0759 let p: &'static mut usize = &mut self.cats_chased;
//[base]~^ ERROR E0759
//[nll]~^^ ERROR lifetime may not live long enough
*p += 1; *p += 1;
} }

View file

@ -1,22 +1,22 @@
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/regions-addr-of-upvar-self.rs:8:41 --> $DIR/regions-addr-of-upvar-self.rs:12:41
| |
LL | let p: &'static mut usize = &mut self.food; LL | let p: &'static mut usize = &mut self.food;
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'_` as defined here... note: first, the lifetime cannot outlive the lifetime `'_` as defined here...
--> $DIR/regions-addr-of-upvar-self.rs:7:18 --> $DIR/regions-addr-of-upvar-self.rs:11:18
| |
LL | let _f = || { LL | let _f = || {
| ^^ | ^^
note: ...so that closure can access `self` note: ...so that closure can access `self`
--> $DIR/regions-addr-of-upvar-self.rs:8:41 --> $DIR/regions-addr-of-upvar-self.rs:12:41
| |
LL | let p: &'static mut usize = &mut self.food; LL | let p: &'static mut usize = &mut self.food;
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime... = note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content note: ...so that reference does not outlive borrowed content
--> $DIR/regions-addr-of-upvar-self.rs:8:41 --> $DIR/regions-addr-of-upvar-self.rs:12:41
| |
LL | let p: &'static mut usize = &mut self.food; LL | let p: &'static mut usize = &mut self.food;
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-addr-of-upvar-self.rs:8:20 --> $DIR/regions-addr-of-upvar-self.rs:12:20
| |
LL | let _f = || { LL | let _f = || {
| -- lifetime `'1` represents this closure's body | -- lifetime `'1` represents this closure's body
@ -9,7 +9,7 @@ LL | let p: &'static mut usize = &mut self.food;
= note: closure implements `FnMut`, so references to captured variables can't escape the closure = note: closure implements `FnMut`, so references to captured variables can't escape the closure
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-addr-of-upvar-self.rs:8:20 --> $DIR/regions-addr-of-upvar-self.rs:12:20
| |
LL | pub fn chase_cat(&mut self) { LL | pub fn chase_cat(&mut self) {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
@ -18,7 +18,7 @@ LL | let p: &'static mut usize = &mut self.food;
| ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
error[E0597]: `self` does not live long enough error[E0597]: `self` does not live long enough
--> $DIR/regions-addr-of-upvar-self.rs:8:46 --> $DIR/regions-addr-of-upvar-self.rs:12:46
| |
LL | let _f = || { LL | let _f = || {
| -- value captured here | -- value captured here

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct Dog { struct Dog {
food: usize, food: usize,
} }
@ -5,7 +9,11 @@ struct Dog {
impl Dog { impl Dog {
pub fn chase_cat(&mut self) { pub fn chase_cat(&mut self) {
let _f = || { let _f = || {
let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer let p: &'static mut usize = &mut self.food;
//[base]~^ ERROR cannot infer
//[nll]~^^ ERROR lifetime may not live long enough
//[nll]~^^^ ERROR lifetime may not live long enough
//[nll]~^^^^ ERROR E0597
*p = 3; *p = 3;
}; };
} }

View file

@ -1,71 +1,71 @@
error[E0477]: the type `&'a isize` does not fulfill the required lifetime error[E0477]: the type `&'a isize` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:22:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5
| |
LL | assert_send::<&'a isize>(); LL | assert_send::<&'a isize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^
error[E0477]: the type `&'a str` does not fulfill the required lifetime error[E0477]: the type `&'a str` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:32:5
| |
LL | assert_send::<&'a str>(); LL | assert_send::<&'a str>();
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^
error[E0477]: the type `&'a [isize]` does not fulfill the required lifetime error[E0477]: the type `&'a [isize]` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:30:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:38:5
| |
LL | assert_send::<&'a [isize]>(); LL | assert_send::<&'a [isize]>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^
error[E0477]: the type `Box<&'a isize>` does not fulfill the required lifetime error[E0477]: the type `Box<&'a isize>` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:44:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:54:5
| |
LL | assert_send::<Box<&'a isize>>(); LL | assert_send::<Box<&'a isize>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^
error[E0477]: the type `*const &'a isize` does not fulfill the required lifetime error[E0477]: the type `*const &'a isize` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:55:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:67:5
| |
LL | assert_send::<*const &'a isize>(); LL | assert_send::<*const &'a isize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^
error[E0477]: the type `*mut &'a isize` does not fulfill the required lifetime error[E0477]: the type `*mut &'a isize` does not fulfill the required lifetime
--> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:73:5
| |
LL | assert_send::<*mut &'a isize>(); LL | assert_send::<*mut &'a isize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-by-trait-requiring-static.rs:6:18 --> $DIR/regions-bounded-by-trait-requiring-static.rs:10:18
| |
LL | fn assert_send<T:'static>() { } LL | fn assert_send<T:'static>() { }
| ^^^^^^^ | ^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:22:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5
| |
LL | fn param_not_ok<'a>(x: &'a isize) { LL | fn param_not_ok<'a>(x: &'a isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -7,7 +7,7 @@ LL | assert_send::<&'a isize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:32:5
| |
LL | fn param_not_ok1<'a>(_: &'a isize) { LL | fn param_not_ok1<'a>(_: &'a isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -15,7 +15,7 @@ LL | assert_send::<&'a str>();
| ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:30:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:38:5
| |
LL | fn param_not_ok2<'a>(_: &'a isize) { LL | fn param_not_ok2<'a>(_: &'a isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -23,7 +23,7 @@ LL | assert_send::<&'a [isize]>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:44:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:54:5
| |
LL | fn box_with_region_not_ok<'a>() { LL | fn box_with_region_not_ok<'a>() {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -31,7 +31,7 @@ LL | assert_send::<Box<&'a isize>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:55:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:67:5
| |
LL | fn unsafe_ok2<'a>(_: &'a isize) { LL | fn unsafe_ok2<'a>(_: &'a isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -39,7 +39,7 @@ LL | assert_send::<*const &'a isize>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5 --> $DIR/regions-bounded-by-trait-requiring-static.rs:73:5
| |
LL | fn unsafe_ok3<'a>(_: &'a isize) { LL | fn unsafe_ok3<'a>(_: &'a isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here

View file

@ -2,6 +2,10 @@
// in this file all test region bound and lifetime violations that are // in this file all test region bound and lifetime violations that are
// detected during type check. // detected during type check.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait Dummy : 'static { } trait Dummy : 'static { }
fn assert_send<T:'static>() { } fn assert_send<T:'static>() { }
@ -19,15 +23,21 @@ fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
// otherwise lifetime pointers are not ok // otherwise lifetime pointers are not ok
fn param_not_ok<'a>(x: &'a isize) { fn param_not_ok<'a>(x: &'a isize) {
assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime assert_send::<&'a isize>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn param_not_ok1<'a>(_: &'a isize) { fn param_not_ok1<'a>(_: &'a isize) {
assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime assert_send::<&'a str>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn param_not_ok2<'a>(_: &'a isize) { fn param_not_ok2<'a>(_: &'a isize) {
assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime assert_send::<&'a [isize]>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
// boxes are ok // boxes are ok
@ -41,7 +51,9 @@ fn box_ok() {
// but not if they own a bad thing // but not if they own a bad thing
fn box_with_region_not_ok<'a>() { fn box_with_region_not_ok<'a>() {
assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime assert_send::<Box<&'a isize>>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
// raw pointers are ok unless they point at unsendable things // raw pointers are ok unless they point at unsendable things
@ -52,11 +64,15 @@ fn unsafe_ok1<'a>(_: &'a isize) {
} }
fn unsafe_ok2<'a>(_: &'a isize) { fn unsafe_ok2<'a>(_: &'a isize) {
assert_send::<*const &'a isize>(); //~ ERROR does not fulfill the required lifetime assert_send::<*const &'a isize>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn unsafe_ok3<'a>(_: &'a isize) { fn unsafe_ok3<'a>(_: &'a isize) {
assert_send::<*mut &'a isize>(); //~ ERROR does not fulfill the required lifetime assert_send::<*mut &'a isize>();
//[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() { fn main() {

View file

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:20:7 --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:23:7
| |
LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) { LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
| ------- ------- these two types are declared with different lifetimes... | ------- ------- these two types are declared with different lifetimes...

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:20:5 --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:23:5
| |
LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) { LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
| -- -- lifetime `'y` defined here | -- -- lifetime `'y` defined here

View file

@ -1,4 +1,7 @@
// aux-build:rbmtp_cross_crate_lib.rs // aux-build:rbmtp_cross_crate_lib.rs
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
// Check explicit region bounds on methods in the cross crate case. // Check explicit region bounds on methods in the cross crate case.
@ -17,7 +20,9 @@ fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {
fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) { fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
// Here the value provided for 'y is 'y, and hence 'y:'x does not hold. // Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
a.bigger_region(b) //~ ERROR lifetime mismatch [E0623] a.bigger_region(b)
//[base]~^ ERROR lifetime mismatch [E0623]
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() { } fn main() { }

View file

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch error[E0623]: lifetime mismatch
--> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:7 --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:24:7
| |
LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
| ------- ------- these two types are declared with different lifetimes... | ------- ------- these two types are declared with different lifetimes...

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5 --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:24:5
| |
LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -2,6 +2,10 @@
// nominal types (but not on other types) and that they are type // nominal types (but not on other types) and that they are type
// checked. // checked.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct Inv<'a> { // invariant w/r/t 'a struct Inv<'a> { // invariant w/r/t 'a
x: &'a mut &'a isize x: &'a mut &'a isize
} }
@ -17,7 +21,9 @@ fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
// Here the value provided for 'y is 'b, and hence 'b:'a does not hold. // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
f.method(b); //~ ERROR lifetime mismatch [E0623] f.method(b);
//[base]~^ ERROR lifetime mismatch [E0623]
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {

View file

@ -1,11 +1,11 @@
error[E0477]: the type `&'a isize` does not fulfill the required lifetime error[E0477]: the type `&'a isize` does not fulfill the required lifetime
--> $DIR/regions-bounded-method-type-parameters.rs:12:9 --> $DIR/regions-bounded-method-type-parameters.rs:16:9
| |
LL | Foo.some_method::<&'a isize>(); LL | Foo.some_method::<&'a isize>();
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
note: type must satisfy the static lifetime as required by this binding note: type must satisfy the static lifetime as required by this binding
--> $DIR/regions-bounded-method-type-parameters.rs:8:22 --> $DIR/regions-bounded-method-type-parameters.rs:12:22
| |
LL | fn some_method<A:'static>(self) { } LL | fn some_method<A:'static>(self) { }
| ^^^^^^^ | ^^^^^^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounded-method-type-parameters.rs:12:9 --> $DIR/regions-bounded-method-type-parameters.rs:16:9
| |
LL | fn caller<'a>(x: &isize) { LL | fn caller<'a>(x: &isize) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here

View file

@ -2,6 +2,10 @@
// nominal types (but not on other types) and that they are type // nominal types (but not on other types) and that they are type
// checked. // checked.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct Foo; struct Foo;
impl Foo { impl Foo {
@ -10,7 +14,8 @@ impl Foo {
fn caller<'a>(x: &isize) { fn caller<'a>(x: &isize) {
Foo.some_method::<&'a isize>(); Foo.some_method::<&'a isize>();
//~^ ERROR does not fulfill the required lifetime //[base]~^ ERROR does not fulfill the required lifetime
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() { } fn main() { }

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/regions-bounds.rs:9:12 --> $DIR/regions-bounds.rs:13:12
| |
LL | return e; LL | return e;
| ^ lifetime mismatch | ^ lifetime mismatch
@ -7,18 +7,18 @@ LL | return e;
= note: expected struct `TupleStruct<'b>` = note: expected struct `TupleStruct<'b>`
found struct `TupleStruct<'a>` found struct `TupleStruct<'a>`
note: the lifetime `'a` as defined here... note: the lifetime `'a` as defined here...
--> $DIR/regions-bounds.rs:8:10 --> $DIR/regions-bounds.rs:12:10
| |
LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
| ^^ | ^^
note: ...does not necessarily outlive the lifetime `'b` as defined here note: ...does not necessarily outlive the lifetime `'b` as defined here
--> $DIR/regions-bounds.rs:8:13 --> $DIR/regions-bounds.rs:12:13
| |
LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
| ^^ | ^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/regions-bounds.rs:13:12 --> $DIR/regions-bounds.rs:19:12
| |
LL | return e; LL | return e;
| ^ lifetime mismatch | ^ lifetime mismatch
@ -26,12 +26,12 @@ LL | return e;
= note: expected struct `Struct<'b>` = note: expected struct `Struct<'b>`
found struct `Struct<'a>` found struct `Struct<'a>`
note: the lifetime `'a` as defined here... note: the lifetime `'a` as defined here...
--> $DIR/regions-bounds.rs:12:10 --> $DIR/regions-bounds.rs:18:10
| |
LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
| ^^ | ^^
note: ...does not necessarily outlive the lifetime `'b` as defined here note: ...does not necessarily outlive the lifetime `'b` as defined here
--> $DIR/regions-bounds.rs:12:13 --> $DIR/regions-bounds.rs:18:13
| |
LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
| ^^ | ^^

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounds.rs:9:12 --> $DIR/regions-bounds.rs:13:12
| |
LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
@ -11,7 +11,7 @@ LL | return e;
= help: consider adding the following bound: `'a: 'b` = help: consider adding the following bound: `'a: 'b`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-bounds.rs:13:12 --> $DIR/regions-bounds.rs:19:12
| |
LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -2,15 +2,23 @@
// nominal types (but not on other types) and that they are type // nominal types (but not on other types) and that they are type
// checked. // checked.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
struct TupleStruct<'a>(&'a isize); struct TupleStruct<'a>(&'a isize);
struct Struct<'a> { x:&'a isize } struct Struct<'a> { x:&'a isize }
fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
return e; //~ ERROR mismatched types return e;
//[base]~^ ERROR mismatched types
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
return e; //~ ERROR mismatched types return e;
//[base]~^ ERROR mismatched types
//[nll]~^^ ERROR lifetime may not live long enough
} }
fn main() { } fn main() { }

View file

@ -1,5 +1,5 @@
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:15:5 --> $DIR/regions-close-associated-type-into-object.rs:19:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | Box::new(item)
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:22:5 --> $DIR/regions-close-associated-type-into-object.rs:26:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | Box::new(item)
= note: ...so that the type `Box<<T as Iter>::Item>` will meet its required lifetime bounds = note: ...so that the type `Box<<T as Iter>::Item>` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:28:5 --> $DIR/regions-close-associated-type-into-object.rs:32:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -26,7 +26,7 @@ LL | Box::new(item)
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:35:5 --> $DIR/regions-close-associated-type-into-object.rs:39:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:15:5 --> $DIR/regions-close-associated-type-into-object.rs:19:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | Box::new(item)
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:22:5 --> $DIR/regions-close-associated-type-into-object.rs:26:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | Box::new(item)
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:28:5 --> $DIR/regions-close-associated-type-into-object.rs:32:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -26,7 +26,7 @@ LL | Box::new(item)
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:35:5 --> $DIR/regions-close-associated-type-into-object.rs:39:5
| |
LL | Box::new(item) LL | Box::new(item)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait X {} trait X {}

View file

@ -1,5 +1,5 @@
error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/regions-close-object-into-object-2.rs:9:16 --> $DIR/regions-close-object-into-object-2.rs:13:16
| |
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> { LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| ------------------ this data with lifetime `'a`... | ------------------ this data with lifetime `'a`...
@ -7,7 +7,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...is used and required to live as long as `'static` here | ^^^ ...is used and required to live as long as `'static` here
| |
note: `'static` lifetime requirement introduced by the return type note: `'static` lifetime requirement introduced by the return type
--> $DIR/regions-close-object-into-object-2.rs:8:60 --> $DIR/regions-close-object-into-object-2.rs:12:60
| |
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> { LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| ^^^^^^^ `'static` requirement introduced here | ^^^^^^^ `'static` requirement introduced here

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-2.rs:9:5 --> $DIR/regions-close-object-into-object-2.rs:13:5
| |
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> { LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -7,7 +7,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
error[E0515]: cannot return value referencing local data `*v` error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-2.rs:9:5 --> $DIR/regions-close-object-into-object-2.rs:13:5
| |
LL | Box::new(B(&*v)) as Box<dyn X> LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait A<T> { } trait A<T> { }
struct B<'a, T:'a>(&'a (dyn A<T> + 'a)); struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
@ -6,7 +10,10 @@ trait X { }
impl<'a, T> X for B<'a, T> {} impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> { fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
Box::new(B(&*v)) as Box<dyn X> //~ ERROR E0759 Box::new(B(&*v)) as Box<dyn X>
//[base]~^ ERROR E0759
//[nll]~^^ ERROR lifetime may not live long enough
//[nll]~| ERROR cannot return value referencing local data `*v` [E0515]
} }
fn main() { } fn main() { }

View file

@ -1,5 +1,5 @@
error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/regions-close-object-into-object-4.rs:9:16 --> $DIR/regions-close-object-into-object-4.rs:13:16
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| ---------------- this data with lifetime `'a`... | ---------------- this data with lifetime `'a`...
@ -7,7 +7,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...is used and required to live as long as `'static` here | ^^^ ...is used and required to live as long as `'static` here
| |
note: `'static` lifetime requirement introduced by the return type note: `'static` lifetime requirement introduced by the return type
--> $DIR/regions-close-object-into-object-4.rs:8:52 --> $DIR/regions-close-object-into-object-4.rs:12:52
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| ^^^^^^^ `'static` requirement introduced here | ^^^^^^^ `'static` requirement introduced here

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `U` may not live long enough error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5 --> $DIR/regions-close-object-into-object-4.rs:13:5
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static` | - help: consider adding an explicit lifetime bound...: `U: 'static`
@ -7,7 +7,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds | ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error[E0310]: the parameter type `U` may not live long enough error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5 --> $DIR/regions-close-object-into-object-4.rs:13:5
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static` | - help: consider adding an explicit lifetime bound...: `U: 'static`
@ -15,7 +15,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error[E0310]: the parameter type `U` may not live long enough error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5 --> $DIR/regions-close-object-into-object-4.rs:13:5
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static` | - help: consider adding an explicit lifetime bound...: `U: 'static`
@ -23,7 +23,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5 --> $DIR/regions-close-object-into-object-4.rs:13:5
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -31,7 +31,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
error[E0515]: cannot return value referencing local data `*v` error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-4.rs:9:5 --> $DIR/regions-close-object-into-object-4.rs:13:5
| |
LL | Box::new(B(&*v)) as Box<dyn X> LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
@ -40,7 +40,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| returns a value referencing data owned by the current function | returns a value referencing data owned by the current function
error[E0310]: the parameter type `U` may not live long enough error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:14 --> $DIR/regions-close-object-into-object-4.rs:13:14
| |
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| - help: consider adding an explicit lifetime bound...: `U: 'static` | - help: consider adding an explicit lifetime bound...: `U: 'static`

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait A<T> { } trait A<T> { }
struct B<'a, T:'a>(&'a (dyn A<T> + 'a)); struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
@ -6,7 +10,15 @@ trait X { }
impl<'a, T> X for B<'a, T> {} impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> { fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
Box::new(B(&*v)) as Box<dyn X> //~ ERROR E0759 Box::new(B(&*v)) as Box<dyn X>
//[base]~^ ERROR E0759
//[nll]~^^ ERROR the parameter type `U` may not live long enough [E0310]
//[nll]~| ERROR the parameter type `U` may not live long enough [E0310]
//[nll]~| ERROR the parameter type `U` may not live long enough [E0310]
//[nll]~| ERROR lifetime may not live long enough
//[nll]~| ERROR cannot return value referencing local data `*v` [E0515]
//[nll]~| ERROR the parameter type `U` may not live long enough [E0310]
} }
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -8,13 +8,13 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
| |
note: ...that is required by this bound note: ...that is required by this bound
--> $DIR/regions-close-object-into-object-5.rs:9:17 --> $DIR/regions-close-object-into-object-5.rs:13:17
| |
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a)); LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^ | ^^
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -23,7 +23,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:14 --> $DIR/regions-close-object-into-object-5.rs:21:14
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -32,13 +32,13 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^ ...so that the type `T` will meet its required lifetime bounds... | ^ ...so that the type `T` will meet its required lifetime bounds...
| |
note: ...that is required by this bound note: ...that is required by this bound
--> $DIR/regions-close-object-into-object-5.rs:9:17 --> $DIR/regions-close-object-into-object-5.rs:13:17
| |
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a)); LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^ | ^^
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:14 --> $DIR/regions-close-object-into-object-5.rs:21:14
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -47,13 +47,13 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^ ...so that the type `T` will meet its required lifetime bounds... | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
| |
note: ...that is required by this bound note: ...that is required by this bound
--> $DIR/regions-close-object-into-object-5.rs:9:17 --> $DIR/regions-close-object-into-object-5.rs:13:17
| |
LL | struct B<'a, T: 'a>(&'a (A<T> + 'a)); LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
| ^^ | ^^
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:16 --> $DIR/regions-close-object-into-object-5.rs:21:16
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -62,7 +62,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at | ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:16 --> $DIR/regions-close-object-into-object-5.rs:21:16
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -71,7 +71,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long | ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:16 --> $DIR/regions-close-object-into-object-5.rs:21:16
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -8,7 +8,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -17,7 +17,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`
@ -26,7 +26,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0515]: cannot return value referencing local data `*v` error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-5.rs:17:5 --> $DIR/regions-close-object-into-object-5.rs:21:5
| |
LL | Box::new(B(&*v)) as Box<dyn X> LL | Box::new(B(&*v)) as Box<dyn X>
| ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
@ -35,7 +35,7 @@ LL | Box::new(B(&*v)) as Box<dyn X>
| returns a value referencing data owned by the current function | returns a value referencing data owned by the current function
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:14 --> $DIR/regions-close-object-into-object-5.rs:21:14
| |
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> { LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static` | - help: consider adding an explicit lifetime bound...: `T: 'static`

View file

@ -1,3 +1,7 @@
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
#![allow(warnings)] #![allow(warnings)]
@ -19,9 +23,10 @@ fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
//~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough //[base]~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough //[base]~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough //[base]~| ERROR the parameter type `T` may not live long enough
//[nll]~| ERROR cannot return value referencing local data `*v` [E0515]
} }
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `A` may not live long enough error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:12:5 --> $DIR/regions-close-over-type-parameter-1.rs:15:5
| |
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> { LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +` | -- help: consider adding an explicit lifetime bound...: `A: 'static +`
@ -7,7 +7,7 @@ LL | Box::new(v) as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error[E0309]: the parameter type `A` may not live long enough error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:21:5 --> $DIR/regions-close-over-type-parameter-1.rs:24:5
| |
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> { LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +` | -- help: consider adding an explicit lifetime bound...: `A: 'b +`

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `A` may not live long enough error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:12:5 --> $DIR/regions-close-over-type-parameter-1.rs:15:5
| |
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> { LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +` | -- help: consider adding an explicit lifetime bound...: `A: 'static +`
@ -7,7 +7,7 @@ LL | Box::new(v) as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error[E0309]: the parameter type `A` may not live long enough error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:21:5 --> $DIR/regions-close-over-type-parameter-1.rs:24:5
| |
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> { LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +` | -- help: consider adding an explicit lifetime bound...: `A: 'b +`

View file

@ -2,6 +2,9 @@
// an object. This should yield errors unless `A` (and the object) // an object. This should yield errors unless `A` (and the object)
// both have suitable bounds. // both have suitable bounds.
// revisions: base nll
// ignore-compare-mode-nll
//[nll] compile-flags: -Z borrowck=mir
trait SomeTrait { trait SomeTrait {
fn get(&self) -> isize; fn get(&self) -> isize;

Some files were not shown because too many files have changed in this diff Show more