Auto merge of #70305 - Centril:rollup-zi13fz4, r=Centril

Rollup of 8 pull requests

Successful merges:

 - #69080 (rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.)
 - #69940 (librustc_codegen_llvm: Replace deprecated API usage)
 - #69942 (Increase verbosity when suggesting subtle code changes)
 - #69968 (rustc: keep upvars tupled in {Closure,Generator}Substs.)
 - #70123 (Ensure LLVM is in the link path for rustc tools)
 - #70159 (Update the bundled wasi-libc with libstd)
 - #70233 (resolve: Do not resolve visibilities on proc macro definitions twice)
 - #70286 (Miri error type: remove UbExperimental variant)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-03-23 09:30:00 +00:00
commit 5aa8f199c3
218 changed files with 1334 additions and 1103 deletions

View file

@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{Duration, Instant};
use build_helper::t;
use build_helper::{output, t};
use crate::cache::{Cache, Interned, INTERNER};
use crate::check;
@ -23,7 +23,7 @@ use crate::install;
use crate::native;
use crate::test;
use crate::tool;
use crate::util::{self, add_lib_path, exe, libdir};
use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir};
use crate::{Build, DocTests, GitRepo, Mode};
pub use crate::Compiler;
@ -660,7 +660,7 @@ impl<'a> Builder<'a> {
return;
}
add_lib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command);
add_dylib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command);
}
/// Gets a path to the compiler specified.
@ -698,6 +698,20 @@ impl<'a> Builder<'a> {
cmd
}
/// Return the path to `llvm-config` for the target, if it exists.
///
/// Note that this returns `None` if LLVM is disabled, or if we're in a
/// check build or dry-run, where there's no need to build all of LLVM.
fn llvm_config(&self, target: Interned<String>) -> Option<PathBuf> {
if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run {
let llvm_config = self.ensure(native::Llvm { target });
if llvm_config.is_file() {
return Some(llvm_config);
}
}
None
}
/// Prepares an invocation of `cargo` to be run.
///
/// This will create a `Command` that represents a pending execution of
@ -1034,6 +1048,17 @@ impl<'a> Builder<'a> {
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler));
}
// Tools that use compiler libraries may inherit the `-lLLVM` link
// requirement, but the `-L` library path is not propagated across
// separate Cargo projects. We can add LLVM's library path to the
// platform-specific environment variable as a workaround.
if mode == Mode::ToolRustc {
if let Some(llvm_config) = self.llvm_config(target) {
let llvm_libdir = output(Command::new(&llvm_config).arg("--libdir"));
add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cargo);
}
}
if self.config.incremental {
cargo.env("CARGO_INCREMENTAL", "1");
} else {

View file

@ -451,44 +451,6 @@ impl Step for Rustc {
false,
);
// We used to build librustc_codegen_llvm as a separate step,
// which produced a dylib that the compiler would dlopen() at runtime.
// This meant that we only needed to make sure that libLLVM.so was
// installed by the time we went to run a tool using it - since
// librustc_codegen_llvm was effectively a standalone artifact,
// other crates were completely oblivious to its dependency
// on `libLLVM.so` during build time.
//
// However, librustc_codegen_llvm is now built as an ordinary
// crate during the same step as the rest of the compiler crates.
// This means that any crates depending on it will see the fact
// that it uses `libLLVM.so` as a native library, and will
// cause us to pass `-llibLLVM.so` to the linker when we link
// a binary.
//
// For `rustc` itself, this works out fine.
// During the `Assemble` step, we call `dist::maybe_install_llvm_dylib`
// to copy libLLVM.so into the `stage` directory. We then link
// the compiler binary, which will find `libLLVM.so` in the correct place.
//
// However, this is insufficient for tools that are build against stage0
// (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything,
// we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't
// a problem - we would copy the tool binary into its correct stage directory
// (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler).
// Since libLLVM.so wasn't resolved until runtime, it was fine for it to
// not exist while we were building it.
//
// To ensure that we can still build stage1 tools against a stage0 compiler,
// we explicitly copy libLLVM.so into the stage0 sysroot when building
// the stage0 compiler. This ensures that tools built against stage0
// will see libLLVM.so at build time, making the linker happy.
if compiler.stage == 0 {
builder.info(&format!("Installing libLLVM.so to stage 0 ({})", compiler.host));
let sysroot = builder.sysroot(compiler);
dist::maybe_install_llvm_dylib(builder, compiler.host, &sysroot);
}
builder.ensure(RustcLink {
compiler: builder.compiler(compiler.stage, builder.config.build),
target_compiler: compiler,

View file

@ -12,7 +12,7 @@ use crate::channel;
use crate::channel::GitInfo;
use crate::compile;
use crate::toolstate::ToolState;
use crate::util::{add_lib_path, exe, CiEnv};
use crate::util::{add_dylib_path, exe, CiEnv};
use crate::Compiler;
use crate::Mode;
@ -388,7 +388,7 @@ pub struct ErrorIndex {
impl ErrorIndex {
pub fn command(builder: &Builder<'_>, compiler: Compiler) -> Command {
let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler }));
add_lib_path(
add_dylib_path(
vec![PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))],
&mut cmd,
);
@ -689,7 +689,7 @@ impl<'a> Builder<'a> {
}
}
add_lib_path(lib_paths, &mut cmd);
add_dylib_path(lib_paths, &mut cmd);
cmd
}
}

View file

@ -40,7 +40,7 @@ pub fn libdir(target: &str) -> &'static str {
}
/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
pub fn add_dylib_path(path: Vec<PathBuf>, cmd: &mut Command) {
let mut list = dylib_path();
for path in path {
list.insert(0, path);
@ -72,6 +72,31 @@ pub fn dylib_path() -> Vec<PathBuf> {
env::split_paths(&var).collect()
}
/// Adds a list of lookup paths to `cmd`'s link library lookup path.
pub fn add_link_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
let mut list = link_lib_path();
for path in path {
list.insert(0, path);
}
cmd.env(link_lib_path_var(), t!(env::join_paths(list)));
}
/// Returns the environment variable which the link library lookup path
/// resides in for this platform.
fn link_lib_path_var() -> &'static str {
if cfg!(target_env = "msvc") { "LIB" } else { "LIBRARY_PATH" }
}
/// Parses the `link_lib_path_var()` environment variable, returning a list of
/// paths that are members of this lookup path.
fn link_lib_path() -> Vec<PathBuf> {
let var = match env::var_os(link_lib_path_var()) {
Some(v) => v,
None => return vec![],
};
env::split_paths(&var).collect()
}
/// `push` all components to `buf`. On windows, append `.exe` to the last component.
pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
let (&file, components) = components.split_last().expect("at least one component required");

View file

@ -12,7 +12,7 @@ export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
git clone https://github.com/CraneStation/wasi-libc
cd wasi-libc
git reset --hard 1fad33890a5e299027ce0eab7b6ad5260585e347
git reset --hard 9efc2f428358564fe64c374d762d0bfce1d92507
make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
cd ..

View file

@ -319,8 +319,6 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught!
Ub(String),
/// Free-form case for experimental UB. Only for errors that are never caught!
UbExperimental(String),
/// Unreachable code was executed.
Unreachable,
/// An enum discriminant was set to a value which was outside the range of valid values.
@ -381,7 +379,7 @@ impl fmt::Debug for UndefinedBehaviorInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use UndefinedBehaviorInfo::*;
match self {
Ub(msg) | UbExperimental(msg) => write!(f, "{}", msg),
Ub(msg) => write!(f, "{}", msg),
Unreachable => write!(f, "entering unreachable code"),
InvalidDiscriminant(val) => write!(f, "encountering invalid enum discriminant {}", val),
BoundsCheckFailed { ref len, ref index } => write!(
@ -563,8 +561,7 @@ impl InterpError<'_> {
InterpError::MachineStop(_)
| InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
_ => false,
}
}

View file

