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:
bors 2019-09-25 01:49:46 +00:00
commit b7820b2893
93 changed files with 1044 additions and 666 deletions

View File

@ -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",

View File

@ -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()))

View File

@ -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,

View File

@ -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()));
}
}
}

View File

@ -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 {

View File

@ -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,

View File

@ -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(),

View File

@ -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");

View File

@ -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),

View File

@ -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

View File

@ -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),

View File

@ -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,
}
})
}

View File

@ -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,

View File

@ -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 {

View File

@ -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());
}
}
}

View File

@ -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();

View File

@ -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
}

View File

@ -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();

View File

@ -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>,
}

View File

@ -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)
});

View File

@ -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
};
}

View File

@ -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 |

View 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()));
}
}
}

View File

@ -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)),

View File

@ -32,6 +32,7 @@ mod schema;
mod native_libs;
mod link_args;
mod foreign_modules;
mod dependency_format;
pub mod creader;
pub mod cstore;

View File

@ -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>>,

View File

@ -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...

View File

@ -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);
}

View File

@ -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`.

View File

@ -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))
}

View File

@ -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());

View File

@ -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,

View File

@ -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,

View File

@ -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.

View File

@ -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.

View File

@ -1,4 +1,5 @@
// compile-flags:-Zshare-generics=yes
// no-prefer-dynamic
#![crate_type="rlib"]

View File

@ -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"]

View File

@ -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;

View 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

View File

@ -0,0 +1,5 @@
extern crate foo;
pub fn bar() {
foo::foo();
}

View File

@ -0,0 +1,9 @@
pub fn foo() {
bar::<usize>();
}
pub fn bar<T>() {
baz();
}
fn baz() {}

View File

@ -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" ]

View File

@ -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) {}
}

View File

@ -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;

View File

@ -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>;

View File

@ -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`.

View File

@ -12,5 +12,5 @@ impl Foo for isize {
pub fn main() {
let x: isize = Foo::bar();
//~^ ERROR type annotations required
//~^ ERROR type annotations needed
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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`.

View File

@ -15,3 +15,4 @@ LL | c2(); c1();
error: aborting due to previous error
For more information about this error, try `rustc --explain E0524`.

View File

@ -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`.

View File

@ -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;

View File

@ -8,7 +8,7 @@ fn foo<T>(x: T) {
W: Fn()>
(y: T) { //~ ERROR E0401
}
bfnr(x);
bfnr(x); //~ ERROR type annotations needed
}

View File

@ -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`.

View File

@ -3,7 +3,7 @@
#![feature(asm)]
fn main() {
let a;
let a; //~ ERROR type annotations needed
asm!("nop" : "r"(a));
//~^ ERROR E0661
}

View File

@ -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`.

View File

@ -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!() }

View File

@ -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`.

View File

@ -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)
}
}

View File

@ -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);

View File

@ -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
{

View File

@ -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 {

View File

@ -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() {}

View File

@ -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> {}

View File

@ -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); }

View File

@ -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
}

View File

@ -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`.

View File

@ -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`.
"}

View File

@ -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.

View File

@ -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`.

View File

@ -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() {}

View File

@ -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() {}

View File

@ -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() {}

View File

@ -1,4 +1,4 @@
fn main() {
let r#self;
let r#self: ();
//~^ ERROR `self` cannot be a raw identifier
}

View File

@ -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

View File

@ -1,4 +1,4 @@
fn main() {
let r#_;
let r#_: ();
//~^ ERROR `_` cannot be a raw identifier
}

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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() {

View File

@ -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()?

View File

@ -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
}

View File

@ -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

View File

@ -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() { }

View File

@ -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;

View File

@ -4,5 +4,5 @@ fn foo<T: Into<String>>(x: i32) {}
fn main() {
foo(42);
//~^ ERROR type annotations required
//~^ ERROR type annotations needed
}

View File

@ -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) {}

View File

@ -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
{

View File

@ -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 {

View File

@ -20,7 +20,7 @@ fn method() {
}
fn closure() {
let _ = |a, b: _| -> _ { 0 }; // OK
let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed
}
fn main() {}

View File

@ -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