mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Auto merge of #64754 - Centril:rollup-iwtb5xd, r=Centril
Rollup of 7 pull requests Successful merges: - #64324 (rustc: Fix mixing crates with different `share_generics`) - #64428 (Error explanation e0524) - #64481 (A more explanatory thread local storage panic message) - #64599 (Rustdoc render async function re-export) - #64743 (Update cargo) - #64746 (Remove blanket silencing of "type annotation needed" errors) - #64753 (Don't emit explain with json short messages.) Failed merges: r? @ghost
This commit is contained in:
commit
b7820b2893
47
Cargo.lock
47
Cargo.lock
@ -269,6 +269,7 @@ version = "0.40.0"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bytesize",
|
||||
"cargo-platform",
|
||||
"cargo-test-macro",
|
||||
"cargo-test-support",
|
||||
"clap",
|
||||
@ -278,7 +279,7 @@ dependencies = [
|
||||
"crypto-hash",
|
||||
"curl",
|
||||
"curl-sys",
|
||||
"env_logger",
|
||||
"env_logger 0.7.0",
|
||||
"failure",
|
||||
"filetime",
|
||||
"flate2",
|
||||
@ -325,6 +326,13 @@ dependencies = [
|
||||
"winapi 0.3.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-test-macro"
|
||||
version = "0.1.0"
|
||||
@ -526,7 +534,7 @@ name = "compiletest"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"getopts",
|
||||
"lazy_static 1.3.0",
|
||||
"libc",
|
||||
@ -938,6 +946,19 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ecdb7dd54465526f0a56d666e3b2dd5f3a218665a030b6e4ad9e70fa95d8fa"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.12.0"
|
||||
@ -1339,9 +1360,9 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
@ -1866,7 +1887,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"elasticlunr-rs",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"error-chain",
|
||||
"handlebars",
|
||||
"itertools 0.8.0",
|
||||
@ -1891,7 +1912,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"failure",
|
||||
"log",
|
||||
"mdbook",
|
||||
@ -2084,7 +2105,7 @@ dependencies = [
|
||||
"colored",
|
||||
"compiletest_rs",
|
||||
"directories",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"getrandom",
|
||||
"hex 0.3.2",
|
||||
"log",
|
||||
@ -2493,7 +2514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -2620,7 +2641,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"clap",
|
||||
"derive_more",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"humantime",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
@ -2914,7 +2935,7 @@ dependencies = [
|
||||
"clippy_lints",
|
||||
"crossbeam-channel",
|
||||
"difference",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"failure",
|
||||
"futures",
|
||||
"heck",
|
||||
@ -2998,7 +3019,7 @@ name = "rls-rustc"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"clippy_lints",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"failure",
|
||||
"futures",
|
||||
"log",
|
||||
@ -3399,7 +3420,7 @@ dependencies = [
|
||||
name = "rustc_driver"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"graphviz",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
@ -3781,7 +3802,7 @@ dependencies = [
|
||||
"derive-new",
|
||||
"diff",
|
||||
"dirs",
|
||||
"env_logger",
|
||||
"env_logger 0.6.2",
|
||||
"failure",
|
||||
"getopts",
|
||||
"ignore",
|
||||
|
@ -2184,9 +2184,7 @@ impl<'a> LoweringContext<'a> {
|
||||
match decl.output {
|
||||
FunctionRetTy::Ty(ref ty) => match in_band_ty_params {
|
||||
Some((def_id, _)) if impl_trait_return_allow => {
|
||||
hir::Return(self.lower_ty(ty,
|
||||
ImplTraitContext::OpaqueTy(Some(def_id))
|
||||
))
|
||||
hir::Return(self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))))
|
||||
}
|
||||
_ => {
|
||||
hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed()))
|
||||
|
@ -988,7 +988,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||
value.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| {
|
||||
if let ty::Opaque(def_id, substs) = ty.sty {
|
||||
if ty.references_error() {
|
||||
return tcx.types.err;
|
||||
} else if let ty::Opaque(def_id, substs) = ty.sty {
|
||||
// Check that this is `impl Trait` type is
|
||||
// declared by `parent_def_id` -- i.e., one whose
|
||||
// value we are inferring. At present, this is
|
||||
@ -1155,6 +1157,15 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||
);
|
||||
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
|
||||
|
||||
for predicate in &bounds.predicates {
|
||||
if let ty::Predicate::Projection(projection) = &predicate {
|
||||
if projection.skip_binder().ty.references_error() {
|
||||
// No point on adding these obligations since there's a type error involved.
|
||||
return ty_var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.obligations.reserve(bounds.predicates.len());
|
||||
for predicate in bounds.predicates {
|
||||
// Change the predicate to refer to the type variable,
|
||||
|
@ -1,64 +1,10 @@
|
||||
//! Resolution of mixing rlibs and dylibs
|
||||
//! Type definitions for learning about the dependency formats of all upstream
|
||||
//! crates (rlibs/dylibs/oh my).
|
||||
//!
|
||||
//! When producing a final artifact, such as a dynamic library, the compiler has
|
||||
//! a choice between linking an rlib or linking a dylib of all upstream
|
||||
//! dependencies. The linking phase must guarantee, however, that a library only
|
||||
//! show up once in the object file. For example, it is illegal for library A to
|
||||
//! be statically linked to B and C in separate dylibs, and then link B and C
|
||||
//! into a crate D (because library A appears twice).
|
||||
//!
|
||||
//! The job of this module is to calculate what format each upstream crate
|
||||
//! should be used when linking each output type requested in this session. This
|
||||
//! generally follows this set of rules:
|
||||
//!
|
||||
//! 1. Each library must appear exactly once in the output.
|
||||
//! 2. Each rlib contains only one library (it's just an object file)
|
||||
//! 3. Each dylib can contain more than one library (due to static linking),
|
||||
//! and can also bring in many dynamic dependencies.
|
||||
//!
|
||||
//! With these constraints in mind, it's generally a very difficult problem to
|
||||
//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
|
||||
//! that NP-ness may come into the picture here...
|
||||
//!
|
||||
//! The current selection algorithm below looks mostly similar to:
|
||||
//!
|
||||
//! 1. If static linking is required, then require all upstream dependencies
|
||||
//! to be available as rlibs. If not, generate an error.
|
||||
//! 2. If static linking is requested (generating an executable), then
|
||||
//! attempt to use all upstream dependencies as rlibs. If any are not
|
||||
//! found, bail out and continue to step 3.
|
||||
//! 3. Static linking has failed, at least one library must be dynamically
|
||||
//! linked. Apply a heuristic by greedily maximizing the number of
|
||||
//! dynamically linked libraries.
|
||||
//! 4. Each upstream dependency available as a dynamic library is
|
||||
//! registered. The dependencies all propagate, adding to a map. It is
|
||||
//! possible for a dylib to add a static library as a dependency, but it
|
||||
//! is illegal for two dylibs to add the same static library as a
|
||||
//! dependency. The same dylib can be added twice. Additionally, it is
|
||||
//! illegal to add a static dependency when it was previously found as a
|
||||
//! dylib (and vice versa)
|
||||
//! 5. After all dynamic dependencies have been traversed, re-traverse the
|
||||
//! remaining dependencies and add them statically (if they haven't been
|
||||
//! added already).
|
||||
//!
|
||||
//! While not perfect, this algorithm should help support use-cases such as leaf
|
||||
//! dependencies being static while the larger tree of inner dependencies are
|
||||
//! all dynamic. This isn't currently very well battle tested, so it will likely
|
||||
//! fall short in some use cases.
|
||||
//!
|
||||
//! Currently, there is no way to specify the preference of linkage with a
|
||||
//! particular library (other than a global dynamic/static switch).
|
||||
//! Additionally, the algorithm is geared towards finding *any* solution rather
|
||||
//! than finding a number of solutions (there are normally quite a few).
|
||||
|
||||
use crate::hir::def_id::CrateNum;
|
||||
//! For all the gory details, see the provider of the `dependency_formats`
|
||||
//! query.
|
||||
|
||||
use crate::session::config;
|
||||
use crate::ty::TyCtxt;
|
||||
use crate::middle::cstore::{self, DepKind};
|
||||
use crate::middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
/// A list of dependencies for a certain crate type.
|
||||
///
|
||||
@ -71,324 +17,12 @@ pub type DependencyList = Vec<Linkage>;
|
||||
/// A mapping of all required dependencies for a particular flavor of output.
|
||||
///
|
||||
/// This is local to the tcx, and is generally relevant to one session.
|
||||
pub type Dependencies = FxHashMap<config::CrateType, DependencyList>;
|
||||
pub type Dependencies = Vec<(config::CrateType, DependencyList)>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
|
||||
pub enum Linkage {
|
||||
NotLinked,
|
||||
IncludedFromDylib,
|
||||
Static,
|
||||
Dynamic,
|
||||
}
|
||||
|
||||
pub fn calculate(tcx: TyCtxt<'_>) {
|
||||
let sess = &tcx.sess;
|
||||
let fmts = sess.crate_types.borrow().iter().map(|&ty| {
|
||||
let linkage = calculate_type(tcx, ty);
|
||||
verify_ok(tcx, &linkage);
|
||||
(ty, linkage)
|
||||
}).collect::<FxHashMap<_, _>>();
|
||||
sess.abort_if_errors();
|
||||
sess.dependency_formats.set(fmts);
|
||||
}
|
||||
|
||||
fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
|
||||
let sess = &tcx.sess;
|
||||
|
||||
if !sess.opts.output_types.should_codegen() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let preferred_linkage = match ty {
|
||||
// cdylibs must have all static dependencies.
|
||||
config::CrateType::Cdylib => Linkage::Static,
|
||||
|
||||
// Generating a dylib without `-C prefer-dynamic` means that we're going
|
||||
// to try to eagerly statically link all dependencies. This is normally
|
||||
// done for end-product dylibs, not intermediate products.
|
||||
config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
|
||||
config::CrateType::Dylib => Linkage::Dynamic,
|
||||
|
||||
// If the global prefer_dynamic switch is turned off, or the final
|
||||
// executable will be statically linked, prefer static crate linkage.
|
||||
config::CrateType::Executable if !sess.opts.cg.prefer_dynamic ||
|
||||
sess.crt_static() => Linkage::Static,
|
||||
config::CrateType::Executable => Linkage::Dynamic,
|
||||
|
||||
// proc-macro crates are mostly cdylibs, but we also need metadata.
|
||||
config::CrateType::ProcMacro => Linkage::Static,
|
||||
|
||||
// No linkage happens with rlibs, we just needed the metadata (which we
|
||||
// got long ago), so don't bother with anything.
|
||||
config::CrateType::Rlib => Linkage::NotLinked,
|
||||
|
||||
// staticlibs must have all static dependencies.
|
||||
config::CrateType::Staticlib => Linkage::Static,
|
||||
};
|
||||
|
||||
if preferred_linkage == Linkage::NotLinked {
|
||||
// If the crate is not linked, there are no link-time dependencies.
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
if preferred_linkage == Linkage::Static {
|
||||
// Attempt static linkage first. For dylibs and executables, we may be
|
||||
// able to retry below with dynamic linkage.
|
||||
if let Some(v) = attempt_static(tcx) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// Staticlibs, cdylibs, and static executables must have all static
|
||||
// dependencies. If any are not found, generate some nice pretty errors.
|
||||
if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib ||
|
||||
(ty == config::CrateType::Executable && sess.crt_static() &&
|
||||
!sess.target.target.options.crt_static_allows_dylibs) {
|
||||
for &cnum in tcx.crates().iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() { continue }
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.rlib.is_some() { continue }
|
||||
sess.err(&format!("crate `{}` required to be available in rlib format, \
|
||||
but was not found in this form",
|
||||
tcx.crate_name(cnum)));
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
let mut formats = FxHashMap::default();
|
||||
|
||||
// Sweep all crates for found dylibs. Add all dylibs, as well as their
|
||||
// dependencies, ensuring there are no conflicts. The only valid case for a
|
||||
// dependency to be relied upon twice is for both cases to rely on a dylib.
|
||||
for &cnum in tcx.crates().iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() { continue }
|
||||
let name = tcx.crate_name(cnum);
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.dylib.is_some() {
|
||||
info!("adding dylib: {}", name);
|
||||
add_library(tcx, cnum, RequireDynamic, &mut formats);
|
||||
let deps = tcx.dylib_dependency_formats(cnum);
|
||||
for &(depnum, style) in deps.iter() {
|
||||
info!("adding {:?}: {}", style, tcx.crate_name(depnum));
|
||||
add_library(tcx, depnum, style, &mut formats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect what we've got so far in the return vector.
|
||||
let last_crate = tcx.crates().len();
|
||||
let mut ret = (1..last_crate+1).map(|cnum| {
|
||||
match formats.get(&CrateNum::new(cnum)) {
|
||||
Some(&RequireDynamic) => Linkage::Dynamic,
|
||||
Some(&RequireStatic) => Linkage::IncludedFromDylib,
|
||||
None => Linkage::NotLinked,
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Run through the dependency list again, and add any missing libraries as
|
||||
// static libraries.
|
||||
//
|
||||
// If the crate hasn't been included yet and it's not actually required
|
||||
// (e.g., it's an allocator) then we skip it here as well.
|
||||
for &cnum in tcx.crates().iter() {
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.dylib.is_none() &&
|
||||
!formats.contains_key(&cnum) &&
|
||||
tcx.dep_kind(cnum) == DepKind::Explicit {
|
||||
assert!(src.rlib.is_some() || src.rmeta.is_some());
|
||||
info!("adding staticlib: {}", tcx.crate_name(cnum));
|
||||
add_library(tcx, cnum, RequireStatic, &mut formats);
|
||||
ret[cnum.as_usize() - 1] = Linkage::Static;
|
||||
}
|
||||
}
|
||||
|
||||
// We've gotten this far because we're emitting some form of a final
|
||||
// artifact which means that we may need to inject dependencies of some
|
||||
// form.
|
||||
//
|
||||
// Things like allocators and panic runtimes may not have been activated
|
||||
// quite yet, so do so here.
|
||||
activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
|
||||
&|cnum| tcx.is_panic_runtime(cnum));
|
||||
|
||||
// When dylib B links to dylib A, then when using B we must also link to A.
|
||||
// It could be the case, however, that the rlib for A is present (hence we
|
||||
// found metadata), but the dylib for A has since been removed.
|
||||
//
|
||||
// For situations like this, we perform one last pass over the dependencies,
|
||||
// making sure that everything is available in the requested format.
|
||||
for (cnum, kind) in ret.iter().enumerate() {
|
||||
let cnum = CrateNum::new(cnum + 1);
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
match *kind {
|
||||
Linkage::NotLinked |
|
||||
Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static if src.rlib.is_some() => continue,
|
||||
Linkage::Dynamic if src.dylib.is_some() => continue,
|
||||
kind => {
|
||||
let kind = match kind {
|
||||
Linkage::Static => "rlib",
|
||||
_ => "dylib",
|
||||
};
|
||||
sess.err(&format!("crate `{}` required to be available in {} format, \
|
||||
but was not found in this form",
|
||||
tcx.crate_name(cnum), kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn add_library(
|
||||
tcx: TyCtxt<'_>,
|
||||
cnum: CrateNum,
|
||||
link: LinkagePreference,
|
||||
m: &mut FxHashMap<CrateNum, LinkagePreference>,
|
||||
) {
|
||||
match m.get(&cnum) {
|
||||
Some(&link2) => {
|
||||
// If the linkages differ, then we'd have two copies of the library
|
||||
// if we continued linking. If the linkages are both static, then we
|
||||
// would also have two copies of the library (static from two
|
||||
// different locations).
|
||||
//
|
||||
// This error is probably a little obscure, but I imagine that it
|
||||
// can be refined over time.
|
||||
if link2 != link || link == RequireStatic {
|
||||
tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \
|
||||
shows up once", tcx.crate_name(cnum)))
|
||||
.help("having upstream crates all available in one format \
|
||||
will likely make this go away")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
None => { m.insert(cnum, link); }
|
||||
}
|
||||
}
|
||||
|
||||
fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
|
||||
let sess = &tcx.sess;
|
||||
let crates = cstore::used_crates(tcx, RequireStatic);
|
||||
if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
|
||||
return None
|
||||
}
|
||||
|
||||
// All crates are available in an rlib format, so we're just going to link
|
||||
// everything in explicitly so long as it's actually required.
|
||||
let last_crate = tcx.crates().len();
|
||||
let mut ret = (1..last_crate+1).map(|cnum| {
|
||||
if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit {
|
||||
Linkage::Static
|
||||
} else {
|
||||
Linkage::NotLinked
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Our allocator/panic runtime may not have been linked above if it wasn't
|
||||
// explicitly linked, which is the case for any injected dependency. Handle
|
||||
// that here and activate them.
|
||||
activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
|
||||
&|cnum| tcx.is_panic_runtime(cnum));
|
||||
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
// Given a list of how to link upstream dependencies so far, ensure that an
|
||||
// injected dependency is activated. This will not do anything if one was
|
||||
// transitively included already (e.g., via a dylib or explicitly so).
|
||||
//
|
||||
// If an injected dependency was not found then we're guaranteed the
|
||||
// metadata::creader module has injected that dependency (not listed as
|
||||
// a required dependency) in one of the session's field. If this field is not
|
||||
// set then this compilation doesn't actually need the dependency and we can
|
||||
// also skip this step entirely.
|
||||
fn activate_injected_dep(injected: Option<CrateNum>,
|
||||
list: &mut DependencyList,
|
||||
replaces_injected: &dyn Fn(CrateNum) -> bool) {
|
||||
for (i, slot) in list.iter().enumerate() {
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
if !replaces_injected(cnum) {
|
||||
continue
|
||||
}
|
||||
if *slot != Linkage::NotLinked {
|
||||
return
|
||||
}
|
||||
}
|
||||
if let Some(injected) = injected {
|
||||
let idx = injected.as_usize() - 1;
|
||||
assert_eq!(list[idx], Linkage::NotLinked);
|
||||
list[idx] = Linkage::Static;
|
||||
}
|
||||
}
|
||||
|
||||
// After the linkage for a crate has been determined we need to verify that
|
||||
// there's only going to be one allocator in the output.
|
||||
fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
|
||||
let sess = &tcx.sess;
|
||||
if list.len() == 0 {
|
||||
return
|
||||
}
|
||||
let mut panic_runtime = None;
|
||||
for (i, linkage) in list.iter().enumerate() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue
|
||||
}
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
|
||||
if tcx.is_panic_runtime(cnum) {
|
||||
if let Some((prev, _)) = panic_runtime {
|
||||
let prev_name = tcx.crate_name(prev);
|
||||
let cur_name = tcx.crate_name(cnum);
|
||||
sess.err(&format!("cannot link together two \
|
||||
panic runtimes: {} and {}",
|
||||
prev_name, cur_name));
|
||||
}
|
||||
panic_runtime = Some((cnum, tcx.panic_strategy(cnum)));
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a panic runtime, then we know by this point that it's the
|
||||
// only one, but we perform validation here that all the panic strategy
|
||||
// compilation modes for the whole DAG are valid.
|
||||
if let Some((cnum, found_strategy)) = panic_runtime {
|
||||
let desired_strategy = sess.panic_strategy();
|
||||
|
||||
// First up, validate that our selected panic runtime is indeed exactly
|
||||
// our same strategy.
|
||||
if found_strategy != desired_strategy {
|
||||
sess.err(&format!("the linked panic runtime `{}` is \
|
||||
not compiled with this crate's \
|
||||
panic strategy `{}`",
|
||||
tcx.crate_name(cnum),
|
||||
desired_strategy.desc()));
|
||||
}
|
||||
|
||||
// Next up, verify that all other crates are compatible with this panic
|
||||
// strategy. If the dep isn't linked, we ignore it, and if our strategy
|
||||
// is abort then it's compatible with everything. Otherwise all crates'
|
||||
// panic strategy must match our own.
|
||||
for (i, linkage) in list.iter().enumerate() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue
|
||||
}
|
||||
if desired_strategy == PanicStrategy::Abort {
|
||||
continue
|
||||
}
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
let found_strategy = tcx.panic_strategy(cnum);
|
||||
let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
|
||||
if is_compiler_builtins || desired_strategy == found_strategy {
|
||||
continue
|
||||
}
|
||||
|
||||
sess.err(&format!("the crate `{}` is compiled with the \
|
||||
panic strategy `{}` which is \
|
||||
incompatible with this crate's \
|
||||
strategy of `{}`",
|
||||
tcx.crate_name(cnum),
|
||||
found_strategy.desc(),
|
||||
desired_strategy.desc()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,6 +244,10 @@ rustc_queries! {
|
||||
desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
query asyncness(key: DefId) -> hir::IsAsync {
|
||||
desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
/// Returns `true` if calls to the function may be promoted.
|
||||
///
|
||||
/// This is either because the function is e.g., a tuple-struct or tuple-variant
|
||||
@ -630,6 +634,12 @@ rustc_queries! {
|
||||
-> &'tcx [(CrateNum, LinkagePreference)] {
|
||||
desc { "dylib dependency formats of crate" }
|
||||
}
|
||||
|
||||
query dependency_formats(_: CrateNum)
|
||||
-> Lrc<crate::middle::dependency_format::Dependencies>
|
||||
{
|
||||
desc { "get the linkage format of all dependencies" }
|
||||
}
|
||||
}
|
||||
|
||||
Codegen {
|
||||
|
@ -687,7 +687,7 @@ pub enum EntryFnType {
|
||||
|
||||
impl_stable_hash_via_hash!(EntryFnType);
|
||||
|
||||
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
|
||||
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, HashStable)]
|
||||
pub enum CrateType {
|
||||
Executable,
|
||||
Dylib,
|
||||
|
@ -7,7 +7,6 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||
|
||||
use crate::lint;
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::middle::dependency_format;
|
||||
use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
|
||||
use crate::session::search_paths::{PathKind, SearchPath};
|
||||
use crate::util::nodemap::{FxHashMap, FxHashSet};
|
||||
@ -91,7 +90,6 @@ pub struct Session {
|
||||
pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
|
||||
pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
|
||||
pub crate_types: Once<Vec<config::CrateType>>,
|
||||
pub dependency_formats: Once<dependency_format::Dependencies>,
|
||||
/// The `crate_disambiguator` is constructed out of all the `-C metadata`
|
||||
/// arguments passed to the compiler. Its value together with the crate-name
|
||||
/// forms a unique global identifier for the crate. It is used to allow
|
||||
@ -1248,7 +1246,6 @@ fn build_session_(
|
||||
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
|
||||
plugin_attributes: Lock::new(Vec::new()),
|
||||
crate_types: Once::new(),
|
||||
dependency_formats: Once::new(),
|
||||
crate_disambiguator: Once::new(),
|
||||
features: Once::new(),
|
||||
recursion_limit: Once::new(),
|
||||
|
@ -1432,8 +1432,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>,
|
||||
body_id: Option<hir::BodyId>) {
|
||||
fn maybe_report_ambiguity(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
body_id: Option<hir::BodyId>,
|
||||
) {
|
||||
// Unable to successfully determine, probably means
|
||||
// insufficient type information, but could mean
|
||||
// ambiguous impls. The latter *ought* to be a
|
||||
@ -1442,9 +1445,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
let predicate = self.resolve_vars_if_possible(&obligation.predicate);
|
||||
let span = obligation.cause.span;
|
||||
|
||||
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
|
||||
predicate,
|
||||
obligation);
|
||||
debug!(
|
||||
"maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
|
||||
predicate,
|
||||
obligation,
|
||||
body_id,
|
||||
obligation.cause.code,
|
||||
);
|
||||
|
||||
// Ambiguity errors are often caused as fallout from earlier
|
||||
// errors. So just ignore them if this infcx is tainted.
|
||||
@ -1456,6 +1463,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
ty::Predicate::Trait(ref data) => {
|
||||
let trait_ref = data.to_poly_trait_ref();
|
||||
let self_ty = trait_ref.self_ty();
|
||||
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.sty, trait_ref);
|
||||
|
||||
if predicate.references_error() {
|
||||
return;
|
||||
}
|
||||
@ -1480,24 +1489,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
// be ignoring the fact that we don't KNOW the type works
|
||||
// out. Though even that would probably be harmless, given that
|
||||
// we're only talking about builtin traits, which are known to be
|
||||
// inhabited. But in any case I just threw in this check for
|
||||
// has_errors() to be sure that compilation isn't happening
|
||||
// anyway. In that case, why inundate the user.
|
||||
if !self.tcx.sess.has_errors() {
|
||||
if
|
||||
self.tcx.lang_items().sized_trait()
|
||||
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
||||
{
|
||||
self.need_type_info_err(body_id, span, self_ty).emit();
|
||||
} else {
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
span, E0283,
|
||||
"type annotations required: \
|
||||
cannot resolve `{}`",
|
||||
predicate);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
// inhabited. We used to check for `self.tcx.sess.has_errors()` to
|
||||
// avoid inundating the user with unnecessary errors, but we now
|
||||
// check upstream for type errors and dont add the obligations to
|
||||
// begin with in those cases.
|
||||
if
|
||||
self.tcx.lang_items().sized_trait()
|
||||
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
|
||||
{
|
||||
self.need_type_info_err(body_id, span, self_ty).emit();
|
||||
} else {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0283,
|
||||
"type annotations needed: cannot resolve `{}`",
|
||||
predicate,
|
||||
);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1524,11 +1534,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
_ => {
|
||||
if !self.tcx.sess.has_errors() {
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
obligation.cause.span, E0284,
|
||||
"type annotations required: \
|
||||
cannot resolve `{}`",
|
||||
predicate);
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
obligation.cause.span,
|
||||
E0284,
|
||||
"type annotations needed: cannot resolve `{}`",
|
||||
predicate,
|
||||
);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
@ -1766,7 +1778,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
but not on the corresponding trait method",
|
||||
predicate));
|
||||
}
|
||||
ObligationCauseCode::ReturnType(_) |
|
||||
ObligationCauseCode::ReturnType |
|
||||
ObligationCauseCode::ReturnValue(_) |
|
||||
ObligationCauseCode::BlockTailExpression(_) => (),
|
||||
ObligationCauseCode::TrivialBound => {
|
||||
err.help("see issue #48214");
|
||||
|
@ -212,14 +212,14 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// Constant expressions must be sized.
|
||||
ConstSized,
|
||||
|
||||
/// static items must have `Sync` type
|
||||
/// Static items must have `Sync` type
|
||||
SharedStatic,
|
||||
|
||||
BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
|
||||
|
||||
ImplDerivedObligation(DerivedObligationCause<'tcx>),
|
||||
|
||||
/// error derived when matching traits/impls; see ObligationCause for more details
|
||||
/// Error derived when matching traits/impls; see ObligationCause for more details
|
||||
CompareImplMethodObligation {
|
||||
item_name: ast::Name,
|
||||
impl_item_def_id: DefId,
|
||||
@ -248,17 +248,20 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// `start` has wrong type
|
||||
StartFunctionType,
|
||||
|
||||
/// intrinsic has wrong type
|
||||
/// Intrinsic has wrong type
|
||||
IntrinsicType,
|
||||
|
||||
/// method receiver
|
||||
/// Method receiver
|
||||
MethodReceiver,
|
||||
|
||||
/// `return` with no expression
|
||||
ReturnNoExpression,
|
||||
|
||||
/// `return` with an expression
|
||||
ReturnType(hir::HirId),
|
||||
ReturnValue(hir::HirId),
|
||||
|
||||
/// Return type of this function
|
||||
ReturnType,
|
||||
|
||||
/// Block implicit return
|
||||
BlockTailExpression(hir::HirId),
|
||||
|
@ -214,7 +214,7 @@ pub struct SelectionCache<'tcx> {
|
||||
/// of type variables - it just means the obligation isn't sufficiently
|
||||
/// elaborated. In that case we report an ambiguity, and the caller can
|
||||
/// try again after more type information has been gathered or report a
|
||||
/// "type annotations required" error.
|
||||
/// "type annotations needed" error.
|
||||
///
|
||||
/// However, with type parameters, this can be a real problem - type
|
||||
/// parameters don't unify with regular types, but they *can* unify
|
||||
|
@ -485,7 +485,8 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||
super::StructInitializerSized => Some(super::StructInitializerSized),
|
||||
super::VariableType(id) => Some(super::VariableType(id)),
|
||||
super::ReturnType(id) => Some(super::ReturnType(id)),
|
||||
super::ReturnValue(id) => Some(super::ReturnValue(id)),
|
||||
super::ReturnType => Some(super::ReturnType),
|
||||
super::SizedArgumentType => Some(super::SizedArgumentType),
|
||||
super::SizedReturnType => Some(super::SizedReturnType),
|
||||
super::SizedYieldType => Some(super::SizedYieldType),
|
||||
|
@ -1510,9 +1510,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
CrateType::Executable |
|
||||
CrateType::Staticlib |
|
||||
CrateType::ProcMacro |
|
||||
CrateType::Dylib |
|
||||
CrateType::Cdylib => false,
|
||||
CrateType::Rlib |
|
||||
CrateType::Dylib => true,
|
||||
CrateType::Rlib => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ bitflags! {
|
||||
|
||||
/// `true` if there are "names" of types and regions and so forth
|
||||
/// that are local to a particular fn
|
||||
const HAS_FREE_LOCAL_NAMES = 1 << 9;
|
||||
const HAS_FREE_LOCAL_NAMES = 1 << 9;
|
||||
|
||||
/// Present if the type belongs in a local type context.
|
||||
/// Only set for Infer other than Fresh.
|
||||
@ -446,11 +446,11 @@ bitflags! {
|
||||
|
||||
/// Does this have any `ReLateBound` regions? Used to check
|
||||
/// if a global bound is safe to evaluate.
|
||||
const HAS_RE_LATE_BOUND = 1 << 11;
|
||||
const HAS_RE_LATE_BOUND = 1 << 11;
|
||||
|
||||
const HAS_TY_PLACEHOLDER = 1 << 12;
|
||||
|
||||
const HAS_CT_INFER = 1 << 13;
|
||||
const HAS_CT_INFER = 1 << 13;
|
||||
const HAS_CT_PLACEHOLDER = 1 << 14;
|
||||
|
||||
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
|
||||
@ -3353,6 +3353,22 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a function is async.
|
||||
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
|
||||
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(|| {
|
||||
bug!("asyncness: expected local `DefId`, got `{:?}`", def_id)
|
||||
});
|
||||
|
||||
let node = tcx.hir().get(hir_id);
|
||||
|
||||
let fn_like = hir::map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
|
||||
bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
|
||||
});
|
||||
|
||||
fn_like.asyncness()
|
||||
}
|
||||
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
context::provide(providers);
|
||||
erase_regions::provide(providers);
|
||||
@ -3360,6 +3376,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
util::provide(providers);
|
||||
constness::provide(providers);
|
||||
*providers = ty::query::Providers {
|
||||
asyncness,
|
||||
associated_item,
|
||||
associated_item_def_ids,
|
||||
adt_sized_constraint,
|
||||
|
@ -219,15 +219,24 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB
|
||||
(linker.to_path_buf(), cmd)
|
||||
}
|
||||
|
||||
pub fn each_linked_rlib(sess: &Session,
|
||||
info: &CrateInfo,
|
||||
f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
|
||||
pub fn each_linked_rlib(
|
||||
info: &CrateInfo,
|
||||
f: &mut dyn FnMut(CrateNum, &Path),
|
||||
) -> Result<(), String> {
|
||||
let crates = info.used_crates_static.iter();
|
||||
let fmts = sess.dependency_formats.borrow();
|
||||
let fmts = fmts.get(&config::CrateType::Executable)
|
||||
.or_else(|| fmts.get(&config::CrateType::Staticlib))
|
||||
.or_else(|| fmts.get(&config::CrateType::Cdylib))
|
||||
.or_else(|| fmts.get(&config::CrateType::ProcMacro));
|
||||
let mut fmts = None;
|
||||
for (ty, list) in info.dependency_formats.iter() {
|
||||
match ty {
|
||||
config::CrateType::Executable |
|
||||
config::CrateType::Staticlib |
|
||||
config::CrateType::Cdylib |
|
||||
config::CrateType::ProcMacro => {
|
||||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let fmts = match fmts {
|
||||
Some(f) => f,
|
||||
None => return Err("could not find formats for rlibs".to_string())
|
||||
@ -406,7 +415,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
|
||||
tempdir);
|
||||
let mut all_native_libs = vec![];
|
||||
|
||||
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
||||
let name = &codegen_results.crate_info.crate_name[&cnum];
|
||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||
|
||||
@ -1294,11 +1303,13 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker,
|
||||
// Rust crates are not considered at all when creating an rlib output. All
|
||||
// dependencies will be linked when producing the final output (instead of
|
||||
// the intermediate rlib version)
|
||||
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
|
||||
sess: &'a Session,
|
||||
codegen_results: &CodegenResults,
|
||||
crate_type: config::CrateType,
|
||||
tmpdir: &Path) {
|
||||
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &'a Session,
|
||||
codegen_results: &CodegenResults,
|
||||
crate_type: config::CrateType,
|
||||
tmpdir: &Path,
|
||||
) {
|
||||
// All of the heavy lifting has previously been accomplished by the
|
||||
// dependency_format module of the compiler. This is just crawling the
|
||||
// output of that module, adding crates as necessary.
|
||||
@ -1307,8 +1318,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
|
||||
// will slurp up the object files inside), and linking to a dynamic library
|
||||
// involves just passing the right -l flag.
|
||||
|
||||
let formats = sess.dependency_formats.borrow();
|
||||
let data = formats.get(&crate_type).unwrap();
|
||||
let (_, data) = codegen_results.crate_info.dependency_formats
|
||||
.iter()
|
||||
.find(|(ty, _)| *ty == crate_type)
|
||||
.expect("failed to find crate type in dependency format list");
|
||||
|
||||
// Invoke get_used_crates to ensure that we get a topological sorting of
|
||||
// crates.
|
||||
@ -1620,10 +1633,12 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
|
||||
// generic function calls a native function, then the generic function must
|
||||
// be instantiated in the target crate, meaning that the native symbol must
|
||||
// also be resolved in the target crate.
|
||||
pub fn add_upstream_native_libraries(cmd: &mut dyn Linker,
|
||||
sess: &Session,
|
||||
codegen_results: &CodegenResults,
|
||||
crate_type: config::CrateType) {
|
||||
pub fn add_upstream_native_libraries(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &Session,
|
||||
codegen_results: &CodegenResults,
|
||||
crate_type: config::CrateType,
|
||||
) {
|
||||
// Be sure to use a topological sorting of crates because there may be
|
||||
// interdependencies between native libraries. When passing -nodefaultlibs,
|
||||
// for example, almost all native libraries depend on libc, so we have to
|
||||
@ -1633,8 +1648,10 @@ pub fn add_upstream_native_libraries(cmd: &mut dyn Linker,
|
||||
// This passes RequireStatic, but the actual requirement doesn't matter,
|
||||
// we're just getting an ordering of crate numbers, we're not worried about
|
||||
// the paths.
|
||||
let formats = sess.dependency_formats.borrow();
|
||||
let data = formats.get(&crate_type).unwrap();
|
||||
let (_, data) = codegen_results.crate_info.dependency_formats
|
||||
.iter()
|
||||
.find(|(ty, _)| *ty == crate_type)
|
||||
.expect("failed to find crate type in dependency format list");
|
||||
|
||||
let crates = &codegen_results.crate_info.used_crates_static;
|
||||
for &(cnum, _) in crates {
|
||||
|
@ -14,6 +14,7 @@ use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
|
||||
LinkerPluginLto, Lto};
|
||||
use rustc::middle::exported_symbols::ExportedSymbol;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_target::spec::{LinkerFlavor, LldFlavor};
|
||||
use rustc_serialize::{json, Encoder};
|
||||
@ -1092,18 +1093,41 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
}
|
||||
}
|
||||
|
||||
let formats = tcx.sess.dependency_formats.borrow();
|
||||
let deps = formats[&crate_type].iter();
|
||||
let formats = tcx.dependency_formats(LOCAL_CRATE);
|
||||
let deps = formats.iter().filter_map(|(t, list)| {
|
||||
if *t == crate_type {
|
||||
Some(list)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).next().unwrap();
|
||||
|
||||
for (index, dep_format) in deps.enumerate() {
|
||||
for (index, dep_format) in deps.iter().enumerate() {
|
||||
let cnum = CrateNum::new(index + 1);
|
||||
// For each dependency that we are linking to statically ...
|
||||
if *dep_format == Linkage::Static {
|
||||
// ... we add its symbol list to our export list.
|
||||
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
|
||||
if level.is_below_threshold(export_threshold) {
|
||||
symbols.push(symbol.symbol_name(tcx).to_string());
|
||||
if !level.is_below_threshold(export_threshold) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not export generic symbols from upstream crates in linked
|
||||
// artifact (notably the `dylib` crate type). The main reason
|
||||
// for this is that `symbol_name` is actually wrong for generic
|
||||
// symbols because it guesses the name we'd give them locally
|
||||
// rather than the name it has upstream (depending on
|
||||
// `share_generics` settings and such).
|
||||
//
|
||||
// To fix that issue we just say that linked artifacts, aka
|
||||
// `dylib`s, never export generic symbols and they aren't
|
||||
// available to downstream crates. (the not available part is
|
||||
// handled elsewhere).
|
||||
if let ExportedSymbol::Generic(..) = symbol {
|
||||
continue;
|
||||
}
|
||||
|
||||
symbols.push(symbol.symbol_name(tcx).to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ fn upstream_monomorphizations_provider(
|
||||
};
|
||||
|
||||
for &cnum in cnums.iter() {
|
||||
for &(ref exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
|
||||
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
|
||||
if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
|
||||
let substs_map = instances.entry(def_id).or_default();
|
||||
|
||||
|
@ -1048,7 +1048,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
}).expect("failed to spawn helper thread");
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
||||
drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
// linkage, then it's already got an allocator shim and we'll be using that
|
||||
// one instead. If nothing exists then it's our job to generate the
|
||||
// allocator!
|
||||
let any_dynamic_crate = tcx.sess.dependency_formats.borrow()
|
||||
let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE)
|
||||
.iter()
|
||||
.any(|(_, list)| {
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
@ -731,6 +731,7 @@ impl CrateInfo {
|
||||
used_crate_source: Default::default(),
|
||||
lang_item_to_crate: Default::default(),
|
||||
missing_lang_items: Default::default(),
|
||||
dependency_formats: tcx.dependency_formats(LOCAL_CRATE),
|
||||
};
|
||||
let lang_items = tcx.lang_items();
|
||||
|
||||
|
@ -33,6 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary};
|
||||
use rustc::middle::dependency_format::Dependencies;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
|
||||
mod error_codes;
|
||||
@ -142,6 +143,7 @@ pub struct CrateInfo {
|
||||
pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
|
||||
pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
|
||||
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
|
||||
pub dependency_formats: Lrc<Dependencies>,
|
||||
}
|
||||
|
||||
|
||||
|
@ -1075,10 +1075,6 @@ pub fn start_codegen<'tcx>(
|
||||
tcx.print_debug_stats();
|
||||
}
|
||||
|
||||
time(tcx.sess, "resolving dependency formats", || {
|
||||
middle::dependency_format::calculate(tcx)
|
||||
});
|
||||
|
||||
let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || {
|
||||
encode_and_write_metadata(tcx, outputs)
|
||||
});
|
||||
|
@ -10,6 +10,7 @@ use rustc::middle::cstore::{CrateStore, DepKind,
|
||||
EncodedMetadata, NativeLibraryKind};
|
||||
use rustc::middle::exported_symbols::ExportedSymbol;
|
||||
use rustc::middle::stability::DeprecationEntry;
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::hir::def;
|
||||
use rustc::hir;
|
||||
use rustc::session::{CrateDisambiguator, Session};
|
||||
@ -133,6 +134,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
|
||||
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
|
||||
is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) }
|
||||
asyncness => { cdata.asyncness(def_id.index) }
|
||||
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
|
||||
static_mutability => { cdata.static_mutability(def_id.index) }
|
||||
def_kind => { cdata.def_kind(def_id.index) }
|
||||
@ -239,7 +241,30 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
|
||||
used_crate_source => { Lrc::new(cdata.source.clone()) }
|
||||
|
||||
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
|
||||
exported_symbols => {
|
||||
let mut syms = cdata.exported_symbols(tcx);
|
||||
|
||||
// When linked into a dylib crates don't export their generic symbols,
|
||||
// so if that's happening then we can't load upstream monomorphizations
|
||||
// from this crate.
|
||||
let formats = tcx.dependency_formats(LOCAL_CRATE);
|
||||
let remove_generics = formats.iter().any(|(_ty, list)| {
|
||||
match list.get(def_id.krate.as_usize() - 1) {
|
||||
Some(Linkage::IncludedFromDylib) | Some(Linkage::Dynamic) => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
if remove_generics {
|
||||
syms.retain(|(sym, _threshold)| {
|
||||
match sym {
|
||||
ExportedSymbol::Generic(..) => false,
|
||||
_ => return true,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Arc::new(syms)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
@ -370,6 +395,11 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||
tcx.arena.alloc(visible_parent_map)
|
||||
},
|
||||
|
||||
dependency_formats: |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
Lrc::new(crate::dependency_format::calculate(tcx))
|
||||
},
|
||||
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -1212,6 +1212,15 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
constness == hir::Constness::Const
|
||||
}
|
||||
|
||||
pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
|
||||
match self.entry(id).kind {
|
||||
EntryKind::Fn(data) => data.decode(self).asyncness,
|
||||
EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
|
||||
EntryKind::ForeignFn(data) => data.decode(self).asyncness,
|
||||
_ => bug!("asyncness: expect functions entry."),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_foreign_item(&self, id: DefIndex) -> bool {
|
||||
match self.entry(id).kind {
|
||||
EntryKind::ForeignImmStatic |
|
||||
|
370
src/librustc_metadata/dependency_format.rs
Normal file
370
src/librustc_metadata/dependency_format.rs
Normal file
@ -0,0 +1,370 @@
|
||||
//! Resolution of mixing rlibs and dylibs
|
||||
//!
|
||||
//! When producing a final artifact, such as a dynamic library, the compiler has
|
||||
//! a choice between linking an rlib or linking a dylib of all upstream
|
||||
//! dependencies. The linking phase must guarantee, however, that a library only
|
||||
//! show up once in the object file. For example, it is illegal for library A to
|
||||
//! be statically linked to B and C in separate dylibs, and then link B and C
|
||||
//! into a crate D (because library A appears twice).
|
||||
//!
|
||||
//! The job of this module is to calculate what format each upstream crate
|
||||
//! should be used when linking each output type requested in this session. This
|
||||
//! generally follows this set of rules:
|
||||
//!
|
||||
//! 1. Each library must appear exactly once in the output.
|
||||
//! 2. Each rlib contains only one library (it's just an object file)
|
||||
//! 3. Each dylib can contain more than one library (due to static linking),
|
||||
//! and can also bring in many dynamic dependencies.
|
||||
//!
|
||||
//! With these constraints in mind, it's generally a very difficult problem to
|
||||
//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
|
||||
//! that NP-ness may come into the picture here...
|
||||
//!
|
||||
//! The current selection algorithm below looks mostly similar to:
|
||||
//!
|
||||
//! 1. If static linking is required, then require all upstream dependencies
|
||||
//! to be available as rlibs. If not, generate an error.
|
||||
//! 2. If static linking is requested (generating an executable), then
|
||||
//! attempt to use all upstream dependencies as rlibs. If any are not
|
||||
//! found, bail out and continue to step 3.
|
||||
//! 3. Static linking has failed, at least one library must be dynamically
|
||||
//! linked. Apply a heuristic by greedily maximizing the number of
|
||||
//! dynamically linked libraries.
|
||||
//! 4. Each upstream dependency available as a dynamic library is
|
||||
//! registered. The dependencies all propagate, adding to a map. It is
|
||||
//! possible for a dylib to add a static library as a dependency, but it
|
||||
//! is illegal for two dylibs to add the same static library as a
|
||||
//! dependency. The same dylib can be added twice. Additionally, it is
|
||||
//! illegal to add a static dependency when it was previously found as a
|
||||
//! dylib (and vice versa)
|
||||
//! 5. After all dynamic dependencies have been traversed, re-traverse the
|
||||
//! remaining dependencies and add them statically (if they haven't been
|
||||
//! added already).
|
||||
//!
|
||||
//! While not perfect, this algorithm should help support use-cases such as leaf
|
||||
//! dependencies being static while the larger tree of inner dependencies are
|
||||
//! all dynamic. This isn't currently very well battle tested, so it will likely
|
||||
//! fall short in some use cases.
|
||||
//!
|
||||
//! Currently, there is no way to specify the preference of linkage with a
|
||||
//! particular library (other than a global dynamic/static switch).
|
||||
//! Additionally, the algorithm is geared towards finding *any* solution rather
|
||||
//! than finding a number of solutions (there are normally quite a few).
|
||||
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
|
||||
use rustc::middle::cstore::{self, DepKind};
|
||||
use rustc::middle::dependency_format::{DependencyList, Dependencies, Linkage};
|
||||
use rustc::session::config;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
pub fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
|
||||
tcx.sess.crate_types.borrow().iter().map(|&ty| {
|
||||
let linkage = calculate_type(tcx, ty);
|
||||
verify_ok(tcx, &linkage);
|
||||
(ty, linkage)
|
||||
}).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
|
||||
let sess = &tcx.sess;
|
||||
|
||||
if !sess.opts.output_types.should_codegen() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let preferred_linkage = match ty {
|
||||
// cdylibs must have all static dependencies.
|
||||
config::CrateType::Cdylib => Linkage::Static,
|
||||
|
||||
// Generating a dylib without `-C prefer-dynamic` means that we're going
|
||||
// to try to eagerly statically link all dependencies. This is normally
|
||||
// done for end-product dylibs, not intermediate products.
|
||||
config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
|
||||
config::CrateType::Dylib => Linkage::Dynamic,
|
||||
|
||||
// If the global prefer_dynamic switch is turned off, or the final
|
||||
// executable will be statically linked, prefer static crate linkage.
|
||||
config::CrateType::Executable if !sess.opts.cg.prefer_dynamic ||
|
||||
sess.crt_static() => Linkage::Static,
|
||||
config::CrateType::Executable => Linkage::Dynamic,
|
||||
|
||||
// proc-macro crates are mostly cdylibs, but we also need metadata.
|
||||
config::CrateType::ProcMacro => Linkage::Static,
|
||||
|
||||
// No linkage happens with rlibs, we just needed the metadata (which we
|
||||
// got long ago), so don't bother with anything.
|
||||
config::CrateType::Rlib => Linkage::NotLinked,
|
||||
|
||||
// staticlibs must have all static dependencies.
|
||||
config::CrateType::Staticlib => Linkage::Static,
|
||||
};
|
||||
|
||||
if preferred_linkage == Linkage::NotLinked {
|
||||
// If the crate is not linked, there are no link-time dependencies.
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
if preferred_linkage == Linkage::Static {
|
||||
// Attempt static linkage first. For dylibs and executables, we may be
|
||||
// able to retry below with dynamic linkage.
|
||||
if let Some(v) = attempt_static(tcx) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// Staticlibs, cdylibs, and static executables must have all static
|
||||
// dependencies. If any are not found, generate some nice pretty errors.
|
||||
if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib ||
|
||||
(ty == config::CrateType::Executable && sess.crt_static() &&
|
||||
!sess.target.target.options.crt_static_allows_dylibs) {
|
||||
for &cnum in tcx.crates().iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() { continue }
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.rlib.is_some() { continue }
|
||||
sess.err(&format!("crate `{}` required to be available in rlib format, \
|
||||
but was not found in this form",
|
||||
tcx.crate_name(cnum)));
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
let mut formats = FxHashMap::default();
|
||||
|
||||
// Sweep all crates for found dylibs. Add all dylibs, as well as their
|
||||
// dependencies, ensuring there are no conflicts. The only valid case for a
|
||||
// dependency to be relied upon twice is for both cases to rely on a dylib.
|
||||
for &cnum in tcx.crates().iter() {
|
||||
if tcx.dep_kind(cnum).macros_only() { continue }
|
||||
let name = tcx.crate_name(cnum);
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.dylib.is_some() {
|
||||
log::info!("adding dylib: {}", name);
|
||||
add_library(tcx, cnum, RequireDynamic, &mut formats);
|
||||
let deps = tcx.dylib_dependency_formats(cnum);
|
||||
for &(depnum, style) in deps.iter() {
|
||||
log::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
|
||||
add_library(tcx, depnum, style, &mut formats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect what we've got so far in the return vector.
|
||||
let last_crate = tcx.crates().len();
|
||||
let mut ret = (1..last_crate+1).map(|cnum| {
|
||||
match formats.get(&CrateNum::new(cnum)) {
|
||||
Some(&RequireDynamic) => Linkage::Dynamic,
|
||||
Some(&RequireStatic) => Linkage::IncludedFromDylib,
|
||||
None => Linkage::NotLinked,
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Run through the dependency list again, and add any missing libraries as
|
||||
// static libraries.
|
||||
//
|
||||
// If the crate hasn't been included yet and it's not actually required
|
||||
// (e.g., it's an allocator) then we skip it here as well.
|
||||
for &cnum in tcx.crates().iter() {
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
if src.dylib.is_none() &&
|
||||
!formats.contains_key(&cnum) &&
|
||||
tcx.dep_kind(cnum) == DepKind::Explicit {
|
||||
assert!(src.rlib.is_some() || src.rmeta.is_some());
|
||||
log::info!("adding staticlib: {}", tcx.crate_name(cnum));
|
||||
add_library(tcx, cnum, RequireStatic, &mut formats);
|
||||
ret[cnum.as_usize() - 1] = Linkage::Static;
|
||||
}
|
||||
}
|
||||
|
||||
// We've gotten this far because we're emitting some form of a final
|
||||
// artifact which means that we may need to inject dependencies of some
|
||||
// form.
|
||||
//
|
||||
// Things like allocators and panic runtimes may not have been activated
|
||||
// quite yet, so do so here.
|
||||
activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
|
||||
&|cnum| tcx.is_panic_runtime(cnum));
|
||||
|
||||
// When dylib B links to dylib A, then when using B we must also link to A.
|
||||
// It could be the case, however, that the rlib for A is present (hence we
|
||||
// found metadata), but the dylib for A has since been removed.
|
||||
//
|
||||
// For situations like this, we perform one last pass over the dependencies,
|
||||
// making sure that everything is available in the requested format.
|
||||
for (cnum, kind) in ret.iter().enumerate() {
|
||||
let cnum = CrateNum::new(cnum + 1);
|
||||
let src = tcx.used_crate_source(cnum);
|
||||
match *kind {
|
||||
Linkage::NotLinked |
|
||||
Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static if src.rlib.is_some() => continue,
|
||||
Linkage::Dynamic if src.dylib.is_some() => continue,
|
||||
kind => {
|
||||
let kind = match kind {
|
||||
Linkage::Static => "rlib",
|
||||
_ => "dylib",
|
||||
};
|
||||
sess.err(&format!("crate `{}` required to be available in {} format, \
|
||||
but was not found in this form",
|
||||
tcx.crate_name(cnum), kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn add_library(
|
||||
tcx: TyCtxt<'_>,
|
||||
cnum: CrateNum,
|
||||
link: LinkagePreference,
|
||||
m: &mut FxHashMap<CrateNum, LinkagePreference>,
|
||||
) {
|
||||
match m.get(&cnum) {
|
||||
Some(&link2) => {
|
||||
// If the linkages differ, then we'd have two copies of the library
|
||||
// if we continued linking. If the linkages are both static, then we
|
||||
// would also have two copies of the library (static from two
|
||||
// different locations).
|
||||
//
|
||||
// This error is probably a little obscure, but I imagine that it
|
||||
// can be refined over time.
|
||||
if link2 != link || link == RequireStatic {
|
||||
tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \
|
||||
shows up once", tcx.crate_name(cnum)))
|
||||
.help("having upstream crates all available in one format \
|
||||
will likely make this go away")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
None => { m.insert(cnum, link); }
|
||||
}
|
||||
}
|
||||
|
||||
fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
|
||||
let sess = &tcx.sess;
|
||||
let crates = cstore::used_crates(tcx, RequireStatic);
|
||||
if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
|
||||
return None
|
||||
}
|
||||
|
||||
// All crates are available in an rlib format, so we're just going to link
|
||||
// everything in explicitly so long as it's actually required.
|
||||
let last_crate = tcx.crates().len();
|
||||
let mut ret = (1..last_crate+1).map(|cnum| {
|
||||
if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit {
|
||||
Linkage::Static
|
||||
} else {
|
||||
Linkage::NotLinked
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Our allocator/panic runtime may not have been linked above if it wasn't
|
||||
// explicitly linked, which is the case for any injected dependency. Handle
|
||||
// that here and activate them.
|
||||
activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
|
||||
&|cnum| tcx.is_panic_runtime(cnum));
|
||||
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
// Given a list of how to link upstream dependencies so far, ensure that an
|
||||
// injected dependency is activated. This will not do anything if one was
|
||||
// transitively included already (e.g., via a dylib or explicitly so).
|
||||
//
|
||||
// If an injected dependency was not found then we're guaranteed the
|
||||
// metadata::creader module has injected that dependency (not listed as
|
||||
// a required dependency) in one of the session's field. If this field is not
|
||||
// set then this compilation doesn't actually need the dependency and we can
|
||||
// also skip this step entirely.
|
||||
fn activate_injected_dep(injected: Option<CrateNum>,
|
||||
list: &mut DependencyList,
|
||||
replaces_injected: &dyn Fn(CrateNum) -> bool) {
|
||||
for (i, slot) in list.iter().enumerate() {
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
if !replaces_injected(cnum) {
|
||||
continue
|
||||
}
|
||||
if *slot != Linkage::NotLinked {
|
||||
return
|
||||
}
|
||||
}
|
||||
if let Some(injected) = injected {
|
||||
let idx = injected.as_usize() - 1;
|
||||
assert_eq!(list[idx], Linkage::NotLinked);
|
||||
list[idx] = Linkage::Static;
|
||||
}
|
||||
}
|
||||
|
||||
// After the linkage for a crate has been determined we need to verify that
|
||||
// there's only going to be one allocator in the output.
|
||||
fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
|
||||
let sess = &tcx.sess;
|
||||
if list.len() == 0 {
|
||||
return
|
||||
}
|
||||
let mut panic_runtime = None;
|
||||
for (i, linkage) in list.iter().enumerate() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue
|
||||
}
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
|
||||
if tcx.is_panic_runtime(cnum) {
|
||||
if let Some((prev, _)) = panic_runtime {
|
||||
let prev_name = tcx.crate_name(prev);
|
||||
let cur_name = tcx.crate_name(cnum);
|
||||
sess.err(&format!("cannot link together two \
|
||||
panic runtimes: {} and {}",
|
||||
prev_name, cur_name));
|
||||
}
|
||||
panic_runtime = Some((cnum, tcx.panic_strategy(cnum)));
|
||||
}
|
||||
}
|
||||
|
||||
// If we found a panic runtime, then we know by this point that it's the
|
||||
// only one, but we perform validation here that all the panic strategy
|
||||
// compilation modes for the whole DAG are valid.
|
||||
if let Some((cnum, found_strategy)) = panic_runtime {
|
||||
let desired_strategy = sess.panic_strategy();
|
||||
|
||||
// First up, validate that our selected panic runtime is indeed exactly
|
||||
// our same strategy.
|
||||
if found_strategy != desired_strategy {
|
||||
sess.err(&format!("the linked panic runtime `{}` is \
|
||||
not compiled with this crate's \
|
||||
panic strategy `{}`",
|
||||
tcx.crate_name(cnum),
|
||||
desired_strategy.desc()));
|
||||
}
|
||||
|
||||
// Next up, verify that all other crates are compatible with this panic
|
||||
// strategy. If the dep isn't linked, we ignore it, and if our strategy
|
||||
// is abort then it's compatible with everything. Otherwise all crates'
|
||||
// panic strategy must match our own.
|
||||
for (i, linkage) in list.iter().enumerate() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue
|
||||
}
|
||||
if desired_strategy == PanicStrategy::Abort {
|
||||
continue
|
||||
}
|
||||
let cnum = CrateNum::new(i + 1);
|
||||
let found_strategy = tcx.panic_strategy(cnum);
|
||||
let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
|
||||
if is_compiler_builtins || desired_strategy == found_strategy {
|
||||
continue
|
||||
}
|
||||
|
||||
sess.err(&format!("the crate `{}` is compiled with the \
|
||||
panic strategy `{}` which is \
|
||||
incompatible with this crate's \
|
||||
strategy of `{}`",
|
||||
tcx.crate_name(cnum),
|
||||
found_strategy.desc(),
|
||||
desired_strategy.desc()));
|
||||
}
|
||||
}
|
||||
}
|
@ -875,7 +875,7 @@ impl EncodeContext<'tcx> {
|
||||
EntryKind::AssocConst(container, const_qualif, rendered_const)
|
||||
}
|
||||
ty::AssocKind::Method => {
|
||||
let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
|
||||
let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.node {
|
||||
let param_names = match *m {
|
||||
hir::TraitMethod::Required(ref names) => {
|
||||
self.encode_fn_param_names(names)
|
||||
@ -885,6 +885,7 @@ impl EncodeContext<'tcx> {
|
||||
}
|
||||
};
|
||||
FnData {
|
||||
asyncness: method_sig.header.asyncness,
|
||||
constness: hir::Constness::NotConst,
|
||||
param_names,
|
||||
sig: self.lazy(&tcx.fn_sig(def_id)),
|
||||
@ -982,6 +983,7 @@ impl EncodeContext<'tcx> {
|
||||
ty::AssocKind::Method => {
|
||||
let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
|
||||
FnData {
|
||||
asyncness: sig.header.asyncness,
|
||||
constness: sig.header.constness,
|
||||
param_names: self.encode_fn_param_names_for_body(body),
|
||||
sig: self.lazy(&tcx.fn_sig(def_id)),
|
||||
@ -1128,6 +1130,7 @@ impl EncodeContext<'tcx> {
|
||||
}
|
||||
hir::ItemKind::Fn(_, header, .., body) => {
|
||||
let data = FnData {
|
||||
asyncness: header.asyncness,
|
||||
constness: header.constness,
|
||||
param_names: self.encode_fn_param_names_for_body(body),
|
||||
sig: self.lazy(tcx.fn_sig(def_id)),
|
||||
@ -1649,20 +1652,22 @@ impl EncodeContext<'tcx> {
|
||||
}
|
||||
|
||||
fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
|
||||
match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
|
||||
Some(arr) => {
|
||||
self.lazy(arr.iter().map(|slot| {
|
||||
match *slot {
|
||||
Linkage::NotLinked |
|
||||
Linkage::IncludedFromDylib => None,
|
||||
|
||||
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
|
||||
Linkage::Static => Some(LinkagePreference::RequireStatic),
|
||||
}
|
||||
}))
|
||||
let formats = self.tcx.dependency_formats(LOCAL_CRATE);
|
||||
for (ty, arr) in formats.iter() {
|
||||
if *ty != config::CrateType::Dylib {
|
||||
continue;
|
||||
}
|
||||
None => Lazy::empty(),
|
||||
return self.lazy(arr.iter().map(|slot| {
|
||||
match *slot {
|
||||
Linkage::NotLinked |
|
||||
Linkage::IncludedFromDylib => None,
|
||||
|
||||
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
|
||||
Linkage::Static => Some(LinkagePreference::RequireStatic),
|
||||
}
|
||||
}));
|
||||
}
|
||||
Lazy::empty()
|
||||
}
|
||||
|
||||
fn encode_info_for_foreign_item(&mut self,
|
||||
@ -1675,6 +1680,7 @@ impl EncodeContext<'tcx> {
|
||||
let kind = match nitem.node {
|
||||
hir::ForeignItemKind::Fn(_, ref names, _) => {
|
||||
let data = FnData {
|
||||
asyncness: hir::IsAsync::NotAsync,
|
||||
constness: hir::Constness::NotConst,
|
||||
param_names: self.encode_fn_param_names(names),
|
||||
sig: self.lazy(tcx.fn_sig(def_id)),
|
||||
|
@ -32,6 +32,7 @@ mod schema;
|
||||
mod native_libs;
|
||||
mod link_args;
|
||||
mod foreign_modules;
|
||||
mod dependency_format;
|
||||
|
||||
pub mod creader;
|
||||
pub mod cstore;
|
||||
|
@ -295,6 +295,7 @@ pub struct MacroDef {
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct FnData<'tcx> {
|
||||
pub asyncness: hir::IsAsync,
|
||||
pub constness: hir::Constness,
|
||||
pub param_names: Lazy<[ast::Name]>,
|
||||
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
|
||||
|
@ -1993,6 +1993,69 @@ fn get_owned_iterator() -> IntoIter<i32> {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0524: r##"
|
||||
A variable which requires unique access is being used in more than one closure
|
||||
at the same time.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0524
|
||||
fn set(x: &mut isize) {
|
||||
*x += 4;
|
||||
}
|
||||
|
||||
fn dragoooon(x: &mut isize) {
|
||||
let mut c1 = || set(x);
|
||||
let mut c2 = || set(x); // error!
|
||||
|
||||
c2();
|
||||
c1();
|
||||
}
|
||||
```
|
||||
|
||||
To solve this issue, multiple solutions are available. First, is it required
|
||||
for this variable to be used in more than one closure at a time? If it is the
|
||||
case, use reference counted types such as `Rc` (or `Arc` if it runs
|
||||
concurrently):
|
||||
|
||||
```
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn set(x: &mut isize) {
|
||||
*x += 4;
|
||||
}
|
||||
|
||||
fn dragoooon(x: &mut isize) {
|
||||
let x = Rc::new(RefCell::new(x));
|
||||
let y = Rc::clone(&x);
|
||||
let mut c1 = || { let mut x2 = x.borrow_mut(); set(&mut x2); };
|
||||
let mut c2 = || { let mut x2 = y.borrow_mut(); set(&mut x2); }; // ok!
|
||||
|
||||
c2();
|
||||
c1();
|
||||
}
|
||||
```
|
||||
|
||||
If not, just run closures one at a time:
|
||||
|
||||
```
|
||||
fn set(x: &mut isize) {
|
||||
*x += 4;
|
||||
}
|
||||
|
||||
fn dragoooon(x: &mut isize) {
|
||||
{ // This block isn't necessary since non-lexical lifetimes, it's just to
|
||||
// make it more clear.
|
||||
let mut c1 = || set(&mut *x);
|
||||
c1();
|
||||
} // `c1` has been dropped here so we're free to use `x` again!
|
||||
let mut c2 = || set(&mut *x);
|
||||
c2();
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0595: r##"
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
@ -2393,7 +2456,6 @@ There are some known bugs that trigger this message.
|
||||
// E0385, // {} in an aliasable location
|
||||
E0493, // destructors cannot be evaluated at compile-time
|
||||
E0521, // borrowed data escapes outside of closure
|
||||
E0524, // two closures require unique access to `..` at the same time
|
||||
E0526, // shuffle indices are not constant
|
||||
E0594, // cannot assign to {}
|
||||
// E0598, // lifetime of {} is too short to guarantee its contents can be...
|
||||
|
@ -1253,7 +1253,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
expression.map(|expr| (expr, blk_id)),
|
||||
);
|
||||
}
|
||||
ObligationCauseCode::ReturnType(id) => {
|
||||
ObligationCauseCode::ReturnValue(id) => {
|
||||
db = self.report_return_mismatched_types(
|
||||
cause, expected, found, err, fcx, id, None);
|
||||
}
|
||||
|
@ -664,12 +664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||
let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone());
|
||||
ret_coercion.borrow_mut()
|
||||
.coerce(self,
|
||||
&self.cause(return_expr.span,
|
||||
ObligationCauseCode::ReturnType(return_expr.hir_id)),
|
||||
return_expr,
|
||||
return_expr_ty);
|
||||
ret_coercion.borrow_mut().coerce(
|
||||
self,
|
||||
&self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
|
||||
return_expr,
|
||||
return_expr_ty,
|
||||
);
|
||||
}
|
||||
|
||||
/// Type check assignment expression `expr` of form `lhs = rhs`.
|
||||
|
@ -2698,30 +2698,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
traits::ObligationCause::new(span, self.body_id, code));
|
||||
}
|
||||
|
||||
pub fn require_type_is_sized(&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>)
|
||||
{
|
||||
let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
|
||||
self.require_type_meets(ty, span, code, lang_item);
|
||||
pub fn require_type_is_sized(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
if !ty.references_error() {
|
||||
let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
|
||||
self.require_type_meets(ty, span, code, lang_item);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn require_type_is_sized_deferred(&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>)
|
||||
{
|
||||
self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
|
||||
pub fn require_type_is_sized_deferred(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
if !ty.references_error() {
|
||||
self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_bound(&self,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
cause: traits::ObligationCause<'tcx>)
|
||||
{
|
||||
self.fulfillment_cx.borrow_mut()
|
||||
.register_bound(self, self.param_env, ty, def_id, cause);
|
||||
pub fn register_bound(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
cause: traits::ObligationCause<'tcx>,
|
||||
) {
|
||||
if !ty.references_error() {
|
||||
self.fulfillment_cx.borrow_mut()
|
||||
.register_bound(self, self.param_env, ty, def_id, cause);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
|
||||
@ -2780,22 +2789,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
/// Registers an obligation for checking later, during regionck, that the type `ty` must
|
||||
/// outlive the region `r`.
|
||||
pub fn register_wf_obligation(&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>)
|
||||
{
|
||||
pub fn register_wf_obligation(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
// WF obligations never themselves fail, so no real need to give a detailed cause:
|
||||
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
||||
self.register_predicate(traits::Obligation::new(cause,
|
||||
self.param_env,
|
||||
ty::Predicate::WellFormed(ty)));
|
||||
self.register_predicate(
|
||||
traits::Obligation::new(cause, self.param_env, ty::Predicate::WellFormed(ty)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Registers obligations that all types appearing in `substs` are well-formed.
|
||||
pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr) {
|
||||
for ty in substs.types() {
|
||||
self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
|
||||
if !ty.references_error() {
|
||||
self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2834,12 +2846,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// FIXME(arielb1): use this instead of field.ty everywhere
|
||||
// Only for fields! Returns <none> for methods>
|
||||
// Indifferent to privacy flags
|
||||
pub fn field_ty(&self,
|
||||
span: Span,
|
||||
field: &'tcx ty::FieldDef,
|
||||
substs: SubstsRef<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
pub fn field_ty(
|
||||
&self,
|
||||
span: Span,
|
||||
field: &'tcx ty::FieldDef,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
self.normalize_associated_types_in(span, &field.ty(self.tcx, substs))
|
||||
}
|
||||
|
||||
|
@ -596,7 +596,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
|
||||
}
|
||||
implied_bounds.extend(sig.inputs());
|
||||
|
||||
fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation);
|
||||
fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::ReturnType);
|
||||
|
||||
// FIXME(#25759) return types should not be implied bounds
|
||||
implied_bounds.push(sig.output());
|
||||
|
@ -217,7 +217,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
};
|
||||
|
||||
let asyncness = cx.tcx.asyncness(did);
|
||||
let predicates = cx.tcx.predicates_of(did);
|
||||
let (generics, decl) = clean::enter_impl_trait(cx, || {
|
||||
((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx))
|
||||
@ -230,7 +230,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
|
||||
unsafety: sig.unsafety(),
|
||||
abi: sig.abi(),
|
||||
constness,
|
||||
asyncness: hir::IsAsync::NotAsync,
|
||||
asyncness,
|
||||
},
|
||||
all_types,
|
||||
ret_types,
|
||||
|
@ -2403,6 +2403,7 @@ impl Clean<Item> for ty::AssocItem {
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
};
|
||||
let asyncness = cx.tcx.asyncness(self.def_id);
|
||||
let defaultness = match self.container {
|
||||
ty::ImplContainer(_) => Some(self.defaultness),
|
||||
ty::TraitContainer(_) => None,
|
||||
@ -2414,7 +2415,7 @@ impl Clean<Item> for ty::AssocItem {
|
||||
unsafety: sig.unsafety(),
|
||||
abi: sig.abi(),
|
||||
constness,
|
||||
asyncness: hir::IsAsync::NotAsync,
|
||||
asyncness,
|
||||
},
|
||||
defaultness,
|
||||
all_types,
|
||||
|
@ -236,8 +236,8 @@ impl<T: 'static> LocalKey<T> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with<F, R>(&'static self, f: F) -> R
|
||||
where F: FnOnce(&T) -> R {
|
||||
self.try_with(f).expect("cannot access a TLS value during or \
|
||||
after it is destroyed")
|
||||
self.try_with(f).expect("cannot access a Thread Local Storage value \
|
||||
during or after destruction")
|
||||
}
|
||||
|
||||
/// Acquires a reference to the value in this TLS key.
|
||||
|
@ -112,6 +112,13 @@ impl Emitter for JsonEmitter {
|
||||
panic!("failed to print notification: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn should_show_explain(&self) -> bool {
|
||||
match self.json_rendered {
|
||||
HumanReadableErrorType::Short(_) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The following data types are provided just for serialisation.
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags:-Zshare-generics=yes
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type="rlib"]
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// ignore-tidy-linelength
|
||||
// no-prefer-dynamic
|
||||
// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe
|
||||
|
||||
#![crate_type="rlib"]
|
||||
|
@ -5,6 +5,7 @@
|
||||
// aux-build:panic-runtime-lang-items.rs
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate panic_runtime_unwind;
|
||||
extern crate panic_runtime_unwind2;
|
||||
|
39
src/test/run-make-fulldeps/issue-64319/Makefile
Normal file
39
src/test/run-make-fulldeps/issue-64319/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
-include ../tools.mk
|
||||
|
||||
# Different optimization levels imply different values for `-Zshare-generics`,
|
||||
# so try out a whole bunch of combinations to make sure everything is compatible
|
||||
all:
|
||||
# First up, try some defaults
|
||||
$(RUSTC) --crate-type rlib foo.rs
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
|
||||
|
||||
# Next try mixing up some things explicitly
|
||||
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
|
||||
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
|
||||
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
|
||||
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
|
||||
|
||||
# Now combine a whole bunch of options together
|
||||
$(RUSTC) --crate-type rlib foo.rs
|
||||
$(RUSTC) --crate-type dylib bar.rs
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no
|
||||
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes
|
5
src/test/run-make-fulldeps/issue-64319/bar.rs
Normal file
5
src/test/run-make-fulldeps/issue-64319/bar.rs
Normal file
@ -0,0 +1,5 @@
|
||||
extern crate foo;
|
||||
|
||||
pub fn bar() {
|
||||
foo::foo();
|
||||
}
|
9
src/test/run-make-fulldeps/issue-64319/foo.rs
Normal file
9
src/test/run-make-fulldeps/issue-64319/foo.rs
Normal file
@ -0,0 +1,9 @@
|
||||
pub fn foo() {
|
||||
bar::<usize>();
|
||||
}
|
||||
|
||||
pub fn bar<T>() {
|
||||
baz();
|
||||
}
|
||||
|
||||
fn baz() {}
|
@ -79,12 +79,12 @@ all:
|
||||
# Check that a Rust dylib exports its monomorphic functions, including generics this time
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ]
|
||||
|
||||
# Check that a Rust dylib exports the monomorphic functions from its dependencies
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ]
|
||||
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ]
|
||||
|
||||
# Check that an executable does not export any dynamic symbols
|
||||
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ]
|
||||
|
@ -1,3 +1,5 @@
|
||||
// edition:2018
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
pub fn func<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
|
||||
@ -11,8 +13,16 @@ pub fn func3(_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone) {}
|
||||
|
||||
pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
|
||||
|
||||
pub async fn async_fn() {}
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a) {}
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
|
||||
impl Bar {
|
||||
pub async fn async_foo(&self) {}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// aux-build:impl_trait_aux.rs
|
||||
// edition:2018
|
||||
|
||||
extern crate impl_trait_aux;
|
||||
|
||||
@ -20,13 +21,20 @@ pub use impl_trait_aux::func2;
|
||||
// @!has - '//pre[@class="rust fn"]' 'where'
|
||||
pub use impl_trait_aux::func3;
|
||||
|
||||
|
||||
// @has impl_trait/fn.func4.html
|
||||
// @has - '//pre[@class="rust fn"]' "func4<T>("
|
||||
// @has - '//pre[@class="rust fn"]' "T: Iterator<Item = impl Clone>,"
|
||||
pub use impl_trait_aux::func4;
|
||||
|
||||
// @has impl_trait/fn.async_fn.html
|
||||
// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()"
|
||||
pub use impl_trait_aux::async_fn;
|
||||
|
||||
// @has impl_trait/struct.Foo.html
|
||||
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
|
||||
// @!has - '//code[@id="method.v"]' 'where'
|
||||
pub use impl_trait_aux::Foo;
|
||||
|
||||
// @has impl_trait/struct.Bar.html
|
||||
// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo("
|
||||
pub use impl_trait_aux::Bar;
|
||||
|
@ -1,10 +1,10 @@
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Foo: Iterator<Item = i32> {}
|
||||
trait Bar: Foo<Item = u32> {} //~ ERROR type annotations required
|
||||
trait Bar: Foo<Item = u32> {} //~ ERROR type annotations needed
|
||||
|
||||
trait I32Iterator = Iterator<Item = i32>;
|
||||
trait U32Iterator = I32Iterator<Item = u32>;
|
||||
trait U32Iterator = I32Iterator<Item = u32>; //~ ERROR type annotations needed
|
||||
|
||||
fn main() {
|
||||
let _: &dyn I32Iterator<Item = u32>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
|
||||
error[E0284]: type annotations needed: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
|
||||
--> $DIR/associated-types-overridden-binding.rs:4:1
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32> {}
|
||||
@ -6,6 +6,13 @@ LL | trait Foo: Iterator<Item = i32> {}
|
||||
LL | trait Bar: Foo<Item = u32> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/associated-types-overridden-binding.rs:7:1
|
||||
|
|
||||
LL | trait U32Iterator = I32Iterator<Item = u32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0284.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
@ -12,5 +12,5 @@ impl Foo for isize {
|
||||
|
||||
pub fn main() {
|
||||
let x: isize = Foo::bar();
|
||||
//~^ ERROR type annotations required
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<_ as Foo>::A == _`
|
||||
error[E0284]: type annotations needed: cannot resolve `<_ as Foo>::A == _`
|
||||
--> $DIR/associated-types-unconstrained.rs:14:20
|
||||
|
|
||||
LL | let x: isize = Foo::bar();
|
||||
|
@ -1,10 +1,6 @@
|
||||
// Tests that two closures cannot simultaneously have mutable
|
||||
// and immutable access to the variable. Issue #6801.
|
||||
|
||||
fn get(x: &isize) -> isize {
|
||||
*x
|
||||
}
|
||||
|
||||
fn set(x: &mut isize) {
|
||||
*x = 4;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:13:25
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:9:25
|
||||
|
|
||||
LL | let mut c1 = || set(&mut *x);
|
||||
| ^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:15:25
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:11:25
|
||||
|
|
||||
LL | let mut c2 = || set(&mut *x);
|
||||
| ^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0524]: two closures require unique access to `x` at the same time
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:15:18
|
||||
--> $DIR/borrowck-closures-mut-of-imm.rs:11:18
|
||||
|
|
||||
LL | let mut c1 = || set(&mut *x);
|
||||
| -- - first borrow occurs due to use of `x` in closure
|
||||
@ -28,4 +28,5 @@ LL | c2(); c1();
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0596`.
|
||||
Some errors have detailed explanations: E0524, E0596.
|
||||
For more information about an error, try `rustc --explain E0524`.
|
||||
|
@ -15,3 +15,4 @@ LL | c2(); c1();
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0524`.
|
||||
|
@ -50,4 +50,5 @@ LL | let c1 = |y: &'static mut isize| x = y;
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0500`.
|
||||
Some errors have detailed explanations: E0500, E0524.
|
||||
For more information about an error, try `rustc --explain E0500`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `_: Generator`
|
||||
error[E0283]: type annotations needed: cannot resolve `_: Generator`
|
||||
--> $DIR/E0283.rs:18:21
|
||||
|
|
||||
LL | fn create() -> u32;
|
||||
|
@ -8,7 +8,7 @@ fn foo<T>(x: T) {
|
||||
W: Fn()>
|
||||
(y: T) { //~ ERROR E0401
|
||||
}
|
||||
bfnr(x);
|
||||
bfnr(x); //~ ERROR type annotations needed
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,6 +32,13 @@ LL | fn helper(sel: &Self) -> u8 {
|
||||
| use of generic parameter from outer function
|
||||
| use a type here instead
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/E0401.rs:11:5
|
||||
|
|
||||
LL | bfnr(x);
|
||||
| ^^^^ cannot infer type for `U`
|
||||
|
||||
For more information about this error, try `rustc --explain E0401`.
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0401.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
let a;
|
||||
let a; //~ ERROR type annotations needed
|
||||
asm!("nop" : "r"(a));
|
||||
//~^ ERROR E0661
|
||||
}
|
||||
|
@ -4,5 +4,12 @@ error[E0661]: output operand constraint lacks '=' or '+'
|
||||
LL | asm!("nop" : "r"(a));
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/E0661.rs:6:9
|
||||
|
|
||||
LL | let a;
|
||||
| ^ consider giving `a` a type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
@ -11,8 +11,9 @@ fn in_return() -> impl Debug { panic!() }
|
||||
// Allowed
|
||||
fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
|
||||
|
||||
// Allowed
|
||||
// Disallowed
|
||||
fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
|
||||
//~^ ERROR type annotations needed
|
||||
|
||||
// Disallowed
|
||||
fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
|
||||
@ -58,7 +59,8 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
|
||||
// Disallowed
|
||||
fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
|
||||
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
|
||||
//~^^ ERROR nested `impl Trait` is not allowed
|
||||
//~| ERROR nested `impl Trait` is not allowed
|
||||
//~| ERROR type annotations needed
|
||||
|
||||
// Disallowed
|
||||
fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0666]: nested `impl Trait` is not allowed
|
||||
--> $DIR/where-allowed.rs:50:51
|
||||
--> $DIR/where-allowed.rs:51:51
|
||||
|
|
||||
LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
|
||||
| --------^^^^^^^^^^-
|
||||
@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
|
||||
| outer `impl Trait`
|
||||
|
||||
error[E0666]: nested `impl Trait` is not allowed
|
||||
--> $DIR/where-allowed.rs:59:57
|
||||
--> $DIR/where-allowed.rs:60:57
|
||||
|
|
||||
LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
|
||||
| --------^^^^^^^^^^-
|
||||
@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic
|
||||
| outer `impl Trait`
|
||||
|
||||
error[E0658]: `impl Trait` in type aliases is unstable
|
||||
--> $DIR/where-allowed.rs:122:5
|
||||
--> $DIR/where-allowed.rs:124:5
|
||||
|
|
||||
LL | type Out = impl Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -26,7 +26,7 @@ LL | type Out = impl Debug;
|
||||
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `impl Trait` in type aliases is unstable
|
||||
--> $DIR/where-allowed.rs:158:1
|
||||
--> $DIR/where-allowed.rs:160:1
|
||||
|
|
||||
LL | type InTypeAlias<R> = impl Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -35,205 +35,205 @@ LL | type InTypeAlias<R> = impl Debug;
|
||||
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:18:40
|
||||
--> $DIR/where-allowed.rs:19:40
|
||||
|
|
||||
LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:22:42
|
||||
--> $DIR/where-allowed.rs:23:42
|
||||
|
|
||||
LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:26:38
|
||||
--> $DIR/where-allowed.rs:27:38
|
||||
|
|
||||
LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:30:40
|
||||
--> $DIR/where-allowed.rs:31:40
|
||||
|
|
||||
LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:34:49
|
||||
--> $DIR/where-allowed.rs:35:49
|
||||
|
|
||||
LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:38:51
|
||||
--> $DIR/where-allowed.rs:39:51
|
||||
|
|
||||
LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:42:55
|
||||
--> $DIR/where-allowed.rs:43:55
|
||||
|
|
||||
LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:46:57
|
||||
--> $DIR/where-allowed.rs:47:57
|
||||
|
|
||||
LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:50:51
|
||||
--> $DIR/where-allowed.rs:51:51
|
||||
|
|
||||
LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:55:53
|
||||
--> $DIR/where-allowed.rs:56:53
|
||||
|
|
||||
LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:59:57
|
||||
--> $DIR/where-allowed.rs:60:57
|
||||
|
|
||||
LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:64:59
|
||||
--> $DIR/where-allowed.rs:66:59
|
||||
|
|
||||
LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:68:38
|
||||
--> $DIR/where-allowed.rs:70:38
|
||||
|
|
||||
LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:72:40
|
||||
--> $DIR/where-allowed.rs:74:40
|
||||
|
|
||||
LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:85:32
|
||||
--> $DIR/where-allowed.rs:87:32
|
||||
|
|
||||
LL | struct InBraceStructField { x: impl Debug }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:89:41
|
||||
--> $DIR/where-allowed.rs:91:41
|
||||
|
|
||||
LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:93:27
|
||||
--> $DIR/where-allowed.rs:95:27
|
||||
|
|
||||
LL | struct InTupleStructField(impl Debug);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:98:25
|
||||
--> $DIR/where-allowed.rs:100:25
|
||||
|
|
||||
LL | InBraceVariant { x: impl Debug },
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:100:20
|
||||
--> $DIR/where-allowed.rs:102:20
|
||||
|
|
||||
LL | InTupleVariant(impl Debug),
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:111:23
|
||||
--> $DIR/where-allowed.rs:113:23
|
||||
|
|
||||
LL | fn in_return() -> impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:129:34
|
||||
--> $DIR/where-allowed.rs:131:34
|
||||
|
|
||||
LL | fn in_trait_impl_return() -> impl Debug { () }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:142:33
|
||||
--> $DIR/where-allowed.rs:144:33
|
||||
|
|
||||
LL | fn in_foreign_parameters(_: impl Debug);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:145:31
|
||||
--> $DIR/where-allowed.rs:147:31
|
||||
|
|
||||
LL | fn in_foreign_return() -> impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:162:39
|
||||
--> $DIR/where-allowed.rs:164:39
|
||||
|
|
||||
LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:166:16
|
||||
--> $DIR/where-allowed.rs:168:16
|
||||
|
|
||||
LL | impl PartialEq<impl Debug> for () {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:171:24
|
||||
--> $DIR/where-allowed.rs:173:24
|
||||
|
|
||||
LL | impl PartialEq<()> for impl Debug {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:176:6
|
||||
--> $DIR/where-allowed.rs:178:6
|
||||
|
|
||||
LL | impl impl Debug {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:182:24
|
||||
--> $DIR/where-allowed.rs:184:24
|
||||
|
|
||||
LL | impl InInherentImplAdt<impl Debug> {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:188:11
|
||||
--> $DIR/where-allowed.rs:190:11
|
||||
|
|
||||
LL | where impl Debug: Debug
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:195:15
|
||||
--> $DIR/where-allowed.rs:197:15
|
||||
|
|
||||
LL | where Vec<impl Debug>: Debug
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:202:24
|
||||
--> $DIR/where-allowed.rs:204:24
|
||||
|
|
||||
LL | where T: PartialEq<impl Debug>
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:209:17
|
||||
--> $DIR/where-allowed.rs:211:17
|
||||
|
|
||||
LL | where T: Fn(impl Debug)
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:216:22
|
||||
--> $DIR/where-allowed.rs:218:22
|
||||
|
|
||||
LL | where T: Fn() -> impl Debug
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:222:29
|
||||
--> $DIR/where-allowed.rs:224:29
|
||||
|
|
||||
LL | let _in_local_variable: impl Fn() = || {};
|
||||
| ^^^^^^^^^
|
||||
@ -241,24 +241,36 @@ LL | let _in_local_variable: impl Fn() = || {};
|
||||
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/where-allowed.rs:224:46
|
||||
--> $DIR/where-allowed.rs:226:46
|
||||
|
|
||||
LL | let _in_return_in_local_variable = || -> impl Fn() { || {} };
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/where-allowed.rs:15:30
|
||||
|
|
||||
LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
|
||||
| ^^^^^^^^^^ cannot infer type
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/where-allowed.rs:60:49
|
||||
|
|
||||
LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
|
||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/where-allowed.rs:158:1
|
||||
--> $DIR/where-allowed.rs:160:1
|
||||
|
|
||||
LL | type InTypeAlias<R> = impl Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/where-allowed.rs:122:5
|
||||
--> $DIR/where-allowed.rs:124:5
|
||||
|
|
||||
LL | type Out = impl Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 41 previous errors
|
||||
error: aborting due to 43 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0562, E0658.
|
||||
For more information about an error, try `rustc --explain E0562`.
|
||||
Some errors have detailed explanations: E0282, E0562, E0658.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
@ -24,7 +24,7 @@ trait StreamHash<H: StreamHasher>: Hash<H> {
|
||||
impl<H: StreamHasher> Hash<H> for u8 {
|
||||
fn hash2(&self, hasher: &H) -> u64 {
|
||||
let mut stream = hasher.stream();
|
||||
self.input_stream(&mut stream); //~ ERROR type annotations required
|
||||
self.input_stream(&mut stream); //~ ERROR type annotations needed
|
||||
Stream::result(&stream)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
|
||||
error[E0284]: type annotations needed: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
|
||||
--> $DIR/issue-12028.rs:27:14
|
||||
|
|
||||
LL | self.input_stream(&mut stream);
|
||||
|
@ -7,7 +7,7 @@ trait Foo {
|
||||
fn foo(self);
|
||||
}
|
||||
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations needed
|
||||
where &'a T : Foo,
|
||||
&'b T : Foo
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
|
||||
error[E0283]: type annotations needed: cannot resolve `&'a T: Foo`
|
||||
--> $DIR/issue-21974.rs:10:1
|
||||
|
|
||||
LL | trait Foo {
|
||||
|
@ -2,6 +2,6 @@ trait Trait1<'l0, T0> {}
|
||||
trait Trait0<'l0> {}
|
||||
|
||||
impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
|
||||
//~^ ERROR type annotations required: cannot resolve `T0: Trait0<'l0>`
|
||||
//~^ ERROR type annotations needed: cannot resolve `T0: Trait0<'l0>`
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>`
|
||||
error[E0283]: type annotations needed: cannot resolve `T0: Trait0<'l0>`
|
||||
--> $DIR/issue-24424.rs:4:1
|
||||
|
|
||||
LL | trait Trait0<'l0> {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `S5<_>: Foo`
|
||||
error[E0283]: type annotations needed: cannot resolve `S5<_>: Foo`
|
||||
--> $DIR/issue-29147.rs:21:13
|
||||
|
|
||||
LL | trait Foo { fn xxx(&self); }
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![feature(const_fn)]
|
||||
|
||||
const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
|
||||
//~^ ERROR constant contains unimplemented expression type
|
||||
//~^ ERROR type annotations needed
|
||||
|
||||
trait Tt {
|
||||
const fn const_val<T: Sized>() -> usize {
|
||||
@ -11,6 +11,8 @@ trait Tt {
|
||||
}
|
||||
|
||||
fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| ERROR evaluation of constant value failed
|
||||
z
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,28 @@ error[E0379]: trait fns cannot be declared const
|
||||
LL | const fn const_val<T: Sized>() -> usize {
|
||||
| ^^^^^ trait fns cannot be const
|
||||
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
error[E0283]: type annotations needed: cannot resolve `_: Tt`
|
||||
--> $DIR/issue-54954.rs:3:24
|
||||
|
|
||||
LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | const fn const_val<T: Sized>() -> usize {
|
||||
| --------- - required by this bound in `Tt::const_val`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/issue-54954.rs:13:15
|
||||
|
|
||||
LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
|
||||
| ^^^^^^^ referenced constant has errors
|
||||
|
||||
Some errors have detailed explanations: E0019, E0379.
|
||||
For more information about an error, try `rustc --explain E0019`.
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/issue-54954.rs:13:34
|
||||
|
|
||||
LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
|
||||
| ^^^^^^^ referenced constant has errors
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0080, E0283, E0379.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
|
@ -15,5 +15,3 @@ started: https://doc.rust-lang.org/book/
|
||||
"}
|
||||
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
|
||||
"}
|
||||
{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
|
||||
"}
|
||||
|
@ -15,7 +15,7 @@ impl Foo for Vec<isize> {
|
||||
}
|
||||
|
||||
// This is very hokey: we have heuristics to suppress messages about
|
||||
// type annotations required. But placing these two bits of code into
|
||||
// type annotations needed. But placing these two bits of code into
|
||||
// distinct functions, in this order, causes us to print out both
|
||||
// errors I'd like to see.
|
||||
|
||||
|
@ -27,5 +27,5 @@ LL | v.push(|| *x = String::new());
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0499.
|
||||
Some errors have detailed explanations: E0382, E0499, E0524.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
||||
|
@ -7,9 +7,8 @@
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate wants_panic_runtime_unwind;
|
||||
extern crate wants_panic_runtime_abort;
|
||||
extern crate panic_runtime_lang_items;
|
||||
|
||||
fn main() {}
|
||||
|
@ -4,8 +4,7 @@
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate panic_runtime_abort;
|
||||
extern crate panic_runtime_lang_items;
|
||||
|
||||
fn main() {}
|
||||
|
@ -5,8 +5,7 @@
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate wants_panic_runtime_abort;
|
||||
extern crate panic_runtime_lang_items;
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
let r#self;
|
||||
let r#self: ();
|
||||
//~^ ERROR `self` cannot be a raw identifier
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
error: `self` cannot be a raw identifier
|
||||
--> $DIR/raw-literal-self.rs:2:9
|
||||
|
|
||||
LL | let r#self;
|
||||
LL | let r#self: ();
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
let r#_;
|
||||
let r#_: ();
|
||||
//~^ ERROR `_` cannot be a raw identifier
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
error: `_` cannot be a raw identifier
|
||||
--> $DIR/raw-literal-underscore.rs:2:9
|
||||
|
|
||||
LL | let r#_;
|
||||
LL | let r#_: ();
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -31,6 +31,7 @@ fn rest_patterns() {
|
||||
|
||||
// Ident patterns:
|
||||
let x @ ..; //~ ERROR `..` patterns are not allowed here
|
||||
//~^ ERROR type annotations needed
|
||||
let ref x @ ..; //~ ERROR `..` patterns are not allowed here
|
||||
let ref mut x @ ..; //~ ERROR `..` patterns are not allowed here
|
||||
|
||||
|
@ -58,7 +58,7 @@ LL | let x @ ..;
|
||||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error: `..` patterns are not allowed here
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:34:17
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:35:17
|
||||
|
|
||||
LL | let ref x @ ..;
|
||||
| ^^
|
||||
@ -66,7 +66,7 @@ LL | let ref x @ ..;
|
||||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error: `..` patterns are not allowed here
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:35:21
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:36:21
|
||||
|
|
||||
LL | let ref mut x @ ..;
|
||||
| ^^
|
||||
@ -74,7 +74,7 @@ LL | let ref mut x @ ..;
|
||||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error: `..` can only be used once per tuple pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:42:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:43:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -82,7 +82,7 @@ LL | ..,
|
||||
| ^^ can only be used once per tuple pattern
|
||||
|
||||
error: `..` can only be used once per tuple pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:43:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:44:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -91,7 +91,7 @@ LL | ..
|
||||
| ^^ can only be used once per tuple pattern
|
||||
|
||||
error: `..` can only be used once per tuple pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:48:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:49:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -99,25 +99,25 @@ LL | x,
|
||||
LL | ..
|
||||
| ^^ can only be used once per tuple pattern
|
||||
|
||||
error: `..` can only be used once per tuple struct pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:58:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
LL | ..,
|
||||
| ^^ can only be used once per tuple struct pattern
|
||||
|
||||
error: `..` can only be used once per tuple struct pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:59:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
LL | ..,
|
||||
| ^^ can only be used once per tuple struct pattern
|
||||
|
||||
error: `..` can only be used once per tuple struct pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:60:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
LL | ..,
|
||||
LL | ..
|
||||
| ^^ can only be used once per tuple struct pattern
|
||||
|
||||
error: `..` can only be used once per tuple struct pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:64:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:65:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -126,7 +126,7 @@ LL | ..
|
||||
| ^^ can only be used once per tuple struct pattern
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:72:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:73:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -134,7 +134,7 @@ LL | ..,
|
||||
| ^^ can only be used once per slice pattern
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:73:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:74:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -143,7 +143,7 @@ LL | ..
|
||||
| ^^ can only be used once per slice pattern
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:77:17
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:78:17
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -151,7 +151,7 @@ LL | ref x @ ..,
|
||||
| ^^ can only be used once per slice pattern
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:78:21
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:79:21
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -160,7 +160,7 @@ LL | ref mut y @ ..,
|
||||
| ^^ can only be used once per slice pattern
|
||||
|
||||
error: `..` patterns are not allowed here
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:79:18
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:80:18
|
||||
|
|
||||
LL | (ref z @ ..),
|
||||
| ^^
|
||||
@ -168,7 +168,7 @@ LL | (ref z @ ..),
|
||||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error: `..` can only be used once per slice pattern
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:80:9
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:81:9
|
||||
|
|
||||
LL | ..,
|
||||
| -- previously used here
|
||||
@ -184,5 +184,12 @@ LL | fn foo(..: u8) {}
|
||||
|
|
||||
= note: only allowed in tuple, tuple struct, and slice patterns
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/rest-pat-semantic-disallowed.rs:33:9
|
||||
|
|
||||
LL | let x @ ..;
|
||||
| ^^^^^^ consider giving this pattern a type
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
@ -9,7 +9,7 @@ fn f(x: &i32) -> Result<i32, ()> {
|
||||
|
||||
fn g() -> Result<Vec<i32>, ()> {
|
||||
let l = [1, 2, 3, 4];
|
||||
l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve
|
||||
l.iter().map(f).collect()? //~ ERROR type annotations needed: cannot resolve
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0284]: type annotations required: cannot resolve `<_ as std::ops::Try>::Ok == _`
|
||||
error[E0284]: type annotations needed: cannot resolve `<_ as std::ops::Try>::Ok == _`
|
||||
--> $DIR/question-mark-type-infer.rs:12:5
|
||||
|
|
||||
LL | l.iter().map(f).collect()?
|
||||
|
@ -20,7 +20,7 @@ type Alias = extern "C" fn(#[id] u8, #[id] ...);
|
||||
|
||||
fn free(#[id] arg1: u8) {
|
||||
//~^ ERROR expected an inert attribute, found an attribute macro
|
||||
let lam = |#[id] W(x), #[id] y| ();
|
||||
let lam = |#[id] W(x), #[id] y: usize| ();
|
||||
//~^ ERROR expected an inert attribute, found an attribute macro
|
||||
//~| ERROR expected an inert attribute, found an attribute macro
|
||||
}
|
||||
|
@ -37,13 +37,13 @@ LL | fn free(#[id] arg1: u8) {
|
||||
error: expected an inert attribute, found an attribute macro
|
||||
--> $DIR/proc-macro-cannot-be-used.rs:23:16
|
||||
|
|
||||
LL | let lam = |#[id] W(x), #[id] y| ();
|
||||
LL | let lam = |#[id] W(x), #[id] y: usize| ();
|
||||
| ^^^^^
|
||||
|
||||
error: expected an inert attribute, found an attribute macro
|
||||
--> $DIR/proc-macro-cannot-be-used.rs:23:28
|
||||
|
|
||||
LL | let lam = |#[id] W(x), #[id] y| ();
|
||||
LL | let lam = |#[id] W(x), #[id] y: usize| ();
|
||||
| ^^^^^
|
||||
|
||||
error: expected an inert attribute, found an attribute macro
|
||||
|
@ -22,7 +22,7 @@ mod base {
|
||||
|
||||
pub fn foo() {
|
||||
let _f: base::Foo = base::HasNew::new();
|
||||
//~^ ERROR type annotations required
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `_: base::HasNew<base::Foo>`
|
||||
error[E0283]: type annotations needed: cannot resolve `_: base::HasNew<base::Foo>`
|
||||
--> $DIR/trait-static-method-generic-inference.rs:24:25
|
||||
|
|
||||
LL | fn new() -> T;
|
||||
|
@ -4,5 +4,5 @@ fn foo<T: Into<String>>(x: i32) {}
|
||||
|
||||
fn main() {
|
||||
foo(42);
|
||||
//~^ ERROR type annotations required
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<std::string::String>`
|
||||
error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into<std::string::String>`
|
||||
--> $DIR/type-annotation-needed.rs:6:5
|
||||
|
|
||||
LL | fn foo<T: Into<String>>(x: i32) {}
|
||||
|
@ -2,7 +2,7 @@ trait Foo: Sized {
|
||||
fn foo(self);
|
||||
}
|
||||
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required
|
||||
fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations needed
|
||||
where &'a T : Foo,
|
||||
&'b T : Foo
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
|
||||
error[E0283]: type annotations needed: cannot resolve `&'a T: Foo`
|
||||
--> $DIR/issue-40294.rs:5:1
|
||||
|
|
||||
LL | trait Foo: Sized {
|
||||
|
@ -20,7 +20,7 @@ fn method() {
|
||||
}
|
||||
|
||||
fn closure() {
|
||||
let _ = |a, b: _| -> _ { 0 }; // OK
|
||||
let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -22,7 +22,13 @@ error[E0425]: cannot find value `nonexistent` in this scope
|
||||
LL | nonexistent.nonexistent::<u8>();
|
||||
| ^^^^^^^^^^^ not found in this scope
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/type-path-err-node-types.rs:23:14
|
||||
|
|
||||
LL | let _ = |a, b: _| -> _ { 0 };
|
||||
| ^ consider giving this closure parameter a type
|
||||
|
||||
Some errors have detailed explanations: E0412, E0425, E0433.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0412, E0425, E0433.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit b6c6f685b38d523580813b0031677c2298f458ea
|
||||
Subproject commit aa6b7e01abce30091cc594cb23a15c46cead6e24
|
Loading…
Reference in New Issue
Block a user