@ -229,8 +229,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
// (T1..Tn) and closures have same properties as T1..Tn --
// check if *any* of those are trivial.
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
ty::Closure(def_id, ref substs) => {
substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
ty::Closure(_, ref substs) => {
substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t))
}
ty::Adt(def, _) => {

View file

@ -341,7 +341,7 @@ impl<'tcx> Instance<'tcx> {
substs: ty::SubstsRef<'tcx>,
requested_kind: ty::ClosureKind,
) -> Instance<'tcx> {
let actual_kind = substs.as_closure().kind(def_id, tcx);
let actual_kind = substs.as_closure().kind();
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
@ -372,7 +372,7 @@ impl<'tcx> Instance<'tcx> {
let self_ty = tcx.mk_closure(closure_did, substs);
let sig = substs.as_closure().sig(closure_did, tcx);
let sig = substs.as_closure().sig();
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);

View file

@ -628,8 +628,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?,
ty::Closure(def_id, ref substs) => {
let tys = substs.as_closure().upvar_tys(def_id, tcx);
ty::Closure(_, ref substs) => {
let tys = substs.as_closure().upvar_tys();
univariant(
&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
@ -1402,7 +1402,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// Build a prefix layout, including "promoting" all ineligible
// locals as part of the prefix. We compute the layout of all of
// these fields at once to get optimal packing.
let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count();
let discr_index = substs.as_generator().prefix_tys().count();
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
let max_discr = (info.variant_fields.len() - 1) as u128;
@ -1419,7 +1419,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
.map(|ty| self.layout_of(ty));
let prefix_layouts = substs
.as_generator()
.prefix_tys(def_id, tcx)
.prefix_tys()
.map(|ty| self.layout_of(ty))
.chain(iter::once(Ok(discr_layout)))
.chain(promoted_layouts)
@ -2095,9 +2095,7 @@ where
ty::Str => tcx.types.u8,
// Tuples, generators and closures.
ty::Closure(def_id, ref substs) => {
substs.as_closure().upvar_tys(def_id, tcx).nth(i).unwrap()
}
ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(),
ty::Generator(def_id, ref substs, _) => match this.variants {
Variants::Single { index } => substs
@ -2111,7 +2109,7 @@ where
if i == discr_index {
return discr_layout(discr);
}
substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap()
substs.as_generator().prefix_tys().nth(i).unwrap()
}
},
@ -2298,7 +2296,7 @@ impl<'tcx> ty::Instance<'tcx> {
sig
}
ty::Closure(def_id, substs) => {
let sig = substs.as_closure().sig(def_id, tcx);
let sig = substs.as_closure().sig();
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
sig.map_bound(|sig| tcx.mk_fn_sig(
@ -2309,8 +2307,8 @@ impl<'tcx> ty::Instance<'tcx> {
sig.abi
))
}
ty::Generator(def_id, substs, _) => {
let sig = substs.as_generator().poly_sig(def_id, tcx);
ty::Generator(_, substs, _) => {
let sig = substs.as_generator().poly_sig();
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);

View file

@ -61,15 +61,15 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
// in the `subtys` iterator (e.g., when encountering a
// projection).
match ty.kind {
ty::Closure(def_id, ref substs) => {
for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) {
ty::Closure(_, ref substs) => {
for upvar_ty in substs.as_closure().upvar_tys() {
compute_components(tcx, upvar_ty, out);
}
}
ty::Generator(def_id, ref substs, _) => {
ty::Generator(_, ref substs, _) => {
// Same as the closure case
for upvar_ty in substs.as_generator().upvar_tys(def_id, tcx) {
for upvar_ty in substs.as_generator().upvar_tys() {
compute_components(tcx, upvar_ty, out);
}

View file

@ -617,8 +617,6 @@ pub trait PrettyPrinter<'tcx>:
}
ty::Str => p!(write("str")),
ty::Generator(did, substs, movability) => {
let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx());
let witness = substs.as_generator().witness(did, self.tcx());
match movability {
hir::Movability::Movable => p!(write("[generator")),
hir::Movability::Static => p!(write("[static generator")),
@ -627,31 +625,47 @@ pub trait PrettyPrinter<'tcx>:
// FIXME(eddyb) should use `def_span`.
if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
p!(write("@{:?}", self.tcx().hir().span(hir_id)));
let mut sep = " ";
for (&var_id, upvar_ty) in
self.tcx().upvars(did).as_ref().iter().flat_map(|v| v.keys()).zip(upvar_tys)
{
p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty));
sep = ", ";
if substs.as_generator().is_valid() {
let upvar_tys = substs.as_generator().upvar_tys();
let mut sep = " ";
for (&var_id, upvar_ty) in self
.tcx()
.upvars(did)
.as_ref()
.iter()
.flat_map(|v| v.keys())
.zip(upvar_tys)
{
p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty));
sep = ", ";
}
}
} else {
// Cross-crate closure types should only be
// visible in codegen bug reports, I imagine.
p!(write("@{:?}", did));
let mut sep = " ";
for (index, upvar_ty) in upvar_tys.enumerate() {
p!(write("{}{}:", sep, index), print(upvar_ty));
sep = ", ";
if substs.as_generator().is_valid() {
let upvar_tys = substs.as_generator().upvar_tys();
let mut sep = " ";
for (index, upvar_ty) in upvar_tys.enumerate() {
p!(write("{}{}:", sep, index), print(upvar_ty));
sep = ", ";
}
}
}
p!(write(" "), print(witness), write("]"))
if substs.as_generator().is_valid() {
p!(write(" "), print(substs.as_generator().witness()));
}
p!(write("]"))
}
ty::GeneratorWitness(types) => {
p!(in_binder(&types));
}
ty::Closure(did, substs) => {
let upvar_tys = substs.as_closure().upvar_tys(did, self.tcx());
p!(write("[closure"));
// FIXME(eddyb) should use `def_span`.
@ -661,30 +675,43 @@ pub trait PrettyPrinter<'tcx>:
} else {
p!(write("@{:?}", self.tcx().hir().span(hir_id)));
}
let mut sep = " ";
for (&var_id, upvar_ty) in
self.tcx().upvars(did).as_ref().iter().flat_map(|v| v.keys()).zip(upvar_tys)
{
p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty));
sep = ", ";
if substs.as_closure().is_valid() {
let upvar_tys = substs.as_closure().upvar_tys();
let mut sep = " ";
for (&var_id, upvar_ty) in self
.tcx()
.upvars(did)
.as_ref()
.iter()
.flat_map(|v| v.keys())
.zip(upvar_tys)
{
p!(write("{}{}:", sep, self.tcx().hir().name(var_id)), print(upvar_ty));
sep = ", ";
}
}
} else {
// Cross-crate closure types should only be
// visible in codegen bug reports, I imagine.
p!(write("@{:?}", did));
let mut sep = " ";
for (index, upvar_ty) in upvar_tys.enumerate() {
p!(write("{}{}:", sep, index), print(upvar_ty));
sep = ", ";
if substs.as_closure().is_valid() {
let upvar_tys = substs.as_closure().upvar_tys();
let mut sep = " ";
for (index, upvar_ty) in upvar_tys.enumerate() {
p!(write("{}{}:", sep, index), print(upvar_ty));
sep = ", ";
}
}
}
if self.tcx().sess.verbose() {
p!(write(
" closure_kind_ty={:?} closure_sig_as_fn_ptr_ty={:?}",
substs.as_closure().kind_ty(did, self.tcx()),
substs.as_closure().sig_as_fn_ptr_ty(did, self.tcx())
));
if self.tcx().sess.verbose() && substs.as_closure().is_valid() {
p!(write(" closure_kind_ty="), print(substs.as_closure().kind_ty()));
p!(
write(" closure_sig_as_fn_ptr_ty="),
print(substs.as_closure().sig_as_fn_ptr_ty())
);
}
p!(write("]"))

View file

@ -11,7 +11,7 @@ use crate::mir::interpret::ConstValue;
use crate::mir::interpret::Scalar;
use crate::mir::Promoted;
use crate::ty::layout::VariantIdx;
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::{
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
};
@ -260,15 +260,11 @@ static_assert_size!(TyKind<'_>, 24);
/// A closure can be modeled as a struct that looks like:
///
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> {
/// upvar0: U0,
/// ...
/// upvark: Uk
/// }
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
///
/// where:
///
/// - 'l0...'li and T0...Tj are the lifetime and type parameters
/// - 'l0...'li and T0...Tj are the generic parameters
/// in scope on the function that defined the closure,
/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
/// is rather hackily encoded via a scalar type. See
@ -277,9 +273,9 @@ static_assert_size!(TyKind<'_>, 24);
/// type. For example, `fn(u32, u32) -> u32` would mean that the closure
/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
/// specified above.
/// - U0...Uk are type parameters representing the types of its upvars
/// (borrowed, if appropriate; that is, if Ui represents a by-ref upvar,
/// and the up-var has the type `Foo`, then `Ui = &Foo`).
/// - U is a type parameter representing the types of its upvars, tupled up
/// (borrowed, if appropriate; that is, if an U field represents a by-ref upvar,
/// and the up-var has the type `Foo`, then that field of U will be `&Foo`).
///
/// So, for example, given this function:
///
@ -289,9 +285,7 @@ static_assert_size!(TyKind<'_>, 24);
///
/// the type of the closure would be something like:
///
/// struct Closure<'a, T, U0> {
/// data: U0
/// }
/// struct Closure<'a, T, U>(...U);
///
/// Note that the type of the upvar is not specified in the struct.
/// You may wonder how the impl would then be able to use the upvar,
@ -299,7 +293,7 @@ static_assert_size!(TyKind<'_>, 24);
/// (conceptually) not fully generic over Closure but rather tied to
/// instances with the expected upvar types:
///
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> {
/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
/// ...
/// }
///
@ -308,7 +302,7 @@ static_assert_size!(TyKind<'_>, 24);
/// (Here, I am assuming that `data` is mut-borrowed.)
///
/// Now, the last question you may ask is: Why include the upvar types
/// as extra type parameters? The reason for this design is that the
/// in an extra type parameter? The reason for this design is that the
/// upvar types can reference lifetimes that are internal to the
/// creating function. In my example above, for example, the lifetime
/// `'b` represents the scope of the closure itself; this is some
@ -360,7 +354,7 @@ static_assert_size!(TyKind<'_>, 24);
#[derive(Copy, Clone, Debug, TypeFoldable)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
/// concatenated with the types of the upvars.
/// concatenated with a tuple containing the types of the upvars.
///
/// These are separated out because codegen wants to pass them around
/// when monomorphizing.
@ -370,52 +364,52 @@ pub struct ClosureSubsts<'tcx> {
/// Struct returned by `split()`. Note that these are subslices of the
/// parent slice and not canonical substs themselves.
struct SplitClosureSubsts<'tcx> {
closure_kind_ty: Ty<'tcx>,
closure_sig_as_fn_ptr_ty: Ty<'tcx>,
upvar_kinds: &'tcx [GenericArg<'tcx>],
closure_kind_ty: GenericArg<'tcx>,
closure_sig_as_fn_ptr_ty: GenericArg<'tcx>,
tupled_upvars_ty: GenericArg<'tcx>,
}
impl<'tcx> ClosureSubsts<'tcx> {
/// Divides the closure substs into their respective
/// components. Single source of truth with respect to the
/// ordering.
fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitClosureSubsts<'tcx> {
let generics = tcx.generics_of(def_id);
let parent_len = generics.parent_count;
SplitClosureSubsts {
closure_kind_ty: self.substs.type_at(parent_len),
closure_sig_as_fn_ptr_ty: self.substs.type_at(parent_len + 1),
upvar_kinds: &self.substs[parent_len + 2..],
fn split(self) -> SplitClosureSubsts<'tcx> {
match self.substs[..] {
[.., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
SplitClosureSubsts { closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty }
}
_ => bug!("closure substs missing synthetics"),
}
}
/// Returns `true` only if enough of the synthetic types are known to
/// allow using all of the methods on `ClosureSubsts` without panicking.
///
/// Used primarily by `ty::print::pretty` to be able to handle closure
/// types that haven't had their synthetic types substituted in.
pub fn is_valid(self) -> bool {
self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_))
}
#[inline]
pub fn upvar_tys(
self,
def_id: DefId,
tcx: TyCtxt<'_>,
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
upvar_kinds.iter().map(|t| {
if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
}
})
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
self.split().tupled_upvars_ty.expect_ty().tuple_fields()
}
/// Returns the closure kind for this closure; may return a type
/// variable during inference. To get the closure kind during
/// inference, use `infcx.closure_kind(def_id, substs)`.
pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_kind_ty
/// inference, use `infcx.closure_kind(substs)`.
pub fn kind_ty(self) -> Ty<'tcx> {
self.split().closure_kind_ty.expect_ty()
}
/// Returns the `fn` pointer type representing the closure signature for this
/// closure.
pub fn sig_as_fn_ptr_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_sig_as_fn_ptr_ty
// FIXME(eddyb) this should be unnecessary, as the shallowly resolved
// type is known at the time of the creation of `ClosureSubsts`,
// see `rustc_typeck::check::closure`.
pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
self.split().closure_sig_as_fn_ptr_ty.expect_ty()
}
/// Returns the closure kind for this closure; only usable outside
@ -423,13 +417,13 @@ impl<'tcx> ClosureSubsts<'tcx> {
/// there are no type variables.
///
/// If you have an inference context, use `infcx.closure_kind()`.
pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
pub fn kind(self) -> ty::ClosureKind {
self.kind_ty().to_opt_closure_kind().unwrap()
}
/// Extracts the signature from the closure.
pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
let ty = self.sig_as_fn_ptr_ty(def_id, tcx);
pub fn sig(self) -> ty::PolyFnSig<'tcx> {
let ty = self.sig_as_fn_ptr_ty();
match ty.kind {
ty::FnPtr(sig) => sig,
_ => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {:?}", ty.kind),
@ -444,64 +438,59 @@ pub struct GeneratorSubsts<'tcx> {
}
struct SplitGeneratorSubsts<'tcx> {
resume_ty: Ty<'tcx>,
yield_ty: Ty<'tcx>,
return_ty: Ty<'tcx>,
witness: Ty<'tcx>,
upvar_kinds: &'tcx [GenericArg<'tcx>],
resume_ty: GenericArg<'tcx>,
yield_ty: GenericArg<'tcx>,
return_ty: GenericArg<'tcx>,
witness: GenericArg<'tcx>,
tupled_upvars_ty: GenericArg<'tcx>,
}
impl<'tcx> GeneratorSubsts<'tcx> {
fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitGeneratorSubsts<'tcx> {
let generics = tcx.generics_of(def_id);
let parent_len = generics.parent_count;
SplitGeneratorSubsts {
resume_ty: self.substs.type_at(parent_len),
yield_ty: self.substs.type_at(parent_len + 1),
return_ty: self.substs.type_at(parent_len + 2),
witness: self.substs.type_at(parent_len + 3),
upvar_kinds: &self.substs[parent_len + 4..],
fn split(self) -> SplitGeneratorSubsts<'tcx> {
match self.substs[..] {
[.., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
SplitGeneratorSubsts { resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty }
}
_ => bug!("generator substs missing synthetics"),
}
}
/// Returns `true` only if enough of the synthetic types are known to
/// allow using all of the methods on `GeneratorSubsts` without panicking.
///
/// Used primarily by `ty::print::pretty` to be able to handle generator
/// types that haven't had their synthetic types substituted in.
pub fn is_valid(self) -> bool {
self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_))
}
/// This describes the types that can be contained in a generator.
/// It will be a type variable initially and unified in the last stages of typeck of a body.
/// It contains a tuple of all the types that could end up on a generator frame.
/// The state transformation MIR pass may only produce layouts which mention types
/// in this tuple. Upvars are not counted here.
pub fn witness(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).witness
pub fn witness(self) -> Ty<'tcx> {
self.split().witness.expect_ty()
}
#[inline]
pub fn upvar_tys(
self,
def_id: DefId,
tcx: TyCtxt<'_>,
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
upvar_kinds.iter().map(|t| {
if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
}
})
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
self.split().tupled_upvars_ty.expect_ty().tuple_fields()
}
/// Returns the type representing the resume type of the generator.
pub fn resume_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).resume_ty
pub fn resume_ty(self) -> Ty<'tcx> {
self.split().resume_ty.expect_ty()
}
/// Returns the type representing the yield type of the generator.
pub fn yield_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).yield_ty
pub fn yield_ty(self) -> Ty<'tcx> {
self.split().yield_ty.expect_ty()
}
/// Returns the type representing the return type of the generator.
pub fn return_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).return_ty
pub fn return_ty(self) -> Ty<'tcx> {
self.split().return_ty.expect_ty()
}
/// Returns the "generator signature", which consists of its yield
@ -510,17 +499,17 @@ impl<'tcx> GeneratorSubsts<'tcx> {
/// N.B., some bits of the code prefers to see this wrapped in a
/// binder, but it never contains bound regions. Probably this
/// function should be removed.
pub fn poly_sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> PolyGenSig<'tcx> {
ty::Binder::dummy(self.sig(def_id, tcx))
pub fn poly_sig(self) -> PolyGenSig<'tcx> {
ty::Binder::dummy(self.sig())
}
/// Returns the "generator signature", which consists of its resume, yield
/// and return types.
pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> GenSig<'tcx> {
pub fn sig(self) -> GenSig<'tcx> {
ty::GenSig {
resume_ty: self.resume_ty(def_id, tcx),
yield_ty: self.yield_ty(def_id, tcx),
return_ty: self.return_ty(def_id, tcx),
resume_ty: self.resume_ty(),
yield_ty: self.yield_ty(),
return_ty: self.return_ty(),
}
}
}
@ -612,8 +601,8 @@ impl<'tcx> GeneratorSubsts<'tcx> {
/// This is the types of the fields of a generator which are not stored in a
/// variant.
#[inline]
pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = Ty<'tcx>> {
self.upvar_tys(def_id, tcx)
pub fn prefix_tys(self) -> impl Iterator<Item = Ty<'tcx>> {
self.upvar_tys()
}
}
@ -625,22 +614,12 @@ pub enum UpvarSubsts<'tcx> {
impl<'tcx> UpvarSubsts<'tcx> {
#[inline]
pub fn upvar_tys(
self,
def_id: DefId,
tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let upvar_kinds = match self {
UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds,
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let tupled_upvars_ty = match self {
UpvarSubsts::Closure(substs) => substs.as_closure().split().tupled_upvars_ty,
UpvarSubsts::Generator(substs) => substs.as_generator().split().tupled_upvars_ty,
};
upvar_kinds.iter().map(|t| {
if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
}
})
tupled_upvars_ty.expect_ty().tuple_fields()
}
}

