Auto merge of #119889 - GuillaumeGomez:rollup-ah3dhya, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #119817 (Remove special-casing around `AliasKind::Opaque` when structurally resolving in new solver) - #119819 (Check rust lints when an unknown lint is detected) - #119872 (Give me a way to emit all the delayed bugs as errors (add `-Zeagerly-emit-delayed-bugs`)) - #119877 (Add more information to `visit_projection_elem`) - #119884 (Rename `--env` option flag to `--env-set`) - #119885 (Revert #113923) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ce1f2ccf5a
@ -18,7 +18,7 @@ fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Option<Symbol> {
|
||||
if let Some(value) = cx.sess.opts.logical_env.get(var) {
|
||||
return Some(Symbol::intern(value));
|
||||
}
|
||||
// If the environment variable was not defined with the `--env` option, we try to retrieve it
|
||||
// If the environment variable was not defined with the `--env-set` option, we try to retrieve it
|
||||
// from rustc's environment.
|
||||
env::var(var).ok().as_deref().map(Symbol::intern)
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ fn prepare_lto(
|
||||
};
|
||||
|
||||
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
|
||||
if info.level.is_below_threshold(export_threshold) || info.used || info.used_compiler {
|
||||
if info.level.is_below_threshold(export_threshold) || info.used {
|
||||
Some(CString::new(name.as_str()).unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -569,6 +569,7 @@ pub(crate) unsafe fn llvm_optimize(
|
||||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
@ -677,6 +678,7 @@ pub(crate) unsafe fn codegen(
|
||||
unsafe fn with_codegen<'ll, F, R>(
|
||||
tm: &'ll llvm::TargetMachine,
|
||||
llmod: &'ll llvm::Module,
|
||||
no_builtins: bool,
|
||||
f: F,
|
||||
) -> R
|
||||
where
|
||||
@ -684,7 +686,7 @@ pub(crate) unsafe fn codegen(
|
||||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm)
|
||||
}
|
||||
|
||||
@ -785,7 +787,7 @@ pub(crate) unsafe fn codegen(
|
||||
} else {
|
||||
llmod
|
||||
};
|
||||
with_codegen(tm, llmod, |cpm| {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
@ -820,7 +822,7 @@ pub(crate) unsafe fn codegen(
|
||||
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
|
||||
};
|
||||
|
||||
with_codegen(tm, llmod, |cpm| {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
|
@ -2173,8 +2173,13 @@ extern "C" {
|
||||
ArgsCstrBuff: *const c_char,
|
||||
ArgsCstrBuffLen: usize,
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(PM: &PassManager<'a>, M: &'a Module);
|
||||
pub fn LLVMRustAddLibraryInfo<'a>(
|
||||
PM: &PassManager<'a>,
|
||||
M: &'a Module,
|
||||
DisableSimplifyLibCalls: bool,
|
||||
);
|
||||
pub fn LLVMRustWriteOutputFile<'a>(
|
||||
T: &'a TargetMachine,
|
||||
PM: &PassManager<'a>,
|
||||
@ -2196,6 +2201,7 @@ extern "C" {
|
||||
UnrollLoops: bool,
|
||||
SLPVectorize: bool,
|
||||
LoopVectorize: bool,
|
||||
DisableSimplifyLibCalls: bool,
|
||||
EmitLifetimeMarkers: bool,
|
||||
SanitizerOptions: Option<&SanitizerOptions>,
|
||||
PGOGenPath: *const c_char,
|
||||
|
@ -270,14 +270,8 @@ pub fn each_linked_rlib(
|
||||
|
||||
for &cnum in crates {
|
||||
match fmts.get(cnum.as_usize() - 1) {
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue,
|
||||
Some(&Linkage::IncludedFromDylib) => {
|
||||
// We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well.
|
||||
if info.compiler_builtins != Some(cnum) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(&Linkage::Static) => {}
|
||||
Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
|
||||
Some(_) => {}
|
||||
None => return Err(errors::LinkRlibError::MissingFormat),
|
||||
}
|
||||
let crate_name = info.crate_name[&cnum];
|
||||
@ -526,7 +520,8 @@ fn link_staticlib<'a>(
|
||||
&codegen_results.crate_info,
|
||||
Some(CrateType::Staticlib),
|
||||
&mut |cnum, path| {
|
||||
let lto = are_upstream_rust_objects_already_included(sess);
|
||||
let lto = are_upstream_rust_objects_already_included(sess)
|
||||
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
|
||||
|
||||
let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
|
||||
let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
|
||||
@ -1277,6 +1272,24 @@ fn link_sanitizer_runtime(
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a boolean indicating whether the specified crate should be ignored
|
||||
/// during LTO.
|
||||
///
|
||||
/// Crates ignored during LTO are not lumped together in the "massive object
|
||||
/// file" that we create and are linked in their normal rlib states. See
|
||||
/// comments below for what crates do not participate in LTO.
|
||||
///
|
||||
/// It's unusual for a crate to not participate in LTO. Typically only
|
||||
/// compiler-specific and unstable crates have a reason to not participate in
|
||||
/// LTO.
|
||||
pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
// If our target enables builtin function lowering in LLVM then the
|
||||
// crates providing these functions don't participate in LTO (e.g.
|
||||
// no_builtins or compiler builtins crates).
|
||||
!sess.target.no_builtins
|
||||
&& (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
|
||||
}
|
||||
|
||||
/// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
|
||||
pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
fn infer_from(
|
||||
@ -2742,6 +2755,10 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
|
||||
// symbols). We must continue to include the rest of the rlib, however, as
|
||||
// it may contain static native libraries which must be linked in.
|
||||
//
|
||||
// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
|
||||
// their bytecode wasn't included. The object files in those libraries must
|
||||
// still be passed to the linker.
|
||||
//
|
||||
// Note, however, that if we're not doing LTO we can just pass the rlib
|
||||
// blindly to the linker (fast) because it's fine if it's not actually
|
||||
// included as we're at the end of the dependency chain.
|
||||
@ -2767,7 +2784,9 @@ fn add_static_crate<'a>(
|
||||
cmd.link_rlib(&rlib_path);
|
||||
};
|
||||
|
||||
if !are_upstream_rust_objects_already_included(sess) {
|
||||
if !are_upstream_rust_objects_already_included(sess)
|
||||
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum)
|
||||
{
|
||||
link_upstream(cratepath);
|
||||
return;
|
||||
}
|
||||
@ -2781,6 +2800,8 @@ fn add_static_crate<'a>(
|
||||
let canonical_name = name.replace('-', "_");
|
||||
let upstream_rust_objects_already_included =
|
||||
are_upstream_rust_objects_already_included(sess);
|
||||
let is_builtins =
|
||||
sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
|
||||
|
||||
let mut archive = archive_builder_builder.new_archive_builder(sess);
|
||||
if let Err(error) = archive.add_archive(
|
||||
@ -2797,8 +2818,9 @@ fn add_static_crate<'a>(
|
||||
|
||||
// If we're performing LTO and this is a rust-generated object
|
||||
// file, then we don't need the object file as it's part of the
|
||||
// LTO module.
|
||||
if upstream_rust_objects_already_included && is_rust_object {
|
||||
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
|
||||
// though, so we let that object file slide.
|
||||
if upstream_rust_objects_already_included && is_rust_object && is_builtins {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
// export level, however, as they're just implementation details.
|
||||
// Down below we'll hardwire all of the symbols to the `Rust` export
|
||||
// level instead.
|
||||
let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || is_compiler_builtins;
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
|
||||
|
||||
let mut reachable_non_generics: DefIdMap<_> = tcx
|
||||
.reachable_set(())
|
||||
@ -105,14 +105,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
}
|
||||
})
|
||||
.map(|def_id| {
|
||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
|
||||
// We won't link right if this symbol is stripped during LTO.
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())).name;
|
||||
// We have to preserve the symbols of the built-in functions during LTO.
|
||||
let is_builtin_fn = is_compiler_builtins
|
||||
&& symbol_export_level(tcx, def_id.to_def_id())
|
||||
.is_below_threshold(SymbolExportLevel::C)
|
||||
&& codegen_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
|
||||
let used = name == "rust_eh_personality";
|
||||
|
||||
let export_level = if special_runtime_crate {
|
||||
@ -120,6 +114,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
} else {
|
||||
symbol_export_level(tcx, def_id.to_def_id())
|
||||
};
|
||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
|
||||
debug!(
|
||||
"EXPORTED SYMBOL (local): {} ({:?})",
|
||||
tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
|
||||
@ -139,7 +134,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
|| used,
|
||||
used_compiler: is_builtin_fn,
|
||||
};
|
||||
(def_id.to_def_id(), info)
|
||||
})
|
||||
@ -152,7 +146,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Data,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -201,7 +194,6 @@ fn exported_symbols_provider_local(
|
||||
level: info.level,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: info.used,
|
||||
used_compiler: false,
|
||||
},
|
||||
)
|
||||
})
|
||||
@ -218,7 +210,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
@ -238,7 +229,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::Rust,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
@ -251,7 +241,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::Rust,
|
||||
kind: SymbolExportKind::Data,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -271,7 +260,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Data,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
)
|
||||
}));
|
||||
@ -297,7 +285,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Data,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
)
|
||||
}));
|
||||
@ -315,7 +302,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Data,
|
||||
used: true,
|
||||
used_compiler: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
@ -356,7 +342,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::Rust,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
@ -373,7 +358,6 @@ fn exported_symbols_provider_local(
|
||||
level: SymbolExportLevel::Rust,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -148,12 +148,23 @@ impl ModuleConfig {
|
||||
|
||||
let emit_obj = if !should_emit_obj {
|
||||
EmitObj::None
|
||||
} else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
|
||||
} else if sess.target.obj_is_bitcode
|
||||
|| (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
|
||||
{
|
||||
// This case is selected if the target uses objects as bitcode, or
|
||||
// if linker plugin LTO is enabled. In the linker plugin LTO case
|
||||
// the assumption is that the final link-step will read the bitcode
|
||||
// and convert it to object code. This may be done by either the
|
||||
// native linker or rustc itself.
|
||||
//
|
||||
// Note, however, that the linker-plugin-lto requested here is
|
||||
// explicitly ignored for `#![no_builtins]` crates. These crates are
|
||||
// specifically ignored by rustc's LTO passes and wouldn't work if
|
||||
// loaded into the linker. These crates define symbols that LLVM
|
||||
// lowers intrinsics to, and these symbol dependencies aren't known
|
||||
// until after codegen. As a result any crate marked
|
||||
// `#![no_builtins]` is assumed to not participate in LTO and
|
||||
// instead goes on to generate object code.
|
||||
EmitObj::Bitcode
|
||||
} else if need_bitcode_in_object(tcx) {
|
||||
EmitObj::ObjectCode(BitcodeSection::Full)
|
||||
@ -1023,6 +1034,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
|
@ -859,6 +859,7 @@ impl CrateInfo {
|
||||
local_crate_name,
|
||||
compiler_builtins,
|
||||
profiler_runtime: None,
|
||||
is_no_builtins: Default::default(),
|
||||
native_libraries: Default::default(),
|
||||
used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
|
||||
crate_name: Default::default(),
|
||||
@ -885,6 +886,9 @@ impl CrateInfo {
|
||||
if tcx.is_profiler_runtime(cnum) {
|
||||
info.profiler_runtime = Some(cnum);
|
||||
}
|
||||
if tcx.is_no_builtins(cnum) {
|
||||
info.is_no_builtins.insert(cnum);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle circular dependencies in the standard library.
|
||||
@ -892,7 +896,9 @@ impl CrateInfo {
|
||||
// If global LTO is enabled then almost everything (*) is glued into a single object file,
|
||||
// so this logic is not necessary and can cause issues on some targets (due to weak lang
|
||||
// item symbols being "privatized" to that object file), so we disable it.
|
||||
// (*) Native libs are not glued, and we assume that they cannot define weak lang items.
|
||||
// (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued,
|
||||
// and we assume that they cannot define weak lang items. This is not currently enforced
|
||||
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
||||
let target = &tcx.sess.target;
|
||||
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
||||
let missing_weak_lang_items: FxHashSet<Symbol> = info
|
||||
|
@ -25,7 +25,7 @@ extern crate tracing;
|
||||
extern crate rustc_middle;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
@ -158,6 +158,7 @@ pub struct CrateInfo {
|
||||
pub local_crate_name: Symbol,
|
||||
pub compiler_builtins: Option<CrateNum>,
|
||||
pub profiler_runtime: Option<CrateNum>,
|
||||
pub is_no_builtins: FxHashSet<CrateNum>,
|
||||
pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>,
|
||||
pub crate_name: FxHashMap<CrateNum, Symbol>,
|
||||
pub used_libraries: Vec<NativeLib>,
|
||||
|
@ -85,7 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
|
||||
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
|
||||
fn annotation_type_for_level(level: Level) -> AnnotationType {
|
||||
match level {
|
||||
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error,
|
||||
Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error,
|
||||
Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
|
||||
Level::Note | Level::OnceNote => AnnotationType::Note,
|
||||
Level::Help | Level::OnceHelp => AnnotationType::Help,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::snippet::Style;
|
||||
use crate::{
|
||||
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
|
||||
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
||||
CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
|
||||
MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
|
||||
@ -243,12 +243,15 @@ impl Diagnostic {
|
||||
|
||||
pub fn is_error(&self) -> bool {
|
||||
match self.level {
|
||||
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => {
|
||||
true
|
||||
}
|
||||
Level::Bug
|
||||
| Level::DelayedBug(DelayedBugKind::Normal)
|
||||
| Level::Fatal
|
||||
| Level::Error
|
||||
| Level::FailureNote => true,
|
||||
|
||||
Level::ForceWarning(_)
|
||||
| Level::Warning
|
||||
| Level::DelayedBug(DelayedBugKind::GoodPath)
|
||||
| Level::Note
|
||||
| Level::OnceNote
|
||||
| Level::Help
|
||||
@ -318,7 +321,7 @@ impl Diagnostic {
|
||||
"downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
|
||||
self.level
|
||||
);
|
||||
self.level = Level::DelayedBug;
|
||||
self.level = Level::DelayedBug(DelayedBugKind::Normal);
|
||||
}
|
||||
|
||||
/// Appends a labeled span to the diagnostic.
|
||||
|
@ -519,6 +519,12 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
|
||||
pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
|
||||
AtomicRef::new(&(default_track_diagnostic as _));
|
||||
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
|
||||
pub enum DelayedBugKind {
|
||||
Normal,
|
||||
GoodPath,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct DiagCtxtFlags {
|
||||
/// If false, warning-level lints are suppressed.
|
||||
@ -527,6 +533,9 @@ pub struct DiagCtxtFlags {
|
||||
/// If Some, the Nth error-level diagnostic is upgraded to bug-level.
|
||||
/// (rustc: see `-Z treat-err-as-bug`)
|
||||
pub treat_err_as_bug: Option<NonZeroUsize>,
|
||||
/// Eagerly emit delayed bugs as errors, so that the compiler debugger may
|
||||
/// see all of the errors being emitted at once.
|
||||
pub eagerly_emit_delayed_bugs: bool,
|
||||
/// Show macro backtraces.
|
||||
/// (rustc: see `-Z macro-backtrace`)
|
||||
pub macro_backtrace: bool,
|
||||
@ -541,8 +550,7 @@ impl Drop for DiagCtxtInner {
|
||||
self.emit_stashed_diagnostics();
|
||||
|
||||
if !self.has_errors() {
|
||||
let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new());
|
||||
self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
|
||||
self.flush_delayed(DelayedBugKind::Normal)
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this explains what `good_path_delayed_bugs` are!
|
||||
@ -551,11 +559,7 @@ impl Drop for DiagCtxtInner {
|
||||
// lints can be `#[allow]`'d, potentially leading to this triggering.
|
||||
// Also, "good path" should be replaced with a better naming.
|
||||
if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
|
||||
let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new());
|
||||
self.flush_delayed(
|
||||
bugs,
|
||||
"no warnings or errors encountered even though `good_path_delayed_bugs` issued",
|
||||
);
|
||||
self.flush_delayed(DelayedBugKind::GoodPath);
|
||||
}
|
||||
|
||||
if self.check_unstable_expect_diagnostics {
|
||||
@ -865,7 +869,8 @@ impl DiagCtxt {
|
||||
if treat_next_err_as_bug {
|
||||
self.bug(msg);
|
||||
}
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit()
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
|
||||
.emit()
|
||||
}
|
||||
|
||||
/// Like `delayed_bug`, but takes an additional span.
|
||||
@ -882,16 +887,15 @@ impl DiagCtxt {
|
||||
if treat_next_err_as_bug {
|
||||
self.span_bug(sp, msg);
|
||||
}
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
|
||||
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
|
||||
.with_span(sp)
|
||||
.emit()
|
||||
}
|
||||
|
||||
// FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's
|
||||
// where the explanation of what "good path" is (also, it should be renamed).
|
||||
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let diagnostic = Diagnostic::new(DelayedBug, msg);
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
|
||||
DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
@ -1218,9 +1222,7 @@ impl DiagCtxt {
|
||||
}
|
||||
|
||||
pub fn flush_delayed(&self) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new());
|
||||
inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
|
||||
self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1270,17 +1272,30 @@ impl DiagCtxtInner {
|
||||
return None;
|
||||
}
|
||||
|
||||
if diagnostic.level == DelayedBug {
|
||||
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
||||
// once *any* errors were emitted (and truncate `span_delayed_bugs`
|
||||
// when an error is first emitted, also), but maybe there's a case
|
||||
// in which that's not sound? otherwise this is really inefficient.
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
self.span_delayed_bugs
|
||||
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
|
||||
// FIXME(eddyb) this should check for `has_errors` and stop pushing
|
||||
// once *any* errors were emitted (and truncate `span_delayed_bugs`
|
||||
// when an error is first emitted, also), but maybe there's a case
|
||||
// in which that's not sound? otherwise this is really inefficient.
|
||||
match diagnostic.level {
|
||||
DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => {
|
||||
diagnostic.level = Error;
|
||||
}
|
||||
DelayedBug(DelayedBugKind::Normal) => {
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
self.span_delayed_bugs
|
||||
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
|
||||
|
||||
#[allow(deprecated)]
|
||||
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
#[allow(deprecated)]
|
||||
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
|
||||
}
|
||||
DelayedBug(DelayedBugKind::GoodPath) => {
|
||||
let backtrace = std::backtrace::Backtrace::capture();
|
||||
self.good_path_delayed_bugs
|
||||
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
|
||||
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if diagnostic.has_future_breakage() {
|
||||
@ -1396,11 +1411,18 @@ impl DiagCtxtInner {
|
||||
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
|
||||
}
|
||||
|
||||
fn flush_delayed(
|
||||
&mut self,
|
||||
bugs: Vec<DelayedDiagnostic>,
|
||||
explanation: impl Into<DiagnosticMessage> + Copy,
|
||||
) {
|
||||
fn flush_delayed(&mut self, kind: DelayedBugKind) {
|
||||
let (bugs, explanation) = match kind {
|
||||
DelayedBugKind::Normal => (
|
||||
std::mem::take(&mut self.span_delayed_bugs),
|
||||
"no errors encountered even though `span_delayed_bug` issued",
|
||||
),
|
||||
DelayedBugKind::GoodPath => (
|
||||
std::mem::take(&mut self.good_path_delayed_bugs),
|
||||
"no warnings or errors encountered even though `good_path_delayed_bugs` issued",
|
||||
),
|
||||
};
|
||||
|
||||
if bugs.is_empty() {
|
||||
return;
|
||||
}
|
||||
@ -1433,7 +1455,7 @@ impl DiagCtxtInner {
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||
|
||||
// "Undelay" the `DelayedBug`s (into plain `Bug`s).
|
||||
if bug.level != DelayedBug {
|
||||
if !matches!(bug.level, DelayedBug(_)) {
|
||||
// NOTE(eddyb) not panicking here because we're already producing
|
||||
// an ICE, and the more information the merrier.
|
||||
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
|
||||
@ -1521,8 +1543,9 @@ pub enum Level {
|
||||
/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
|
||||
/// that should only be reached when compiling erroneous code.
|
||||
///
|
||||
/// Its `EmissionGuarantee` is `ErrorGuaranteed`.
|
||||
DelayedBug,
|
||||
/// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for
|
||||
/// `GoodPath` delayed bugs.
|
||||
DelayedBug(DelayedBugKind),
|
||||
|
||||
/// An error that causes an immediate abort. Used for things like configuration errors,
|
||||
/// internal overflows, some file operation errors.
|
||||
@ -1597,7 +1620,7 @@ impl Level {
|
||||
fn color(self) -> ColorSpec {
|
||||
let mut spec = ColorSpec::new();
|
||||
match self {
|
||||
Bug | DelayedBug | Fatal | Error => {
|
||||
Bug | DelayedBug(_) | Fatal | Error => {
|
||||
spec.set_fg(Some(Color::Red)).set_intense(true);
|
||||
}
|
||||
ForceWarning(_) | Warning => {
|
||||
@ -1617,7 +1640,7 @@ impl Level {
|
||||
|
||||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
Bug | DelayedBug => "error: internal compiler error",
|
||||
Bug | DelayedBug(_) => "error: internal compiler error",
|
||||
Fatal | Error => "error",
|
||||
ForceWarning(_) | Warning => "warning",
|
||||
Note | OnceNote => "note",
|
||||
|
@ -74,7 +74,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
|
@ -532,8 +532,14 @@ lint_unknown_gated_lint =
|
||||
|
||||
lint_unknown_lint =
|
||||
unknown lint: `{$name}`
|
||||
.suggestion = did you mean
|
||||
.help = did you mean: `{$replace}`
|
||||
.suggestion = {$from_rustc ->
|
||||
[true] a lint with a similar name exists in `rustc` lints
|
||||
*[false] did you mean
|
||||
}
|
||||
.help = {$from_rustc ->
|
||||
[true] a lint with a similar name exists in `rustc` lints: `{$replace}`
|
||||
*[false] did you mean: `{$replace}`
|
||||
}
|
||||
|
||||
lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
|
||||
.help = add `#![register_tool({$tool_name})]` to the crate root
|
||||
|
@ -33,7 +33,7 @@ use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, Ty
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
|
||||
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
|
||||
use rustc_session::{LintStoreMarker, Session};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::edit_distance::find_best_match_for_names;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi;
|
||||
@ -117,7 +117,7 @@ struct LintGroup {
|
||||
pub enum CheckLintNameResult<'a> {
|
||||
Ok(&'a [LintId]),
|
||||
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
|
||||
NoLint(Option<Symbol>),
|
||||
NoLint(Option<(Symbol, bool)>),
|
||||
/// The lint refers to a tool that has not been registered.
|
||||
NoTool,
|
||||
/// The lint has been renamed to a new name.
|
||||
@ -377,7 +377,7 @@ impl LintStore {
|
||||
debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
|
||||
let tool_prefix = format!("{tool_name}::");
|
||||
return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
|
||||
self.no_lint_suggestion(&complete_name)
|
||||
self.no_lint_suggestion(&complete_name, tool_name.as_str())
|
||||
} else {
|
||||
// 2. The tool isn't currently running, so no lints will be registered.
|
||||
// To avoid giving a false positive, ignore all unknown lints.
|
||||
@ -419,13 +419,14 @@ impl LintStore {
|
||||
}
|
||||
}
|
||||
|
||||
fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
|
||||
fn no_lint_suggestion(&self, lint_name: &str, tool_name: &str) -> CheckLintNameResult<'_> {
|
||||
let name_lower = lint_name.to_lowercase();
|
||||
|
||||
if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
|
||||
// First check if the lint name is (partly) in upper case instead of lower case...
|
||||
return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)));
|
||||
return CheckLintNameResult::NoLint(Some((Symbol::intern(&name_lower), false)));
|
||||
}
|
||||
|
||||
// ...if not, search for lints with a similar name
|
||||
// Note: find_best_match_for_name depends on the sort order of its input vector.
|
||||
// To ensure deterministic output, sort elements of the lint_groups hash map.
|
||||
@ -441,7 +442,16 @@ impl LintStore {
|
||||
let groups = groups.iter().map(|k| Symbol::intern(k));
|
||||
let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
|
||||
let names: Vec<Symbol> = groups.chain(lints).collect();
|
||||
let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None);
|
||||
let mut lookups = vec![Symbol::intern(&name_lower)];
|
||||
if let Some(stripped) = name_lower.split("::").last() {
|
||||
lookups.push(Symbol::intern(stripped));
|
||||
}
|
||||
let res = find_best_match_for_names(&names, &lookups, None);
|
||||
let is_rustc = res.map_or_else(
|
||||
|| false,
|
||||
|s| name_lower.contains("::") && !s.as_str().starts_with(tool_name),
|
||||
);
|
||||
let suggestion = res.map(|s| (s, is_rustc));
|
||||
CheckLintNameResult::NoLint(suggestion)
|
||||
}
|
||||
|
||||
@ -454,7 +464,7 @@ impl LintStore {
|
||||
match self.by_name.get(&complete_name) {
|
||||
None => match self.lint_groups.get(&*complete_name) {
|
||||
// Now we are sure, that this lint exists nowhere
|
||||
None => self.no_lint_suggestion(lint_name),
|
||||
None => self.no_lint_suggestion(lint_name, tool_name),
|
||||
Some(LintGroup { lint_ids, depr, .. }) => {
|
||||
// Reaching this would be weird, but let's cover this case anyway
|
||||
if let Some(LintAlias { name, silent }) = depr {
|
||||
|
@ -582,8 +582,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
||||
}
|
||||
CheckLintNameResult::NoLint(suggestion) => {
|
||||
let name = lint_name.clone();
|
||||
let suggestion =
|
||||
suggestion.map(|replace| UnknownLintSuggestion::WithoutSpan { replace });
|
||||
let suggestion = suggestion.map(|(replace, from_rustc)| {
|
||||
UnknownLintSuggestion::WithoutSpan { replace, from_rustc }
|
||||
});
|
||||
let requested_level = RequestedLevel { level, lint_name };
|
||||
let lint = UnknownLintFromCommandLine { name, suggestion, requested_level };
|
||||
self.emit_lint(UNKNOWN_LINTS, lint);
|
||||
@ -990,8 +991,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
let suggestion = suggestion.map(|replace| {
|
||||
UnknownLintSuggestion::WithSpan { suggestion: sp, replace }
|
||||
let suggestion = suggestion.map(|(replace, from_rustc)| {
|
||||
UnknownLintSuggestion::WithSpan { suggestion: sp, replace, from_rustc }
|
||||
});
|
||||
let lint = UnknownLint { name, suggestion };
|
||||
self.emit_spanned_lint(UNKNOWN_LINTS, sp.into(), lint);
|
||||
|
@ -1050,9 +1050,10 @@ pub enum UnknownLintSuggestion {
|
||||
#[primary_span]
|
||||
suggestion: Span,
|
||||
replace: Symbol,
|
||||
from_rustc: bool,
|
||||
},
|
||||
#[help(lint_help)]
|
||||
WithoutSpan { replace: Symbol },
|
||||
WithoutSpan { replace: Symbol, from_rustc: bool },
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
@ -531,9 +531,12 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
|
||||
|
||||
// Unfortunately, the LLVM C API doesn't provide a way to create the
|
||||
// TargetLibraryInfo pass, so we use this method to do so.
|
||||
extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M) {
|
||||
extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
|
||||
bool DisableSimplifyLibCalls) {
|
||||
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
||||
TargetLibraryInfoImpl TLII(TargetTriple);
|
||||
if (DisableSimplifyLibCalls)
|
||||
TLII.disableAllFunctions();
|
||||
unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
|
||||
}
|
||||
|
||||
@ -700,7 +703,7 @@ LLVMRustOptimize(
|
||||
bool IsLinkerPluginLTO,
|
||||
bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
|
||||
bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
|
||||
bool EmitLifetimeMarkers,
|
||||
bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
|
||||
LLVMRustSanitizerOptions *SanitizerOptions,
|
||||
const char *PGOGenPath, const char *PGOUsePath,
|
||||
bool InstrumentCoverage, const char *InstrProfileOutput,
|
||||
@ -800,6 +803,8 @@ LLVMRustOptimize(
|
||||
|
||||
Triple TargetTriple(TheModule->getTargetTriple());
|
||||
std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
|
||||
if (DisableSimplifyLibCalls)
|
||||
TLII->disableAllFunctions();
|
||||
FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
|
||||
|
||||
PB.registerModuleAnalyses(MAM);
|
||||
|
@ -35,12 +35,7 @@ pub enum SymbolExportKind {
|
||||
pub struct SymbolExportInfo {
|
||||
pub level: SymbolExportLevel,
|
||||
pub kind: SymbolExportKind,
|
||||
/// Used to mark these symbols not to be internalized by LTO. These symbols
|
||||
/// are also added to `symbols.o` to avoid circular dependencies when linking.
|
||||
pub used: bool,
|
||||
/// Also used to mark these symbols not to be internalized by LTO. But will
|
||||
/// not be added to `symbols.o`. Currently there are only builtin functions.
|
||||
pub used_compiler: bool,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
|
||||
|
@ -1146,6 +1146,7 @@ impl UnstableOptions {
|
||||
DiagCtxtFlags {
|
||||
can_emit_warnings,
|
||||
treat_err_as_bug: self.treat_err_as_bug,
|
||||
eagerly_emit_delayed_bugs: self.eagerly_emit_delayed_bugs,
|
||||
macro_backtrace: self.macro_backtrace,
|
||||
deduplicate_diagnostics: self.deduplicate_diagnostics,
|
||||
track_diagnostics: self.track_diagnostics,
|
||||
@ -1823,7 +1824,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
|
||||
"Remap source names in all output (compiler messages and output files)",
|
||||
"FROM=TO",
|
||||
),
|
||||
opt::multi("", "env", "Inject an environment variable", "VAR=VALUE"),
|
||||
opt::multi("", "env-set", "Inject an environment variable", "VAR=VALUE"),
|
||||
]);
|
||||
opts
|
||||
}
|
||||
@ -2599,11 +2600,11 @@ fn parse_logical_env(
|
||||
) -> FxIndexMap<String, String> {
|
||||
let mut vars = FxIndexMap::default();
|
||||
|
||||
for arg in matches.opt_strs("env") {
|
||||
for arg in matches.opt_strs("env-set") {
|
||||
if let Some((name, val)) = arg.split_once('=') {
|
||||
vars.insert(name.to_string(), val.to_string());
|
||||
} else {
|
||||
early_dcx.early_fatal(format!("`--env`: specify value for variable `{arg}`"));
|
||||
early_dcx.early_fatal(format!("`--env-set`: specify value for variable `{arg}`"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1583,6 +1583,9 @@ options! {
|
||||
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
|
||||
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
|
||||
"enables LTO for dylib crate type"),
|
||||
eagerly_emit_delayed_bugs: bool = (false, parse_bool, [UNTRACKED],
|
||||
"emit delayed bugs eagerly as errors instead of stashing them and emitting \
|
||||
them only if an error has not been emitted"),
|
||||
ehcont_guard: bool = (false, parse_bool, [TRACKED],
|
||||
"generate Windows EHCont Guard tables"),
|
||||
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -170,6 +170,34 @@ pub fn find_best_match_for_name(
|
||||
find_best_match_for_name_impl(false, candidates, lookup, dist)
|
||||
}
|
||||
|
||||
/// Find the best match for multiple words
|
||||
///
|
||||
/// This function is intended for use when the desired match would never be
|
||||
/// returned due to a substring in `lookup` which is superfluous.
|
||||
///
|
||||
/// For example, when looking for the closest lint name to `clippy:missing_docs`,
|
||||
/// we would find `clippy::erasing_op`, despite `missing_docs` existing and being a better suggestion.
|
||||
/// `missing_docs` would have a larger edit distance because it does not contain the `clippy` tool prefix.
|
||||
/// In order to find `missing_docs`, this function takes multiple lookup strings, computes the best match
|
||||
/// for each and returns the match which had the lowest edit distance. In our example, `clippy:missing_docs` and
|
||||
/// `missing_docs` would be `lookups`, enabling `missing_docs` to be the best match, as desired.
|
||||
pub fn find_best_match_for_names(
|
||||
candidates: &[Symbol],
|
||||
lookups: &[Symbol],
|
||||
dist: Option<usize>,
|
||||
) -> Option<Symbol> {
|
||||
lookups
|
||||
.iter()
|
||||
.map(|s| (s, find_best_match_for_name_impl(false, candidates, *s, dist)))
|
||||
.filter_map(|(s, r)| r.map(|r| (s, r)))
|
||||
.min_by(|(s1, r1), (s2, r2)| {
|
||||
let d1 = edit_distance(s1.as_str(), r1.as_str(), usize::MAX).unwrap();
|
||||
let d2 = edit_distance(s2.as_str(), r2.as_str(), usize::MAX).unwrap();
|
||||
d1.cmp(&d2)
|
||||
})
|
||||
.map(|(_, r)| r)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn find_best_match_for_name_impl(
|
||||
use_substring_score: bool,
|
||||
|
@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::TraitEngineExt;
|
||||
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::{ObligationCause, Reveal};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
|
||||
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||
@ -52,14 +52,16 @@ struct NormalizationFolder<'me, 'tcx> {
|
||||
impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
fn normalize_alias_ty(
|
||||
&mut self,
|
||||
alias: AliasTy<'tcx>,
|
||||
alias_ty: Ty<'tcx>,
|
||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
|
||||
|
||||
let infcx = self.at.infcx;
|
||||
let tcx = infcx.tcx;
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
&alias.to_ty(tcx),
|
||||
&alias_ty,
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
@ -76,7 +78,11 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
tcx,
|
||||
self.at.cause.clone(),
|
||||
self.at.param_env,
|
||||
ty::NormalizesTo { alias, term: new_infer_ty.into() },
|
||||
ty::PredicateKind::AliasRelate(
|
||||
alias_ty.into(),
|
||||
new_infer_ty.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
|
||||
// Do not emit an error if normalization is known to fail but instead
|
||||
@ -90,9 +96,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
return Err(errors);
|
||||
}
|
||||
let ty = infcx.resolve_vars_if_possible(new_infer_ty);
|
||||
ty.try_fold_with(self)?
|
||||
|
||||
// Alias is guaranteed to be fully structurally resolved,
|
||||
// so we can super fold here.
|
||||
ty.try_super_fold_with(self)?
|
||||
} else {
|
||||
alias.to_ty(tcx).try_super_fold_with(self)?
|
||||
alias_ty.try_super_fold_with(self)?
|
||||
};
|
||||
|
||||
self.depth -= 1;
|
||||
@ -170,24 +179,18 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
let reveal = self.at.param_env.reveal();
|
||||
let infcx = self.at.infcx;
|
||||
debug_assert_eq!(ty, infcx.shallow_resolve(ty));
|
||||
if !needs_normalization(&ty, reveal) {
|
||||
if !ty.has_projections() {
|
||||
return Ok(ty);
|
||||
}
|
||||
|
||||
// We don't normalize opaque types unless we have
|
||||
// `Reveal::All`, even if we're in the defining scope.
|
||||
let data = match *ty.kind() {
|
||||
ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::All => alias_ty,
|
||||
_ => return ty.try_super_fold_with(self),
|
||||
};
|
||||
let ty::Alias(..) = *ty.kind() else { return ty.try_super_fold_with(self) };
|
||||
|
||||
if data.has_escaping_bound_vars() {
|
||||
let (data, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
|
||||
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?;
|
||||
if ty.has_escaping_bound_vars() {
|
||||
let (ty, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
|
||||
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
|
||||
Ok(PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
@ -197,7 +200,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
||||
result,
|
||||
))
|
||||
} else {
|
||||
ensure_sufficient_stack(|| self.normalize_alias_ty(data))
|
||||
ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
// FIXME(-Znext-solver): Should we resolve opaques here?
|
||||
let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
|
||||
let ty::Alias(..) = *ty.kind() else {
|
||||
return Ok(ty);
|
||||
};
|
||||
|
||||
|
@ -963,7 +963,7 @@ pub enum PointerCoercion {
|
||||
/// Go from a safe fn pointer to an unsafe fn pointer.
|
||||
UnsafeFnPointer,
|
||||
|
||||
/// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
|
||||
/// Go from a non-capturing closure to a fn pointer or an unsafe fn pointer.
|
||||
/// It cannot convert a closure that requires unsafe.
|
||||
ClosureFnPointer(Safety),
|
||||
|
||||
@ -1037,21 +1037,24 @@ impl Place {
|
||||
/// locals from the function body where this place originates from.
|
||||
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
|
||||
let start_ty = locals[self.local].ty;
|
||||
self.projection.iter().fold(Ok(start_ty), |place_ty, elem| {
|
||||
let ty = place_ty?;
|
||||
match elem {
|
||||
ProjectionElem::Deref => Self::deref_ty(ty),
|
||||
ProjectionElem::Field(_idx, fty) => Ok(*fty),
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
|
||||
Self::index_ty(ty)
|
||||
}
|
||||
ProjectionElem::Subslice { from, to, from_end } => {
|
||||
Self::subslice_ty(ty, from, to, from_end)
|
||||
}
|
||||
ProjectionElem::Downcast(_) => Ok(ty),
|
||||
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
|
||||
self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?))
|
||||
}
|
||||
}
|
||||
|
||||
impl ProjectionElem {
|
||||
/// Get the expected type after applying this projection to a given place type.
|
||||
pub fn ty(&self, place_ty: Ty) -> Result<Ty, Error> {
|
||||
let ty = place_ty;
|
||||
match &self {
|
||||
ProjectionElem::Deref => Self::deref_ty(ty),
|
||||
ProjectionElem::Field(_idx, fty) => Ok(*fty),
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => Self::index_ty(ty),
|
||||
ProjectionElem::Subslice { from, to, from_end } => {
|
||||
Self::subslice_ty(ty, from, to, from_end)
|
||||
}
|
||||
})
|
||||
ProjectionElem::Downcast(_) => Ok(ty),
|
||||
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn index_ty(ty: Ty) -> Result<Ty, Error> {
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
use crate::mir::*;
|
||||
use crate::ty::{Const, GenericArgs, Region, Ty};
|
||||
use crate::{Opaque, Span};
|
||||
use crate::{Error, Opaque, Span};
|
||||
|
||||
pub trait MirVisitor {
|
||||
fn visit_body(&mut self, body: &Body) {
|
||||
@ -76,12 +76,14 @@ pub trait MirVisitor {
|
||||
self.super_place(place, ptx, location)
|
||||
}
|
||||
|
||||
fn visit_projection_elem(
|
||||
fn visit_projection_elem<'a>(
|
||||
&mut self,
|
||||
place_ref: PlaceRef<'a>,
|
||||
elem: &ProjectionElem,
|
||||
ptx: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
let _ = place_ref;
|
||||
self.super_projection_elem(elem, ptx, location);
|
||||
}
|
||||
|
||||
@ -284,8 +286,9 @@ pub trait MirVisitor {
|
||||
let _ = ptx;
|
||||
self.visit_local(&place.local, ptx, location);
|
||||
|
||||
for elem in &place.projection {
|
||||
self.visit_projection_elem(elem, ptx, location);
|
||||
for (idx, elem) in place.projection.iter().enumerate() {
|
||||
let place_ref = PlaceRef { local: place.local, projection: &place.projection[..idx] };
|
||||
self.visit_projection_elem(place_ref, elem, ptx, location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,6 +456,19 @@ impl Location {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reference to a place used to represent a partial projection.
|
||||
pub struct PlaceRef<'a> {
|
||||
pub local: Local,
|
||||
pub projection: &'a [ProjectionElem],
|
||||
}
|
||||
|
||||
impl<'a> PlaceRef<'a> {
|
||||
/// Get the type of this place.
|
||||
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
|
||||
self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?))
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a place's usage.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct PlaceContext {
|
||||
|
@ -1,4 +1,4 @@
|
||||
# `env`
|
||||
# `env-set`
|
||||
|
||||
The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372).
|
||||
|
||||
@ -11,11 +11,11 @@ from the `proc_macro` crate.
|
||||
This information will be stored in the dep-info files. For more information about
|
||||
dep-info files, take a look [here](https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files).
|
||||
|
||||
When retrieving an environment variable value, the one specified by `--env` will take
|
||||
When retrieving an environment variable value, the one specified by `--env-set` will take
|
||||
precedence. For example, if you want have `PATH=a` in your environment and pass:
|
||||
|
||||
```bash
|
||||
rustc --env PATH=env
|
||||
rustc --env-set PATH=env
|
||||
```
|
||||
|
||||
Then you will have:
|
||||
@ -24,17 +24,17 @@ Then you will have:
|
||||
assert_eq!(env!("PATH"), "env");
|
||||
```
|
||||
|
||||
It will trigger a new compilation if any of the `--env` argument value is different.
|
||||
It will trigger a new compilation if any of the `--env-set` argument value is different.
|
||||
So if you first passed:
|
||||
|
||||
```bash
|
||||
--env A=B --env X=12
|
||||
--env-set A=B --env X=12
|
||||
```
|
||||
|
||||
and then on next compilation:
|
||||
|
||||
```bash
|
||||
--env A=B
|
||||
--env-set A=B
|
||||
```
|
||||
|
||||
`X` value is different (not set) so the code will be re-compiled.
|
||||
@ -42,4 +42,4 @@ and then on next compilation:
|
||||
Please note that on Windows, environment variables are case insensitive but case
|
||||
preserving whereas `rustc`'s environment variables are case sensitive. For example,
|
||||
having `Path` in your environment (case insensitive) is different than using
|
||||
`rustc --env Path=...` (case sensitive).
|
||||
`rustc --env-set Path=...` (case sensitive).
|
@ -7,10 +7,12 @@
|
||||
#[warn(clippy::if_not_else)]
|
||||
#[warn(clippy::unnecessary_cast)]
|
||||
#[warn(clippy::useless_transmute)]
|
||||
// Shouldn't suggest rustc lint name(`dead_code`)
|
||||
#[warn(clippy::eq_op)]
|
||||
// Should suggest rustc lint name(`dead_code`)
|
||||
#[warn(dead_code)]
|
||||
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
|
||||
#[warn(clippy::unused_self)]
|
||||
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
|
||||
#[warn(clippy::redundant_static_lifetimes)]
|
||||
// issue #118183, should report `missing_docs` from rustc lint
|
||||
#[warn(missing_docs)]
|
||||
fn main() {}
|
||||
|
@ -7,10 +7,12 @@
|
||||
#[warn(clippy::if_not_els)]
|
||||
#[warn(clippy::UNNecsaRy_cAst)]
|
||||
#[warn(clippy::useles_transute)]
|
||||
// Shouldn't suggest rustc lint name(`dead_code`)
|
||||
// Should suggest rustc lint name(`dead_code`)
|
||||
#[warn(clippy::dead_cod)]
|
||||
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
|
||||
#[warn(clippy::unused_colle)]
|
||||
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
|
||||
#[warn(clippy::const_static_lifetim)]
|
||||
// issue #118183, should report `missing_docs` from rustc lint
|
||||
#[warn(clippy::missing_docs)]
|
||||
fn main() {}
|
||||
|
@ -35,7 +35,12 @@ error: unknown lint: `clippy::dead_cod`
|
||||
--> $DIR/unknown_clippy_lints.rs:11:8
|
||||
|
|
||||
LL | #[warn(clippy::dead_cod)]
|
||||
| ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: a lint with a similar name exists in `rustc` lints
|
||||
|
|
||||
LL | #[warn(dead_code)]
|
||||
| ~~~~~~~~~
|
||||
|
||||
error: unknown lint: `clippy::unused_colle`
|
||||
--> $DIR/unknown_clippy_lints.rs:13:8
|
||||
@ -49,5 +54,16 @@ error: unknown lint: `clippy::const_static_lifetim`
|
||||
LL | #[warn(clippy::const_static_lifetim)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: unknown lint: `clippy::missing_docs`
|
||||
--> $DIR/unknown_clippy_lints.rs:17:8
|
||||
|
|
||||
LL | #[warn(clippy::missing_docs)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: a lint with a similar name exists in `rustc` lints
|
||||
|
|
||||
LL | #[warn(missing_docs)]
|
||||
| ~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
@ -165,7 +165,6 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
|
||||
level: SymbolExportLevel::C,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
used_compiler: false,
|
||||
},
|
||||
))
|
||||
}),
|
||||
|
@ -1,15 +1,9 @@
|
||||
include ../tools.mk
|
||||
|
||||
# only-x86_64
|
||||
|
||||
# We want to check that `no_builtins` is correctly participating in LTO.
|
||||
# First, verify that the `foo::foo` symbol can be found when linking.
|
||||
# Next, verify that `memcpy` can be customized using `no_builtins` under LTO.
|
||||
# Others will use the built-in memcpy.
|
||||
|
||||
all:
|
||||
$(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 foo.rs
|
||||
$(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 no_builtins.rs
|
||||
$(RUSTC) main.rs -C lto -C opt-level=2 -C debuginfo=0 -C save-temps -C metadata=1 -C codegen-units=1
|
||||
"$(LLVM_BIN_DIR)"/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll
|
||||
cat "$(TMPDIR)"/lto.ll | "$(LLVM_FILECHECK)" filecheck.lto.txt
|
||||
# Compile a `#![no_builtins]` rlib crate
|
||||
$(RUSTC) no_builtins.rs
|
||||
# Build an executable that depends on that crate using LTO. The no_builtins crate doesn't
|
||||
# participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by
|
||||
# grepping the linker arguments.
|
||||
$(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib'
|
||||
|
@ -1,17 +0,0 @@
|
||||
CHECK: define{{.*}} void @bar
|
||||
CHECK-NEXT: call void @no_builtins
|
||||
CHECK-NEXT: call void @llvm.memcpy
|
||||
|
||||
CHECK: define{{.*}} i32 @main
|
||||
CHECK: call void @bar
|
||||
|
||||
CHECK: define{{.*}} void @foo
|
||||
CHECK-NEXT: call void @llvm.memcpy
|
||||
|
||||
CHECK: define{{.*}} void @no_builtins
|
||||
CHECK-SAME: #[[ATTR:[0-9]+]] {
|
||||
CHECK: call void @foo
|
||||
CHECK-NEXT: call{{.*}} @memcpy
|
||||
|
||||
CHECK: attributes #[[ATTR]]
|
||||
CHECK-SAME: no-builtins
|
@ -1,33 +0,0 @@
|
||||
#![feature(lang_items, no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[inline(never)]
|
||||
#[no_mangle]
|
||||
pub unsafe fn foo(dest: *mut u8, src: *const u8) {
|
||||
// should call `@llvm.memcpy`.
|
||||
memcpy(dest, src, 1024);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, _n: usize) -> *mut u8 {
|
||||
*dest = 0;
|
||||
return src as *mut u8;
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
impl Copy for *mut u8 {}
|
||||
impl Copy for *const u8 {}
|
||||
|
||||
#[lang = "drop_in_place"]
|
||||
#[allow(unconditional_recursion)]
|
||||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
// Code here does not matter - this is replaced by the
|
||||
// real drop glue by the compiler.
|
||||
drop_in_place(to_drop);
|
||||
}
|
@ -1,29 +1,3 @@
|
||||
#![feature(no_core, start, lang_items)]
|
||||
#![no_std]
|
||||
// We use `no_core` to reduce the LTO products is small enough.
|
||||
#![no_core]
|
||||
|
||||
extern crate no_builtins;
|
||||
extern crate foo;
|
||||
|
||||
#[cfg_attr(unix, link(name = "c"))]
|
||||
#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
|
||||
extern "C" {}
|
||||
|
||||
#[start]
|
||||
fn main(_: isize, p: *const *const u8) -> isize {
|
||||
// Make sure the symbols are retained.
|
||||
unsafe { bar(*p as *mut u8, *p); }
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
pub unsafe extern "C" fn bar(dest: *mut u8, src: *const u8) {
|
||||
no_builtins::no_builtins(dest, src);
|
||||
// should call `@llvm.memcpy`
|
||||
foo::memcpy(dest, src, 1024);
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
fn eh_personality() {}
|
||||
fn main() {}
|
||||
|
@ -1,15 +1,2 @@
|
||||
#![feature(lang_items, no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![crate_type = "lib"]
|
||||
#![no_builtins]
|
||||
|
||||
extern crate foo;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn no_builtins(dest: *mut u8, src: *const u8) {
|
||||
// There should be no "undefined reference to `foo::foo'".
|
||||
foo::foo(dest, src);
|
||||
// should call `@memcpy` instead of `@llvm.memcpy`.
|
||||
foo::memcpy(dest, src, 1024);
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
# only-x86_64-unknown-linux-gnu
|
||||
|
||||
all:
|
||||
$(RUSTC) main.rs -o $(TMPDIR)/main
|
||||
[ "$$("$(LLVM_BIN_DIR)"/llvm-nm -U $(TMPDIR)/main | grep -c __fixunssfti)" -eq "0" ]
|
@ -1 +0,0 @@
|
||||
fn main() {}
|
@ -8,8 +8,7 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
|
||||
#[no_mangle]
|
||||
pub fn multer(a: i128, b: i128) -> i128 {
|
||||
// Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function
|
||||
// such as panic or __multi3 (externally defined) in case of a bug. We verify that
|
||||
// no imports exist in our verifier.
|
||||
// Trigger usage of the __multi3 compiler intrinsic which then leads to an imported
|
||||
// panic function in case of a bug. We verify that no imports exist in our verifier.
|
||||
a * b
|
||||
}
|
52
tests/ui/coroutine/clone-rpit.next.stderr
Normal file
52
tests/ui/coroutine/clone-rpit.next.stderr
Normal file
@ -0,0 +1,52 @@
|
||||
error[E0391]: cycle detected when type-checking `foo`
|
||||
--> $DIR/clone-rpit.rs:12:1
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>() -> impl Clone {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires coroutine witness types for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires preparing `foo::{closure#0}` for borrow checking...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires match-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:13:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
= note: ...which again requires type-checking `foo`, completing the cycle
|
||||
note: cycle used when computing type of opaque `foo::{opaque#0}`
|
||||
--> $DIR/clone-rpit.rs:12:25
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>() -> impl Clone {
|
||||
| ^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
@ -1,6 +1,7 @@
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Znext-solver
|
||||
// check-pass
|
||||
//[current] check-pass
|
||||
//[next] known-bug: trait-system-refactor-initiative#82
|
||||
|
||||
#![feature(coroutines, coroutine_trait, coroutine_clone)]
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// run-pass
|
||||
// rustc-env:MY_VAR=tadam
|
||||
// compile-flags: --env MY_VAR=123abc -Zunstable-options
|
||||
// compile-flags: --env-set MY_VAR=123abc -Zunstable-options
|
||||
|
||||
// This test ensures that variables provided with `--env` take precedence over
|
||||
// variables from environment.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: --env FOO=123abc -Zunstable-options
|
||||
// compile-flags: --env-set FOO=123abc -Zunstable-options
|
||||
// run-pass
|
||||
fn main() {
|
||||
assert_eq!(env!("FOO"), "123abc");
|
||||
|
@ -1,6 +1,6 @@
|
||||
// run-pass
|
||||
// rustc-env:MY_ENV=/
|
||||
// Ensures that variables not defined through `--env` are still available.
|
||||
// Ensures that variables not defined through `--env-set` are still available.
|
||||
|
||||
fn main() {
|
||||
assert!(!env!("MY_ENV").is_empty());
|
||||
|
@ -1,3 +1,3 @@
|
||||
// compile-flags: --env A=B
|
||||
// compile-flags: --env-set A=B
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,2 +1,2 @@
|
||||
error: the `-Z unstable-options` flag must also be passed to enable the flag `env`
|
||||
error: the `-Z unstable-options` flag must also be passed to enable the flag `env-set`
|
||||
|
||||
|
13
tests/ui/impl-trait/eagerly-reveal-in-local-body.rs
Normal file
13
tests/ui/impl-trait/eagerly-reveal-in-local-body.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
// compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
fn main() {
|
||||
type Tait = impl Sized;
|
||||
struct S {
|
||||
i: i32,
|
||||
}
|
||||
let x: Tait = S { i: 0 };
|
||||
println!("{}", x.i);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
error[E0733]: recursion in a coroutine requires boxing
|
||||
--> $DIR/recursive-coroutine-indirect.rs:6:5
|
||||
--> $DIR/recursive-coroutine-indirect.rs:10:5
|
||||
|
|
||||
LL | move || {
|
||||
| ^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0733]: recursion in a coroutine requires boxing
|
||||
--> $DIR/recursive-coroutine-indirect.rs:6:5
|
||||
--> $DIR/recursive-coroutine-indirect.rs:10:5
|
||||
|
|
||||
LL | move || {
|
||||
| ^^^^^^^
|
||||
|
@ -1,5 +1,9 @@
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Znext-solver
|
||||
|
||||
//[next] build-fail
|
||||
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
|
||||
|
||||
#![feature(coroutines)]
|
||||
#![allow(unconditional_recursion)]
|
||||
fn coroutine_hold() -> impl Sized {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// aux-build:env.rs
|
||||
// run-pass
|
||||
// rustc-env: THE_CONST=1
|
||||
// compile-flags: -Zunstable-options --env THE_CONST=12 --env ANOTHER=4
|
||||
// compile-flags: -Zunstable-options --env-set THE_CONST=12 --env-set ANOTHER=4
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
|
@ -13,11 +13,8 @@ fn main() {
|
||||
}
|
||||
|
||||
fn weird0() -> impl Sized + !Sized {}
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
|
||||
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
|
||||
fn weird1() -> impl !Sized + Sized {}
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
|
||||
//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
|
||||
fn weird2() -> impl !Sized {}
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR type mismatch resolving `() == impl !Sized`
|
||||
//~^ ERROR type mismatch resolving `() == impl !Sized`
|
||||
|
@ -1,50 +1,17 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:15:36
|
||||
|
|
||||
LL | fn weird0() -> impl Sized + !Sized {}
|
||||
| ------------------- ^^ types differ
|
||||
| |
|
||||
| the expected opaque type
|
||||
|
|
||||
= note: expected opaque type `impl !Sized + Sized`
|
||||
found unit type `()`
|
||||
|
||||
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:15:16
|
||||
|
|
||||
LL | fn weird0() -> impl Sized + !Sized {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:18:36
|
||||
|
|
||||
LL | fn weird1() -> impl !Sized + Sized {}
|
||||
| ------------------- ^^ types differ
|
||||
| |
|
||||
| the expected opaque type
|
||||
|
|
||||
= note: expected opaque type `impl !Sized + Sized`
|
||||
found unit type `()`
|
||||
|
||||
error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:18:16
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:17:16
|
||||
|
|
||||
LL | fn weird1() -> impl !Sized + Sized {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:21:28
|
||||
|
|
||||
LL | fn weird2() -> impl !Sized {}
|
||||
| ----------- ^^ types differ
|
||||
| |
|
||||
| the expected opaque type
|
||||
|
|
||||
= note: expected opaque type `impl !Sized`
|
||||
found unit type `()`
|
||||
|
||||
error[E0271]: type mismatch resolving `() == impl !Sized`
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:21:16
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
|
||||
|
|
||||
LL | fn weird2() -> impl !Sized {}
|
||||
| ^^^^^^^^^^^ types differ
|
||||
@ -63,7 +30,7 @@ note: required by a bound in `consume`
|
||||
LL | fn consume(_: impl Trait) {}
|
||||
| ^^^^^ required by this bound in `consume`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277, E0308.
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
@ -3,7 +3,6 @@
|
||||
#![feature(negative_bounds, unboxed_closures)]
|
||||
|
||||
fn produce() -> impl !Fn<(u32,)> {}
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
|
||||
//~^ ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,21 +1,9 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34
|
||||
|
|
||||
LL | fn produce() -> impl !Fn<(u32,)> {}
|
||||
| ---------------- ^^ types differ
|
||||
| |
|
||||
| the expected opaque type
|
||||
|
|
||||
= note: expected opaque type `impl !Fn<(u32,)>`
|
||||
found unit type `()`
|
||||
|
||||
error[E0271]: type mismatch resolving `() == impl !Fn<(u32,)>`
|
||||
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
|
||||
|
|
||||
LL | fn produce() -> impl !Fn<(u32,)> {}
|
||||
| ^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Some errors have detailed explanations: E0271, E0308.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
@ -23,10 +23,10 @@ fn main() {
|
||||
let x = String::from("hello, world");
|
||||
drop(<() as Foo>::copy_me(&x));
|
||||
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
println!("{x}");
|
||||
}
|
||||
|
@ -52,13 +52,14 @@ LL | drop(<() as Foo>::copy_me(&x));
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
|
||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||
--> $DIR/alias-bound-unsound.rs:24:10
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -13,8 +13,10 @@ fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
|
||||
needs_bar::<T::Assoc1>();
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
|
||||
LL | fn needs_bar<S: Bar>() {}
|
||||
| ^^^ required by this bound in `needs_bar`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
@ -19,6 +19,23 @@ LL | needs_bar::<T::Assoc1>();
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:17
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
@ -9,8 +9,10 @@ fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
|
||||
needs_bar::<T::Assoc>();
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
|
||||
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
|
||||
LL | fn needs_bar<S: Bar>() {}
|
||||
| ^^^ required by this bound in `needs_bar`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc`
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
--> $DIR/recursive-self-normalization.rs:11:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
@ -19,6 +19,23 @@ LL | needs_bar::<T::Assoc>();
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
--> $DIR/recursive-self-normalization.rs:11:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
--> $DIR/recursive-self-normalization.rs:11:17
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
11
tests/ui/treat-err-as-bug/eagerly-emit.rs
Normal file
11
tests/ui/treat-err-as-bug/eagerly-emit.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// compile-flags: -Zeagerly-emit-delayed-bugs
|
||||
|
||||
trait Foo {}
|
||||
|
||||
fn main() {}
|
||||
|
||||
fn f() -> impl Foo {
|
||||
//~^ ERROR the trait bound `i32: Foo` is not satisfied
|
||||
//~| ERROR `report_selection_error` did not emit an error
|
||||
1i32
|
||||
}
|
28
tests/ui/treat-err-as-bug/eagerly-emit.stderr
Normal file
28
tests/ui/treat-err-as-bug/eagerly-emit.stderr
Normal file
@ -0,0 +1,28 @@
|
||||
error: `report_selection_error` did not emit an error
|
||||
--> $DIR/eagerly-emit.rs:7:11
|
||||
|
|
||||
LL | fn f() -> impl Foo {
|
||||
| ^^^^^^^^
|
||||
|
||||
error: trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging
|
||||
|
||||
error[E0277]: the trait bound `i32: Foo` is not satisfied
|
||||
--> $DIR/eagerly-emit.rs:7:11
|
||||
|
|
||||
LL | fn f() -> impl Foo {
|
||||
| ^^^^^^^^ the trait `Foo` is not implemented for `i32`
|
||||
...
|
||||
LL | 1i32
|
||||
| ---- return type was inferred to be `i32` here
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/eagerly-emit.rs:3:1
|
||||
|
|
||||
LL | trait Foo {}
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: expected fulfillment errors
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user