View file

@ -502,7 +502,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> Option<ty::Binder<Ty<'tcx>>> {
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),

View file

@ -71,8 +71,7 @@ pub fn write_compressed_metadata<'tcx>(
// flags, at least for ELF outputs, so that the
// metadata doesn't get loaded into memory.
let directive = format!(".section {}", section_name);
let directive = CString::new(directive).unwrap();
llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr())
llvm::LLVMSetModuleInlineAsm2(metadata_llmod, directive.as_ptr().cast(), directive.len())
}
}

View file

@ -1,7 +1,7 @@
use crate::base;
use crate::common::CodegenCx;
use crate::debuginfo;
use crate::llvm::{self, SetUnnamedAddr, True};
use crate::llvm::{self, True};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
@ -183,7 +183,7 @@ impl CodegenCx<'ll, 'tcx> {
};
llvm::LLVMSetInitializer(gv, cv);
set_global_alignment(&self, gv, align);
SetUnnamedAddr(gv, true);
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
gv
}
}

View file

@ -166,7 +166,7 @@ pub unsafe fn create_module(
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
llvm::LLVMRustDisposeTargetMachine(tm);
let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
.expect("got a non-UTF8 data-layout from LLVM");
@ -458,7 +458,7 @@ impl CodegenCx<'b, 'tcx> {
self.type_variadic_func(&[], ret)
};
let f = self.declare_cfn(name, fn_ty);
llvm::SetUnnamedAddr(f, false);
llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No);
self.intrinsics.borrow_mut().insert(name, f);
f
}

View file

@ -1,11 +1,13 @@
use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DIScope, DISubprogram};
use rustc::mir::{Body, SourceScope};
use rustc_session::config::DebugInfo;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
@ -19,10 +21,17 @@ pub fn compute_mir_scopes(
) {
// Find all the scopes with variables defined in them.
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
// FIXME(eddyb) take into account that arguments always have debuginfo,
// irrespective of their name (assuming full debuginfo is enabled).
for var_debug_info in &mir.var_debug_info {
has_variables.insert(var_debug_info.source_info.scope);
// Only consider variables when they're going to be emitted.
// FIXME(eddyb) don't even allocate `has_variables` otherwise.
if cx.sess().opts.debuginfo == DebugInfo::Full {
// FIXME(eddyb) take into account that arguments always have debuginfo,
// irrespective of their name (assuming full debuginfo is enabled).
// NOTE(eddyb) actually, on second thought, those are always in the
// function scope, which always exists.
for var_debug_info in &mir.var_debug_info {
has_variables.insert(var_debug_info.source_info.scope);
}
}
// Instantiate all scopes.

View file

@ -50,7 +50,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) -
llvm::LLVMSetSection(section_var, section_name.as_ptr().cast());
llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
// This should make sure that the whole section is not larger than
// the string it contains. Otherwise we get a warning from GDB.

View file

@ -663,7 +663,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
}
ty::Closure(def_id, substs) => {
let upvar_tys: Vec<_> = substs.as_closure().upvar_tys(def_id, cx.tcx).collect();
let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect();
let containing_scope = get_namespace_for_item(cx, def_id);
prepare_tuple_metadata(
cx,
@ -678,7 +678,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
ty::Generator(def_id, substs, _) => {
let upvar_tys: Vec<_> = substs
.as_generator()
.prefix_tys(def_id, cx.tcx)
.prefix_tys()
.map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
.collect();
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys)
@ -2299,6 +2299,11 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
return;
}
// Only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo != DebugInfo::Full {
return;
}
let tcx = cx.tcx;
let attrs = tcx.codegen_fn_attrs(def_id);
@ -2358,6 +2363,11 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
return;
}
// Only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo != DebugInfo::Full {
return;
}
let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP);
unsafe {

View file

@ -475,7 +475,12 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
// so avoid methods on other types (e.g., `<*mut T>::null`).
match impl_self_ty.kind {
ty::Adt(def, ..) if !def.is_box() => {
Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
// Again, only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo == DebugInfo::Full {
Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
} else {
Some(namespace::item_namespace(cx, def.did))
}
}
_ => None,
}

View file

@ -40,7 +40,7 @@ fn declare_raw_fn(
llvm::SetFunctionCallConv(llfn, callconv);
// Function addresses in Rust are never significant, allowing functions to
// be merged.
llvm::SetUnnamedAddr(llfn, true);
llvm::SetUnnamedAddress(llfn, llvm::UnnamedAddr::Global);
if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.target.options.disable_redzone) {
llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);

View file

@ -1662,7 +1662,7 @@ fn generic_simd_intrinsic(
llvm_elem_vec_ty,
),
);
llvm::SetUnnamedAddr(f, false);
llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No);
let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None);
return Ok(v);
}
@ -1784,7 +1784,7 @@ fn generic_simd_intrinsic(
&llvm_intrinsic,
bx.type_func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t),
);
llvm::SetUnnamedAddr(f, false);
llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No);
let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None);
return Ok(v);
}
@ -2083,7 +2083,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64);
let f = bx.declare_cfn(&llvm_intrinsic, bx.type_func(&[vec_ty, vec_ty], vec_ty));
llvm::SetUnnamedAddr(f, false);
llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No);
let v = bx.call(f, &[lhs, rhs], None);
return Ok(v);
}

View file

@ -73,6 +73,14 @@ pub enum Visibility {
Protected = 2,
}
/// LLVMUnnamedAddr
#[repr(C)]
pub enum UnnamedAddr {
No,
Local,
Global,
}
/// LLVMDLLStorageClass
#[derive(Copy, Clone)]
#[repr(C)]
@ -727,11 +735,11 @@ extern "C" {
pub fn LLVMCloneModule(M: &Module) -> &Module;
/// Data layout. See Module::getDataLayout.
pub fn LLVMGetDataLayout(M: &Module) -> *const c_char;
pub fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
/// See Module::setModuleInlineAsm.
pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char);
pub fn LLVMSetModuleInlineAsm2(M: &Module, Asm: *const c_char, AsmLen: size_t);
pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t);
/// See llvm::LLVMTypeKind::getTypeID.
@ -1853,7 +1861,7 @@ extern "C" {
UniqueIdLen: size_t,
) -> &'a DIDerivedType;
pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool);
pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(
Builder: &DIBuilder<'a>,

View file

@ -106,9 +106,9 @@ pub fn UnsetComdat(val: &'a Value) {
}
}
pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
pub fn SetUnnamedAddress(global: &'a Value, unnamed: UnnamedAddr) {
unsafe {
LLVMSetUnnamedAddr(global, unnamed as Bool);
LLVMSetUnnamedAddress(global, unnamed);
}
}

View file

@ -3,7 +3,7 @@ use crate::infer::InferCtxt;
use rustc::hir::map::Map;
use rustc::ty::print::Print;
use rustc::ty::{self, DefIdTree, Infer, Ty, TyVar};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@ -277,8 +277,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
};
let ty_msg = match local_visitor.found_ty {
Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => {
let fn_sig = substs.as_closure().sig(*def_id, self.tcx);
Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => {
let fn_sig = substs.as_closure().sig();
let args = closure_args(&fn_sig);
let ret = fn_sig.output().skip_binder().to_string();
format!(" for the closure `fn({}) -> {}`", args, ret)
@ -311,8 +311,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
let suffix = match local_visitor.found_ty {
Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => {
let fn_sig = substs.as_closure().sig(*def_id, self.tcx);
Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => {
let fn_sig = substs.as_closure().sig();
let ret = fn_sig.output().skip_binder().to_string();
if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
@ -462,24 +462,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
e: &Expr<'_>,
err: &mut DiagnosticBuilder<'_>,
) {
if let (Ok(snippet), Some(tables), None) = (
self.tcx.sess.source_map().span_to_snippet(segment.ident.span),
self.in_progress_tables,
&segment.args,
) {
if let (Some(tables), None) = (self.in_progress_tables, &segment.args) {
let borrow = tables.borrow();
if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) {
let generics = self.tcx.generics_of(did);
if !generics.params.is_empty() {
err.span_suggestion(
segment.ident.span,
err.span_suggestion_verbose(
segment.ident.span.shrink_to_hi(),
&format!(
"consider specifying the type argument{} in the method call",
if generics.params.len() > 1 { "s" } else { "" },
pluralize!(generics.params.len()),
),
format!(
"{}::<{}>",
snippet,
"::<{}>",
generics
.params
.iter()

View file

@ -1496,12 +1496,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// Obtains the latest type of the given closure; this may be a
/// closure in the current function, in which case its
/// `ClosureKind` may not yet be known.
pub fn closure_kind(
&self,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Option<ty::ClosureKind> {
let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx);
pub fn closure_kind(&self, closure_substs: SubstsRef<'tcx>) -> Option<ty::ClosureKind> {
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind_ty = self.shallow_resolve(closure_kind_ty);
closure_kind_ty.to_opt_closure_kind()
}

View file

@ -54,6 +54,7 @@ pub enum TypeVariableOriginKind {
/// One of the upvars or closure kind parameters in a `ClosureSubsts`
/// (before it has been determined).
// FIXME(eddyb) distinguish upvar inference variables from the rest.
ClosureSynthetic,
SubstitutionPlaceholder,
AutoDeref,

View file

@ -151,6 +151,7 @@ fn main() {
if env::var_os("LLVM_NDEBUG").is_some() {
cfg.define("NDEBUG", None);
cfg.debug(false);
}
build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm"));

View file

@ -1320,7 +1320,7 @@ impl EncodeContext<'tcx> {
record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
self.encode_item_type(def_id);
if let ty::Closure(def_id, substs) = ty.kind {
record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx));
record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig());
}
self.encode_generics(def_id);
self.encode_optimized_mir(def_id);

View file

@ -1682,10 +1682,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// If a closure captured our `target` and then assigned
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure = self.annotate_fn_sig(
*def_id,
substs.as_closure().sig(*def_id, self.infcx.tcx),
);
annotated_closure =
self.annotate_fn_sig(*def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \

View file

@ -333,7 +333,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
ty::Closure(def_id, closure_substs)
if def_id == self.mir_def_id && upvar_field.is_some() =>
{
let closure_kind_ty = closure_substs.as_closure().kind_ty(def_id, self.infcx.tcx);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind();
let capture_description = match closure_kind {
Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",

View file

@ -135,11 +135,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
if let ty::BoundRegion::BrEnv = free_region.bound_region {
if let DefiningTy::Closure(def_id, substs) =
if let DefiningTy::Closure(_, substs) =
self.regioncx.universal_regions().defining_ty
{
return substs.as_closure().kind(def_id, self.infcx.tcx)
== ty::ClosureKind::FnMut;
return substs.as_closure().kind() == ty::ClosureKind::FnMut;
}
}
}

View file

@ -245,7 +245,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.expect("non-local mir");
let def_ty = self.regioncx.universal_regions().defining_ty;
if let DefiningTy::Closure(def_id, substs) = def_ty {
if let DefiningTy::Closure(_, substs) = def_ty {
let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) =
tcx.hir().expect_expr(mir_hir_id).kind
{
@ -255,7 +255,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
};
let region_name = self.synthesize_region_name();
let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx);
let closure_kind_ty = substs.as_closure().kind_ty();
let note = match closure_kind_ty.to_opt_closure_kind() {
Some(ty::ClosureKind::Fn) => {
"closure implements `Fn`, so references to captured variables \

View file

@ -35,7 +35,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Search the upvars (if any) to find one that references fr. Return its index.
crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option<usize> {
let upvar_index =
self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| {
self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| {
debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty);
tcx.any_free_region_meets(&upvar_ty, |r| {
let r = r.to_region_vid();
@ -44,7 +44,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
})
})?;
let upvar_ty = self.universal_regions().defining_ty.upvar_tys(tcx).nth(upvar_index);
let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index);
debug!(
"get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}",

View file

@ -757,21 +757,21 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
(&adt_def.variants[VariantIdx::new(0)], substs)
}
ty::Closure(def_id, substs) => {
return match substs.as_closure().upvar_tys(def_id, tcx).nth(field.index()) {
ty::Closure(_, substs) => {
return match substs.as_closure().upvar_tys().nth(field.index()) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.as_closure().upvar_tys(def_id, tcx).count(),
field_count: substs.as_closure().upvar_tys().count(),
}),
};
}
ty::Generator(def_id, substs, _) => {
ty::Generator(_, substs, _) => {
// Only prefix fields (upvars and current state) are
// accessible without a variant index.
return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) {
return match substs.as_generator().prefix_tys().nth(field.index()) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.as_generator().prefix_tys(def_id, tcx).count(),
field_count: substs.as_generator().prefix_tys().count(),
}),
};
}
@ -1946,22 +1946,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
}
}
AggregateKind::Closure(def_id, substs) => {
match substs.as_closure().upvar_tys(def_id, tcx).nth(field_index) {
AggregateKind::Closure(_, substs) => {
match substs.as_closure().upvar_tys().nth(field_index) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.as_closure().upvar_tys(def_id, tcx).count(),
field_count: substs.as_closure().upvar_tys().count(),
}),
}
}
AggregateKind::Generator(def_id, substs, _) => {
AggregateKind::Generator(_, substs, _) => {
// It doesn't make sense to look at a field beyond the prefix;
// these require a variant index, and are not initialized in
// aggregate rvalues.
match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) {
match substs.as_generator().prefix_tys().nth(field_index) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.as_generator().prefix_tys(def_id, tcx).count(),
field_count: substs.as_generator().prefix_tys().count(),
}),
}
}
@ -2085,7 +2085,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
let sig = match op.ty(*body, tcx).kind {
ty::Closure(def_id, substs) => substs.as_closure().sig(def_id, tcx),
ty::Closure(_, substs) => substs.as_closure().sig(),
_ => bug!(),
};
let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig, *unsafety);

View file

@ -108,13 +108,11 @@ impl<'tcx> DefiningTy<'tcx> {
/// not a closure or generator, there are no upvars, and hence it
/// will be an empty list. The order of types in this list will
/// match up with the upvar order in the HIR, typesystem, and MIR.
pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
match self {
DefiningTy::Closure(def_id, substs) => {
Either::Left(substs.as_closure().upvar_tys(def_id, tcx))
}
DefiningTy::Generator(def_id, substs, _) => {
Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx)))
DefiningTy::Closure(_, substs) => Either::Left(substs.as_closure().upvar_tys()),
DefiningTy::Generator(_, substs, _) => {
Either::Right(Either::Left(substs.as_generator().upvar_tys()))
}
DefiningTy::FnDef(..) | DefiningTy::Const(..) => {
Either::Right(Either::Right(iter::empty()))
@ -470,9 +468,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
debug!("build: local regions = {}..{}", first_local_index, num_universals);
let yield_ty = match defining_ty {
DefiningTy::Generator(def_id, substs, _) => {
Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx))
}
DefiningTy::Generator(_, substs, _) => Some(substs.as_generator().yield_ty()),
_ => None,
};
@ -580,7 +576,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
match defining_ty {
DefiningTy::Closure(def_id, substs) => {
assert_eq!(self.mir_def_id, def_id);
let closure_sig = substs.as_closure().sig(def_id, tcx);
let closure_sig = substs.as_closure().sig();
let inputs_and_output = closure_sig.inputs_and_output();
let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| {
@ -604,8 +600,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
DefiningTy::Generator(def_id, substs, movability) => {
assert_eq!(self.mir_def_id, def_id);
let resume_ty = substs.as_generator().resume_ty(def_id, tcx);
let output = substs.as_generator().return_ty(def_id, tcx);
let resume_ty = substs.as_generator().resume_ty();
let output = substs.as_generator().return_ty();
let generator_ty = tcx.mk_generator(def_id, substs, movability);
let inputs_and_output =
self.infcx.tcx.intern_type_list(&[generator_ty, resume_ty, output]);

View file

@ -341,8 +341,8 @@ fn build_clone_shim<'tcx>(
let len = len.eval_usize(tcx, param_env);
builder.array_shim(dest, src, ty, len)
}
ty::Closure(def_id, substs) => {
builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys(def_id, tcx))
ty::Closure(_, substs) => {
builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
}
ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
_ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),

View file

@ -1236,8 +1236,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
ty::Generator(_, substs, movability) => {
let substs = substs.as_generator();
(
substs.upvar_tys(def_id, tcx).collect(),
substs.witness(def_id, tcx),
substs.upvar_tys().collect(),
substs.witness(),
substs.discr_ty(tcx),
movability == hir::Movability::Movable,
)

View file

@ -798,8 +798,8 @@ where
fn open_drop(&mut self) -> BasicBlock {
let ty = self.place_ty(self.place);
match ty.kind {
ty::Closure(def_id, substs) => {
let tys: Vec<_> = substs.as_closure().upvar_tys(def_id, self.tcx()).collect();
ty::Closure(_, substs) => {
let tys: Vec<_> = substs.as_closure().upvar_tys().collect();
self.open_drop_for_tuple(&tys)
}
// Note that `elaborate_drops` only drops the upvars of a generator,
@ -808,8 +808,8 @@ where
// This should only happen for the self argument on the resume function.
// It effetively only contains upvars until the generator transformation runs.
// See librustc_body/transform/generator.rs for more details.
ty::Generator(def_id, substs, _) => {
let tys: Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect();
ty::Generator(_, substs, _) => {
let tys: Vec<_> = substs.as_generator().upvar_tys().collect();
self.open_drop_for_tuple(&tys)
}
ty::Tuple(..) => {

View file

@ -140,9 +140,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let (yield_ty, return_ty) = if body.generator_kind.is_some() {
let gen_sig = match ty.kind {
ty::Generator(gen_def_id, gen_substs, ..) => {
gen_substs.as_generator().sig(gen_def_id, tcx)
}
ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
_ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty),
};
(Some(gen_sig.yield_ty), gen_sig.return_ty)
@ -849,12 +847,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
closure_env_projs.push(ProjectionElem::Deref);
closure_ty = ty;
}
let (def_id, upvar_substs) = match closure_ty.kind {
ty::Closure(def_id, substs) => (def_id, ty::UpvarSubsts::Closure(substs)),
ty::Generator(def_id, substs, _) => (def_id, ty::UpvarSubsts::Generator(substs)),
let upvar_substs = match closure_ty.kind {
ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
_ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
};
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
let upvar_tys = upvar_substs.upvar_tys();
let upvars_with_tys = upvars.iter().zip(upvar_tys);
self.upvar_mutbls = upvars_with_tys
.enumerate()

View file

@ -387,7 +387,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
.upvars(def_id)
.iter()
.flat_map(|upvars| upvars.iter())
.zip(substs.upvar_tys(def_id, cx.tcx))
.zip(substs.upvar_tys())
.map(|((&var_hir_id, _), ty)| capture_upvar(cx, expr, var_hir_id, ty))
.collect();
ExprKind::Closure { closure_id: def_id, substs, upvars, movability }
@ -830,7 +830,7 @@ fn convert_var<'tcx>(
let region = cx.tcx.mk_region(region);
let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.kind {
match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() {
match cx.infcx.closure_kind(closure_substs).unwrap() {
ty::ClosureKind::Fn => {
let ref_closure_ty = cx.tcx.mk_ref(
region,

View file

@ -1038,7 +1038,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
def.variant_descr(),
self.tcx.def_path_str(def.did)
)
.span_label(span, format!("field `{}` is private", field.ident))
.span_label(span, "private field")
.emit();
}
}
@ -1180,7 +1180,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
let is_error = !self.item_is_accessible(def_id);
if is_error {
self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr));
self.tcx
.sess
.struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
.span_label(self.span, &format!("private {}", kind))
.emit();
}
is_error
}
@ -1313,8 +1317,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
hir::QPath::Resolved(_, ref path) => path.to_string(),
hir::QPath::TypeRelative(_, ref segment) => segment.ident.to_string(),
};
let msg = format!("{} `{}` is private", kind.descr(def_id), name);
self.tcx.sess.span_err(span, &msg);
let kind = kind.descr(def_id);
self.tcx
.sess
.struct_span_err(span, &format!("{} `{}` is private", kind, name))
.span_label(span, &format!("private {}", kind))
.emit();
return;
}
}

View file

@ -1149,7 +1149,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}))
} else {
let module = parent_scope.module;
let vis = self.resolve_visibility(&item.vis);
let vis = match item.kind {
// Visibilities must not be resolved non-speculatively twice
// and we already resolved this one as a `fn` item visibility.
ItemKind::Fn(..) => self
.resolve_visibility_speculative(&item.vis, true)
.unwrap_or(ty::Visibility::Public),
_ => self.resolve_visibility(&item.vis),
};
if vis != ty::Visibility::Public {
self.insert_unused_macro(ident, item.id, span);
}

View file

@ -951,7 +951,7 @@ impl<'a> Resolver<'a> {
let descr = get_descr(binding);
let mut err =
struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
err.span_label(ident.span, &format!("this {} is private", descr));
err.span_label(ident.span, &format!("private {}", descr));
if let Some(span) = ctor_fields_span {
err.span_label(span, "a constructor is private if any of the fields is private");
}

View file

@ -506,10 +506,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
match (res, source) {
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
err.span_suggestion(
span,
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
format!("{}!", path_str),
"!".to_string(),
Applicability::MaybeIncorrect,
);
if path_str == "try" && span.rust_2015() {

View file

@ -423,7 +423,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
for required_region in required_region_bounds {
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx: self.tcx,
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
});
}
@ -504,7 +503,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx: self.tcx,
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
});
}
@ -541,7 +539,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx: self.tcx,
op: |r| {
self.member_constraint(
opaque_type_def_id,
@ -682,15 +679,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
//
// We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters.
struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
where
OP: FnMut(ty::Region<'tcx>),
{
tcx: TyCtxt<'tcx>,
struct ConstrainOpaqueTypeRegionVisitor<OP> {
op: OP,
}
impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
where
OP: FnMut(ty::Region<'tcx>),
{
@ -717,27 +710,27 @@ where
}
match ty.kind {
ty::Closure(def_id, ref substs) => {
ty::Closure(_, ref substs) => {
// Skip lifetime parameters of the enclosing item(s)
for upvar_ty in substs.as_closure().upvar_tys(def_id, self.tcx) {
for upvar_ty in substs.as_closure().upvar_tys() {
upvar_ty.visit_with(self);
}
substs.as_closure().sig_as_fn_ptr_ty(def_id, self.tcx).visit_with(self);
substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
}
ty::Generator(def_id, ref substs, _) => {
ty::Generator(_, ref substs, _) => {
// Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions.
for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) {
for upvar_ty in substs.as_generator().upvar_tys() {
upvar_ty.visit_with(self);
}
substs.as_generator().return_ty(def_id, self.tcx).visit_with(self);
substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self);
substs.as_generator().resume_ty(def_id, self.tcx).visit_with(self);
substs.as_generator().return_ty().visit_with(self);
substs.as_generator().yield_ty().visit_with(self);
substs.as_generator().resume_ty().visit_with(self);
}
_ => {
ty.super_visit_with(self);

View file

@ -481,7 +481,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
let found_kind = self.closure_kind(closure_substs).unwrap();
let closure_span = self
.tcx
.sess
@ -815,11 +815,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
if found_args.is_empty() && is_closure {
let underscores = vec!["_"; expected_args.len()].join(", ");
err.span_suggestion(
err.span_suggestion_verbose(
pipe_span,
&format!(
"consider changing the closure to take and ignore the expected argument{}",
if expected_args.len() < 2 { "" } else { "s" }
pluralize!(expected_args.len())
),
format!("|{}|", underscores),
Applicability::MachineApplicable,
@ -833,7 +833,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
.map(|(name, _)| name.to_owned())
.collect::<Vec<String>>()
.join(", ");
err.span_suggestion(
err.span_suggestion_verbose(
found_span,
"change the closure to take multiple arguments instead of a single tuple",
format!("|{}|", sugg),
@ -870,7 +870,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
String::new()
},
);
err.span_suggestion(
err.span_suggestion_verbose(
found_span,
"change the closure to accept a tuple instead of individual arguments",
sugg,
@ -1420,15 +1420,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
// |
// = note: cannot resolve `_: Tt`
err.span_suggestion(
span,
err.span_suggestion_verbose(
span.shrink_to_hi(),
&format!(
"consider specifying the type argument{} in the function call",
if generics.params.len() > 1 { "s" } else { "" },
pluralize!(generics.params.len()),
),
format!(
"{}::<{}>",
snippet,
"::<{}>",
generics
.params
.iter()
@ -1590,7 +1589,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
[] => (span.shrink_to_hi(), ":"),
[.., bound] => (bound.span().shrink_to_hi(), " + "),
};
err.span_suggestion(
err.span_suggestion_verbose(
span,
"consider relaxing the implicit `Sized` restriction",
format!("{} ?Sized", separator),

View file

@ -367,9 +367,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) {
let self_ty = trait_ref.self_ty();
let (def_id, output_ty, callable) = match self_ty.kind {
ty::Closure(def_id, substs) => {
(def_id, substs.as_closure().sig(def_id, self.tcx).output(), "closure")
}
ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"),
ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
_ => return,
};
@ -390,7 +388,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
let hir = self.tcx.hir();
// Get the name of the callable and the arguments to be used in the suggestion.
let snippet = match hir.get_if_local(def_id) {
let (snippet, sugg) = match hir.get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, decl, _, span, ..),
..
@ -401,7 +399,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
None => return,
};
let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
format!("{}({})", name, args)
let sugg = format!("({})", args);
(format!("{}{}", name, sugg), sugg)
}
Some(hir::Node::Item(hir::Item {
ident,
@ -422,7 +421,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
})
.collect::<Vec<_>>()
.join(", ");
format!("{}({})", ident, args)
let sugg = format!("({})", args);
(format!("{}{}", ident, sugg), sugg)
}
_ => return,
};
@ -431,10 +431,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// an argument, the `obligation.cause.span` points at the expression
// of the argument, so we can provide a suggestion. This is signaled
// by `points_at_arg`. Otherwise, we give a more general note.
err.span_suggestion(
obligation.cause.span,
err.span_suggestion_verbose(
obligation.cause.span.shrink_to_hi(),
&msg,
snippet,
sugg,
Applicability::HasPlaceholders,
);
} else {
@ -619,7 +619,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
.source_map()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
err.span_suggestion(
err.span_suggestion_verbose(
sp,
"consider changing this borrow's mutability",
"&mut ".to_string(),

View file

@ -445,8 +445,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}
}
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
match self.selcx.infcx().closure_kind(closure_def_id, closure_substs) {
ty::Predicate::ClosureKind(_, closure_substs, kind) => {
match self.selcx.infcx().closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
ProcessResult::Changed(vec![])

View file

@ -1237,7 +1237,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
let gen_sig = vtable.substs.as_generator().poly_sig();
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,
@ -1310,8 +1310,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
let tcx = selcx.tcx();
let closure_sig = vtable.substs.as_closure().sig(vtable.closure_def_id, tcx);
let closure_sig = vtable.substs.as_closure().sig();
let Normalized { value: closure_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,

View file

@ -109,8 +109,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
// (T1..Tn) and closures have same properties as T1..Tn --
// check if *any* of those are trivial.
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
ty::Closure(def_id, ref substs) => {
substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
ty::Closure(_, ref substs) => {
substs.as_closure().upvar_tys().all(|t| trivial_dropck_outlives(tcx, t))
}
ty::Adt(def, _) => {

View file

@ -478,8 +478,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
match self.infcx.closure_kind(closure_def_id, closure_substs) {
ty::Predicate::ClosureKind(_, closure_substs, kind) => {
match self.infcx.closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
Ok(EvaluatedToOk)
@ -1600,9 +1600,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// touch bound regions, they just capture the in-scope
// type/region parameters
match obligation.self_ty().skip_binder().kind {
ty::Closure(closure_def_id, closure_substs) => {
ty::Closure(_, closure_substs) => {
debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation);
match self.infcx.closure_kind(closure_def_id, closure_substs) {
match self.infcx.closure_kind(closure_substs) {
Some(closure_kind) => {
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
if closure_kind.extends(kind) {
@ -2234,9 +2234,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
}
ty::Closure(def_id, substs) => {
ty::Closure(_, substs) => {
// (*) binder moved here
Where(ty::Binder::bind(substs.as_closure().upvar_tys(def_id, self.tcx()).collect()))
Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect()))
}
ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
@ -2313,17 +2313,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
tys.iter().map(|k| k.expect_ty()).collect()
}
ty::Closure(def_id, ref substs) => {
substs.as_closure().upvar_tys(def_id, self.tcx()).collect()
}
ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().collect(),
ty::Generator(def_id, ref substs, _) => {
let witness = substs.as_generator().witness(def_id, self.tcx());
substs
.as_generator()
.upvar_tys(def_id, self.tcx())
.chain(iter::once(witness))
.collect()
ty::Generator(_, ref substs, _) => {
let witness = substs.as_generator().witness();
substs.as_generator().upvar_tys().chain(iter::once(witness)).collect()
}
ty::GeneratorWitness(types) => {
@ -2811,7 +2805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs);
let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs);
let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
self,
obligation.param_env,
@ -2856,7 +2850,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("closure candidate for non-closure {:?}", obligation),
};
let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
self,
obligation.param_env,
@ -3338,14 +3332,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn closure_trait_ref_unnormalized(
&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: DefId,
substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
debug!(
"closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
obligation, closure_def_id, substs,
);
let closure_sig = substs.as_closure().sig(closure_def_id, self.tcx());
debug!("closure_trait_ref_unnormalized(obligation={:?}, substs={:?})", obligation, substs);
let closure_sig = substs.as_closure().sig();
debug!("closure_trait_ref_unnormalized: closure_sig = {:?}", closure_sig);
@ -3367,10 +3357,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn generator_trait_ref_unnormalized(
&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: DefId,
substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx());
let gen_sig = substs.as_generator().poly_sig();
// (1) Feels icky to skip the binder here, but OTOH we know
// that the self-type is an generator type and hence is

View file

@ -474,7 +474,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// generators don't take arguments.
}
ty::Closure(def_id, substs) => {
ty::Closure(_, substs) => {
// Only check the upvar types for WF, not the rest
// of the types within. This is needed because we
// capture the signature and it may not be WF
@ -505,7 +505,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// anyway, except via auto trait matching (which
// only inspects the upvar types).
subtys.skip_current_subtree(); // subtree handled by compute_projection
for upvar_ty in substs.as_closure().upvar_tys(def_id, self.infcx.tcx) {
for upvar_ty in substs.as_closure().upvar_tys() {
self.compute(upvar_ty);
}
}

View file

@ -207,13 +207,13 @@ fn dtorck_constraint_for_ty<'tcx>(
}
}
ty::Closure(def_id, substs) => {
for ty in substs.as_closure().upvar_tys(def_id, tcx) {
ty::Closure(_, substs) => {
for ty in substs.as_closure().upvar_tys() {
dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?;
}
}
ty::Generator(def_id, substs, _movability) => {
ty::Generator(_, substs, _movability) => {
// rust-lang/rust#49918: types can be constructed, stored
// in the interior, and sit idle when generator yields
// (and is subsequently dropped).
@ -240,10 +240,10 @@ fn dtorck_constraint_for_ty<'tcx>(
constraints.outlives.extend(
substs
.as_generator()
.upvar_tys(def_id, tcx)
.upvar_tys()
.map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
);
constraints.outlives.push(substs.as_generator().resume_ty(def_id, tcx).into());
constraints.outlives.push(substs.as_generator().resume_ty().into());
}
ty::Adt(def, substs) => {

View file

@ -93,8 +93,8 @@ where
match component.kind {
_ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (),
ty::Closure(def_id, substs) => {
for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) {
ty::Closure(_, substs) => {
for upvar_ty in substs.as_closure().upvar_tys() {
queue_type(self, upvar_ty);
}
}

View file

@ -1452,8 +1452,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.expect("missing associated type");
if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
let msg = format!("associated type `{}` is private", binding.item_name);
tcx.sess.span_err(binding.span, &msg);
tcx.sess
.struct_span_err(
binding.span,
&format!("associated type `{}` is private", binding.item_name),
)
.span_label(binding.span, "private associated type")
.emit();
}
tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span);
@ -2315,8 +2320,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let kind = DefKind::AssocTy;
if !item.vis.is_accessible_from(def_scope, tcx) {
let msg = format!("{} `{}` is private", kind.descr(item.def_id), assoc_ident);
tcx.sess.span_err(span, &msg);
let kind = kind.descr(item.def_id);
let msg = format!("{} `{}` is private", kind, assoc_ident);
tcx.sess
.struct_span_err(span, &msg)
.span_label(span, &format!("private {}", kind))
.emit();
}
tcx.check_stability(item.def_id, Some(hir_ref_id), span);

View file

@ -104,8 +104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check whether this is a call to a closure where we
// haven't yet decided on whether the closure is fn vs
// fnmut vs fnonce. If so, we have to defer further processing.
if self.closure_kind(def_id, substs).is_none() {
let closure_sig = substs.as_closure().sig(def_id, self.tcx);
if self.closure_kind(substs).is_none() {
let closure_sig = substs.as_closure().sig();
let closure_sig = self
.replace_bound_vars_with_fresh_vars(
call_expr.span,
@ -122,7 +122,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
adjusted_ty,
adjustments,
fn_sig: closure_sig,
closure_def_id: def_id,
closure_substs: substs,
},
);
@ -459,7 +458,6 @@ pub struct DeferredCallResolution<'tcx> {
adjusted_ty: Ty<'tcx>,
adjustments: Vec<Adjustment<'tcx>>,
fn_sig: ty::FnSig<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
}
@ -469,7 +467,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
// we should not be invoked until the closure kind has been
// determined by upvar inference
assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
assert!(fcx.closure_kind(self.closure_substs).is_some());
// We may now know enough to figure out fn vs fnmut etc.
match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) {

View file

@ -77,45 +77,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let generator_types =
check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1;
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
let base_substs =
InternalSubsts::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
// HACK(eddyb) this hardcodes indices into substs but it should rely on
// `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead.
// That would also remove the need for most of the inference variables,
// as they immediately unified with the actual type below, including
// the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods.
let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 };
let substs = base_substs.extend_to(self.tcx, expr_def_id, |param, _| match param.kind {
GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"),
GenericParamDefKind::Type { .. } => self
.infcx
.next_ty_var(TypeVariableOrigin {
GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx {
self.tcx.mk_tup(self.tcx.upvars(expr_def_id).iter().flat_map(|upvars| {
upvars.iter().map(|(&var_hir_id, _)| {
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
self.infcx.next_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish upvar inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.hir().span(var_hir_id),
})
})
}))
} else {
// Create type variables (for now) to represent the various
// pieces of information kept in `{Closure,Generic}Substs`.
// They will either be unified below, or later during the upvar
// inference phase (`upvar.rs`)
self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr.span,
})
.into(),
}
.into(),
GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
});
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
let generator_substs = substs.as_generator();
self.demand_eqtype(
expr.span,
resume_ty,
generator_substs.resume_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(
expr.span,
yield_ty,
generator_substs.yield_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(
expr.span,
liberated_sig.output(),
generator_substs.return_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(
expr.span,
interior,
generator_substs.witness(expr_def_id, self.tcx),
);
self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty());
self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty());
self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty());
self.demand_eqtype(expr.span, interior, generator_substs.witness());
// HACK(eddyb) this forces the types equated above into `substs` but
// it should rely on `GeneratorSubsts` providing a constructor, instead.
@ -142,18 +146,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
self.demand_eqtype(
expr.span,
sig_fn_ptr_ty,
substs.as_closure().sig_as_fn_ptr_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty());
if let Some(kind) = opt_kind {
self.demand_eqtype(
expr.span,
kind.to_ty(self.tcx),
substs.as_closure().kind_ty(expr_def_id, self.tcx),
);
self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty());
}
// HACK(eddyb) this forces the types equated above into `substs` but

View file

@ -62,7 +62,6 @@ use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TypeAndMut};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, InferOk, InferResult};
use rustc_session::parse::feature_err;
@ -236,11 +235,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
ty::Closure(def_id_a, substs_a) => {
ty::Closure(_, substs_a) => {
// Non-capturing closures are coercible to
// function pointers or unsafe function pointers.
// It cannot convert closures that require unsafe.
self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
self.coerce_closure_to_fn(a, substs_a, b)
}
_ => {
// Otherwise, just use unification rules.
@ -732,7 +731,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
fn coerce_closure_to_fn(
&self,
a: Ty<'tcx>,
def_id_a: DefId,
substs_a: SubstsRef<'tcx>,
b: Ty<'tcx>,
) -> CoerceResult<'tcx> {
@ -743,14 +741,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let b = self.shallow_resolve(b);
match b.kind {
ty::FnPtr(fn_ty) if self.tcx.upvars(def_id_a).map_or(true, |v| v.is_empty()) => {
ty::FnPtr(fn_ty) if substs_a.as_closure().upvar_tys().next().is_none() => {
// We coerce the closure, which has fn type
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
// to
// `fn(arg0,arg1,...) -> _`
// or
// `unsafe fn(arg0,arg1,...) -> _`
let closure_sig = substs_a.as_closure().sig(def_id_a, self.tcx);
let closure_sig = substs_a.as_closure().sig();
let unsafety = fn_ty.unsafety();
let pointer_ty = self.tcx.coerce_closure_fn_ty(closure_sig, unsafety);
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);

View file

@ -1580,13 +1580,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let mut err = struct_span_err!(
self.tcx().sess,
expr.span,
field.span,
E0616,
"field `{}` of {} `{}` is private",
field,
kind_name,
struct_path
);
err.span_label(field.span, "private field");
// Also check if an accessible method exists, which is often what is meant.
if self.method_exists(field, expr_t, expr.hir_id, false) && !self.expr_in_place(expr.hir_id)
{
@ -1611,7 +1612,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field,
expr_t
);
err.span_label(field.span, "method, not a field");
if !self.expr_in_place(expr.hir_id) {
self.suggest_method_call(
&mut err,

View file

@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty: Ty<'tcx>,
call_expr: &hir::Expr<'_>,
) {
let has_params = self
let params = self
.probe_for_name(
method_name.span,
probe::Mode::MethodCall,
@ -147,26 +147,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_expr.hir_id,
ProbeScope::TraitsInScope,
)
.and_then(|pick| {
.map(|pick| {
let sig = self.tcx.fn_sig(pick.item.def_id);
Ok(sig.inputs().skip_binder().len() > 1)
});
sig.inputs().skip_binder().len().saturating_sub(1)
})
.unwrap_or(0);
// Account for `foo.bar<T>`;
let sugg_span = method_name.span.with_hi(call_expr.span.hi());
let snippet = self
.tcx
.sess
.source_map()
.span_to_snippet(sugg_span)
.unwrap_or_else(|_| method_name.to_string());
let (suggestion, applicability) = if has_params.unwrap_or_default() {
(format!("{}(...)", snippet), Applicability::HasPlaceholders)
} else {
(format!("{}()", snippet), Applicability::MaybeIncorrect)
};
let sugg_span = call_expr.span.shrink_to_hi();
let (suggestion, applicability) = (
format!("({})", (0..params).map(|_| "_").collect::<Vec<_>>().join(", ")),
if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect },
);
err.span_suggestion(sugg_span, msg, suggestion, applicability);
err.span_suggestion_verbose(sugg_span, msg, suggestion, applicability);
}
/// Performs method lookup. If lookup is successful, it will return the callee

View file

@ -758,25 +758,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
MethodError::Ambiguity(sources) => {
let mut err = struct_span_err!(
self.sess(),
span,
item_name.span,
E0034,
"multiple applicable items in scope"
);
err.span_label(span, format!("multiple `{}` found", item_name));
err.span_label(item_name.span, format!("multiple `{}` found", item_name));
report_candidates(span, &mut err, sources, sugg_span);
err.emit();
}
MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
let kind = kind.descr(def_id);
let mut err = struct_span_err!(
self.tcx.sess,
span,
item_name.span,
E0624,
"{} `{}` is private",
kind.descr(def_id),
kind,
item_name
);
err.span_label(item_name.span, &format!("private {}", kind));
self.suggest_valid_traits(&mut err, out_of_scope_traits);
err.emit();
}

View file

@ -4831,7 +4831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir = self.tcx.hir();
let (def_id, sig) = match found.kind {
ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)),
ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig(def_id, self.tcx)),
ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig()),
_ => return false,
};
@ -4939,15 +4939,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => {}
}
if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) {
err.span_suggestion(
expr.span,
&format!("use parentheses to {}", msg),
format!("{}({})", code, sugg_call),
applicability,
);
return true;
}
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
&format!("use parentheses to {}", msg),
format!("({})", sugg_call),
applicability,
);
return true;
}
false
}

View file

@ -753,17 +753,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
res.descr(),
),
);
let (msg, sugg) = match parent_pat {
Some(Pat { kind: hir::PatKind::Struct(..), .. }) => (
"bind the struct field to a different name instead",
format!("{}: other_{}", ident, ident.as_str().to_lowercase()),
),
_ => (
"introduce a new binding instead",
format!("other_{}", ident.as_str().to_lowercase()),
),
match parent_pat {
Some(Pat { kind: hir::PatKind::Struct(..), .. }) => {
e.span_suggestion_verbose(
ident.span.shrink_to_hi(),
"bind the struct field to a different name instead",
format!(": other_{}", ident.as_str().to_lowercase()),
Applicability::HasPlaceholders,
);
}
_ => {
let msg = "introduce a new binding instead";
let sugg = format!("other_{}", ident.as_str().to_lowercase());
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
}
};
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
}
}
e.emit();

View file

@ -1228,8 +1228,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
// A closure capture can't be borrowed for longer than the
// reference to the closure.
if let ty::Closure(closure_def_id, substs) = ty.kind {
match self.infcx.closure_kind(closure_def_id, substs) {
if let ty::Closure(_, substs) = ty.kind {
match self.infcx.closure_kind(substs) {
Some(ty::ClosureKind::Fn) | Some(ty::ClosureKind::FnMut) => {
// Region of environment pointer
let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {

View file

@ -107,7 +107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
self.closure_kind(closure_def_id, closure_substs).is_none().then_some(closure_substs)
self.closure_kind(closure_substs).is_none().then_some(closure_substs)
} else {
None
};
@ -168,7 +168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Unify the (as yet unbound) type variable in the closure
// substs with the kind we inferred.
let inferred_kind = delegate.current_closure_kind;
let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
// If we have an origin, store it.
@ -197,9 +197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
closure_hir_id, substs, final_upvar_tys
);
for (upvar_ty, final_upvar_ty) in
substs.upvar_tys(closure_def_id, self.tcx).zip(final_upvar_tys)
{
for (upvar_ty, final_upvar_ty) in substs.upvar_tys().zip(final_upvar_tys) {
self.demand_suptype(span, upvar_ty, final_upvar_ty);
}

View file

@ -1374,9 +1374,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
// and we don't do that for closures.
if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node {
let dummy_args = if gen.is_some() {
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>"][..]
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
} else {
&["<closure_kind>", "<closure_signature>"][..]
&["<closure_kind>", "<closure_signature>", "<upvars>"][..]
};
params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef {
@ -1390,22 +1390,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
synthetic: None,
},
}));
if let Some(upvars) = tcx.upvars(def_id) {
params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
ty::GenericParamDef {
index: type_start + i,
name: Symbol::intern("<upvar>"),
def_id,
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
object_lifetime_default: rl::Set1::Empty,
synthetic: None,
},
}
}));
}
}
let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();

View file

@ -1,8 +1,8 @@
error[E0034]: multiple applicable items in scope
--> $DIR/associated-const-ambiguity-report.rs:17:16
--> $DIR/associated-const-ambiguity-report.rs:17:23
|
LL | const X: i32 = <i32>::ID;
| ^^^^^^^^^ multiple `ID` found
| ^^ multiple `ID` found
|
note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32`
--> $DIR/associated-const-ambiguity-report.rs:10:5

View file

@ -1,8 +1,8 @@
error[E0624]: associated constant `ID` is private
--> $DIR/associated-const-private-impl.rs:13:19
--> $DIR/associated-const-private-impl.rs:13:30
|
LL | assert_eq!(1, bar1::Foo::ID);
| ^^^^^^^^^^^^^
| ^^ private associated constant
error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0034]: multiple applicable items in scope
--> $DIR/E0034.rs:20:5
--> $DIR/E0034.rs:20:11
|
LL | Test::foo()
| ^^^^^^^^^ multiple `foo` found
| ^^^ multiple `foo` found
|
note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Test`
--> $DIR/E0034.rs:12:5

View file

@ -2,13 +2,13 @@ error[E0451]: field `b` of struct `bar::Foo` is private
--> $DIR/E0451.rs:14:21
|
LL | let bar::Foo{a, b} = foo;
| ^ field `b` is private
| ^ private field
error[E0451]: field `b` of struct `bar::Foo` is private
--> $DIR/E0451.rs:18:29
|
LL | let f = bar::Foo{ a: 0, b: 0 };
| ^^^^ field `b` is private
| ^^^^ private field
error: aborting due to 2 previous errors

View file

@ -2,7 +2,7 @@ error[E0603]: constant `PRIVATE` is private
--> $DIR/E0603.rs:6:17
|
LL | SomeModule::PRIVATE;
| ^^^^^^^ this constant is private
| ^^^^^^^ private constant
|
note: the constant `PRIVATE` is defined here
--> $DIR/E0603.rs:2:5

View file

@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `method` on type `Foo`
--> $DIR/E0615.rs:11:7
|
LL | f.method;
| ^^^^^^ help: use parentheses to call the method: `method()`
| ^^^^^^ method, not a field
|
help: use parentheses to call the method
|
LL | f.method();
| ^^
error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0616]: field `x` of struct `a::Foo` is private
--> $DIR/E0616.rs:13:5
--> $DIR/E0616.rs:13:7
|
LL | f.x;
| ^^^
| ^ private field
error: aborting due to previous error

View file

@ -2,7 +2,7 @@ error[E0624]: associated function `method` is private
--> $DIR/E0624.rs:11:9
|
LL | foo.method();
| ^^^^^^
| ^^^^^^ private associated function
error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0616]: field `0` of struct `a::Foo` is private
--> $DIR/ex-E0611.rs:11:4
--> $DIR/ex-E0611.rs:11:6
|
LL | y.0;
| ^^^
| ^ private field
error: aborting due to previous error

View file

@ -8,7 +8,7 @@ error[E0603]: constant `FOO` is private
--> $DIR/error-festival.rs:22:10
|
LL | foo::FOO;
| ^^^ this constant is private
| ^^^ private constant
|
note: the constant `FOO` is defined here
--> $DIR/error-festival.rs:7:5

View file

@ -17,22 +17,22 @@ LL | r.a_unstable_undeclared_pub;
= help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
error[E0616]: field `b_crate` of struct `pub_and_stability::Record` is private
--> $DIR/explore-issue-38412.rs:31:5
--> $DIR/explore-issue-38412.rs:31:7
|
LL | r.b_crate;
| ^^^^^^^^^
| ^^^^^^^ private field
error[E0616]: field `c_mod` of struct `pub_and_stability::Record` is private
--> $DIR/explore-issue-38412.rs:32:5
--> $DIR/explore-issue-38412.rs:32:7
|
LL | r.c_mod;
| ^^^^^^^
| ^^^^^ private field
error[E0616]: field `d_priv` of struct `pub_and_stability::Record` is private
--> $DIR/explore-issue-38412.rs:33:5
--> $DIR/explore-issue-38412.rs:33:7
|
LL | r.d_priv;
| ^^^^^^^^
| ^^^^^^ private field
error[E0658]: use of unstable library feature 'unstable_undeclared'
--> $DIR/explore-issue-38412.rs:37:5
@ -44,22 +44,22 @@ LL | t.2;
= help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private
--> $DIR/explore-issue-38412.rs:38:5
--> $DIR/explore-issue-38412.rs:38:7
|
LL | t.3;
| ^^^
| ^ private field
error[E0616]: field `4` of struct `pub_and_stability::Tuple` is private
--> $DIR/explore-issue-38412.rs:39:5
--> $DIR/explore-issue-38412.rs:39:7
|
LL | t.4;
| ^^^
| ^ private field
error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private
--> $DIR/explore-issue-38412.rs:40:5
--> $DIR/explore-issue-38412.rs:40:7
|
LL | t.5;
| ^^^
| ^ private field
error[E0658]: use of unstable library feature 'unstable_undeclared'
--> $DIR/explore-issue-38412.rs:44:7
@ -83,19 +83,19 @@ error[E0624]: associated function `pub_crate` is private
--> $DIR/explore-issue-38412.rs:50:7
|
LL | r.pub_crate();
| ^^^^^^^^^
| ^^^^^^^^^ private associated function
error[E0624]: associated function `pub_mod` is private
--> $DIR/explore-issue-38412.rs:51:7
|
LL | r.pub_mod();
| ^^^^^^^
| ^^^^^^^ private associated function
error[E0624]: associated function `private` is private
--> $DIR/explore-issue-38412.rs:52:7
|
LL | r.private();
| ^^^^^^^
| ^^^^^^^ private associated function
error[E0658]: use of unstable library feature 'unstable_undeclared'
--> $DIR/explore-issue-38412.rs:57:7
@ -119,19 +119,19 @@ error[E0624]: associated function `pub_crate` is private
--> $DIR/explore-issue-38412.rs:63:7
|
LL | t.pub_crate();
| ^^^^^^^^^
| ^^^^^^^^^ private associated function
error[E0624]: associated function `pub_mod` is private
--> $DIR/explore-issue-38412.rs:64:7
|
LL | t.pub_mod();
| ^^^^^^^
| ^^^^^^^ private associated function
error[E0624]: associated function `private` is private
--> $DIR/explore-issue-38412.rs:65:7
|
LL | t.private();
| ^^^^^^^
| ^^^^^^^ private associated function
error: aborting due to 19 previous errors

View file

@ -2,7 +2,7 @@ error[E0603]: function `unexported` is private
--> $DIR/export-import.rs:1:8
|
LL | use m::unexported;
| ^^^^^^^^^^ this function is private
| ^^^^^^^^^^ private function
|
note: the function `unexported` is defined here
--> $DIR/export-import.rs:7:5

View file

@ -2,7 +2,7 @@ error[E0603]: enum `Y` is private
--> $DIR/export-tag-variant.rs:7:26
|
LL | fn main() { let z = foo::Y::Y1; }
| ^ this enum is private
| ^ private enum
|
note: the enum `Y` is defined here
--> $DIR/export-tag-variant.rs:4:5

View file

@ -26,7 +26,7 @@ error[E0603]: function `z` is private
--> $DIR/export.rs:10:18
|
LL | fn main() { foo::z(10); }
| ^ this function is private
| ^ private function
|
note: the function `z` is defined here
--> $DIR/export.rs:5:5

View file

@ -2,7 +2,7 @@ error[E0603]: crate import `core` is private
--> $DIR/extern-crate-visibility.rs:6:10
|
LL | use foo::core::cell;
| ^^^^ this crate import is private
| ^^^^ private crate import
|
note: the crate import `core` is defined here
--> $DIR/extern-crate-visibility.rs:2:5
@ -14,7 +14,7 @@ error[E0603]: crate import `core` is private
--> $DIR/extern-crate-visibility.rs:9:10
|
LL | foo::core::cell::Cell::new(0);
| ^^^^ this crate import is private
| ^^^^ private crate import
|
note: the crate import `core` is defined here
--> $DIR/extern-crate-visibility.rs:2:5

View file

@ -2,15 +2,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
--> $DIR/extern-types-unsized.rs:22:20
|
LL | fn assert_sized<T>() { }
| ------------ -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized`
| |
| required by this bound in `assert_sized`
| ------------ - required by this bound in `assert_sized`
...
LL | assert_sized::<A>();
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `A`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() { }
| ^^^^^^^^
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:25:5

View file

@ -2,7 +2,7 @@ error[E0451]: field `secret_uid` of struct `foo::S` is private
--> $DIR/functional-struct-update-respects-privacy.rs:28:49
|
LL | let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ...
| ^^^ field `secret_uid` is private
| ^^^ private field
error: aborting due to previous error

View file

@ -2,7 +2,7 @@ error: type `foo::S` is private
--> $DIR/fields.rs:15:17
|
LL | let s = S { x: 0 };
| ^^^^^^^^^^
| ^^^^^^^^^^ private type
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
@ -13,7 +13,7 @@ error: type `foo::S` is private
--> $DIR/fields.rs:16:17
|
LL | let _ = s.x;
| ^
| ^ private type
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
@ -24,7 +24,7 @@ error: type `foo::T` is private
--> $DIR/fields.rs:18:17
|
LL | let t = T(0);
| ^^^^
| ^^^^ private type
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation
@ -35,7 +35,7 @@ error: type `foo::T` is private
--> $DIR/fields.rs:19:17
|
LL | let _ = t.0;
| ^
| ^ private type
...
LL | let s = foo::m!(S, x);
| ------------- in this macro invocation

View file

@ -2,7 +2,7 @@ error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
--> $DIR/impl_items.rs:12:23
|
LL | let _: () = S.f();
| ^
| ^ private type
...
LL | foo::m!();
| ---------- in this macro invocation

View file

@ -2,7 +2,7 @@ error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
--> $DIR/intercrate.rs:10:16
|
LL | assert_eq!(intercrate::foo::m!(), 1);
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^ private type
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,8 +1,8 @@
error[E0616]: field `i` of struct `foo::S` is private
--> $DIR/nested_macro_privacy.rs:15:5
--> $DIR/nested_macro_privacy.rs:15:18
|
LL | S::default().i;
| ^^^^^^^^^^^^^^
| ^ private field
error: aborting due to previous error

View file

@ -2,7 +2,7 @@ error[E0603]: function `f` is private
--> $DIR/privacy.rs:16:14
|
LL | foo::f()
| ^ this function is private
| ^ private function
|
note: the function `f` is defined here
--> $DIR/privacy.rs:4:5

View file

@ -8,13 +8,23 @@ error[E0423]: expected value, found macro `semitransparent`
--> $DIR/rustc-macro-transparency.rs:29:5
|
LL | semitransparent;
| ^^^^^^^^^^^^^^^ help: use `!` to invoke the macro: `semitransparent!`
| ^^^^^^^^^^^^^^^
|
help: use `!` to invoke the macro
|
LL | semitransparent!;
| ^
error[E0423]: expected value, found macro `opaque`
--> $DIR/rustc-macro-transparency.rs:30:5
|
LL | opaque;
| ^^^^^^ help: use `!` to invoke the macro: `opaque!`
| ^^^^^^
|
help: use `!` to invoke the macro
|
LL | opaque!;
| ^
error: aborting due to 3 previous errors

View file

@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `abs` on type `i32`
--> $DIR/implicit-method-bind.rs:2:20
|
LL | let _f = 10i32.abs;
| ^^^ help: use parentheses to call the method: `abs()`
| ^^^ method, not a field
|
help: use parentheses to call the method
|
LL | let _f = 10i32.abs();
| ^^
error: aborting due to previous error

View file

@ -17,7 +17,7 @@ error[E0603]: unresolved item import `foo` is private
--> $DIR/import.rs:15:10
|
LL | zed::foo();
| ^^^ this unresolved item import is private
| ^^^ private unresolved item import
|
note: the unresolved item import `foo` is defined here
--> $DIR/import.rs:10:9

View file

@ -2,7 +2,7 @@ error[E0603]: struct import `ParseOptions` is private
--> $DIR/issue-55884-2.rs:12:17
|
LL | pub use parser::ParseOptions;
| ^^^^^^^^^^^^ this struct import is private
| ^^^^^^^^^^^^ private struct import
|
note: the struct import `ParseOptions` is defined here...
--> $DIR/issue-55884-2.rs:9:9

View file

@ -14,7 +14,7 @@ error[E0603]: module import `foo` is private
--> $DIR/reexports.rs:33:15
|
LL | use b::a::foo::S;
| ^^^ this module import is private
| ^^^ private module import
|
note: the module import `foo` is defined here...
--> $DIR/reexports.rs:21:17
@ -31,7 +31,7 @@ error[E0603]: module import `foo` is private
--> $DIR/reexports.rs:34:15
|
LL | use b::b::foo::S as T;
| ^^^ this module import is private
| ^^^ private module import
|
note: the module import `foo` is defined here...
--> $DIR/reexports.rs:26:17

View file

@ -38,7 +38,7 @@ error[E0603]: function `quz` is private
--> $DIR/unresolved-imports-used.rs:9:10
|
LL | use qux::quz;
| ^^^ this function is private
| ^^^ private function
|
note: the function `quz` is defined here
--> $DIR/unresolved-imports-used.rs:5:4

View file

@ -2,7 +2,7 @@ error[E0603]: struct `S` is private
--> $DIR/issue-10545.rs:6:14
|
LL | fn foo(_: a::S) {
| ^ this struct is private
| ^ private struct
|
note: the struct `S` is defined here
--> $DIR/issue-10545.rs:2:5

View file

@ -2,7 +2,7 @@ error[E0603]: trait `Foo` is private
--> $DIR/issue-11593.rs:7:24
|
LL | impl private_trait_xc::Foo for Bar {}
| ^^^ this trait is private
| ^^^ private trait
|
note: the trait `Foo` is defined here
--> $DIR/auxiliary/private-trait-xc.rs:1:1

View file

@ -2,7 +2,7 @@ error[E0603]: enum `Foo` is private
--> $DIR/issue-11680.rs:6:21
|
LL | let _b = other::Foo::Bar(1);
| ^^^ this enum is private
| ^^^ private enum
|
note: the enum `Foo` is defined here
--> $DIR/auxiliary/issue-11680.rs:1:1
@ -14,7 +14,7 @@ error[E0603]: enum `Foo` is private
--> $DIR/issue-11680.rs:9:27
|
LL | let _b = other::test::Foo::Bar(1);
| ^^^ this enum is private
| ^^^ private enum
|
note: the enum `Foo` is defined here
--> $DIR/auxiliary/issue-11680.rs:6:5

View file

@ -2,7 +2,7 @@ error[E0603]: unit struct `C` is private
--> $DIR/issue-13407.rs:6:8
|
LL | A::C = 1;
| ^ this unit struct is private
| ^ private unit struct
|
note: the unit struct `C` is defined here
--> $DIR/issue-13407.rs:2:5

View file

@ -2,7 +2,7 @@ error[E0603]: struct `Foo` is private
--> $DIR/issue-13641.rs:9:8
|
LL | a::Foo::new();
| ^^^ this struct is private
| ^^^ private struct
|
note: the struct `Foo` is defined here
--> $DIR/issue-13641.rs:2:5
@ -14,7 +14,7 @@ error[E0603]: enum `Bar` is private
--> $DIR/issue-13641.rs:11:8
|
LL | a::Bar::new();
| ^^^ this enum is private
| ^^^ private enum
|
note: the enum `Bar` is defined here
--> $DIR/issue-13641.rs:4:5

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