Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[beta] backport rollup #103739

Merged
merged 19 commits into from
Oct 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
244 changes: 244 additions & 0 deletions RELEASES.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_lib_name: &str,
_dll_imports: &[rustc_session::cstore::DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
bug!("creating dll imports is not supported");
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_lib_name: &str,
_dll_imports: &[DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
unimplemented!();
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
is_direct_dependency: bool,
) -> PathBuf {
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
let output_path = {
let mut output_path: PathBuf = tmpdir.to_path_buf();
output_path.push(format!("{}_imports", lib_name));
output_path.push(format!("{}{}", lib_name, name_suffix));
output_path.with_extension("lib")
};

Expand All @@ -134,7 +136,8 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
// that loaded but crashed with an AV upon calling one of the imported
// functions. Therefore, use binutils to create the import library instead,
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
let def_file_path = tmpdir.join(format!("{}_imports", lib_name)).with_extension("def");
let def_file_path =
tmpdir.join(format!("{}{}", lib_name, name_suffix)).with_extension("def");

let def_file_content = format!(
"EXPORTS\n{}",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub trait ArchiveBuilderBuilder {
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
is_direct_dependency: bool,
) -> PathBuf;

fn extract_bundled_libs(
Expand Down
41 changes: 36 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,14 @@ fn link_rlib<'a>(
}

for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
{
let output_path = archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir.as_ref(),
true,
);

ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| {
Expand Down Expand Up @@ -434,9 +435,9 @@ fn link_rlib<'a>(
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
/// linker appears to expect only a single import library for each library used, so we need to
/// collate the symbols together by library name before generating the import libraries.
fn collate_raw_dylibs(
sess: &Session,
used_libraries: &[NativeLib],
fn collate_raw_dylibs<'a, 'b>(
sess: &'a Session,
used_libraries: impl IntoIterator<Item = &'b NativeLib>,
) -> Result<Vec<(String, Vec<DllImport>)>, ErrorGuaranteed> {
// Use index maps to preserve original order of imports and libraries.
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
Expand Down Expand Up @@ -2028,13 +2029,43 @@ fn linker_with_args<'a>(

// Link with the import library generated for any raw-dylib functions.
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
{
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir,
true,
));
}
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
// they are used within inlined functions or instantiated generic functions. We do this *after*
// handling the raw-dylib symbols in the current crate to make sure that those are chosen first
// by the linker.
let (_, dependency_linkage) = codegen_results
.crate_info
.dependency_formats
.iter()
.find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list");
let native_libraries_from_nonstatics = codegen_results
.crate_info
.native_libraries
.iter()
.filter_map(|(cnum, libraries)| {
(dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries)
})
.flatten();
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
{
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir,
false,
));
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
"riscv32" => Architecture::Riscv32,
"riscv64" => Architecture::Riscv64,
"sparc64" => Architecture::Sparc64,
"avr" => Architecture::Avr,
"msp430" => Architecture::Msp430,
"hexagon" => Architecture::Hexagon,
"bpf" => Architecture::Bpf,
// Unsupported architecture.
_ => return None,
};
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
val: &mir::ConstantKind<'tcx>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
// FIXME(const_prop): normalization needed b/c const prop lint in
// `mir_drops_elaborated_and_const_checked`, which happens before
// optimized MIR. Only after optimizing the MIR can we guarantee
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
match val {
mir::ConstantKind::Ty(ct) => self.const_to_op(*ct, layout),
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout),
mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout),
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => {
let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ where
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),

(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
infcx.super_combine_tys(self, a, b).or_else(|err| {
self.tcx().sess.delay_span_bug(
self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on",
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2489,7 +2489,9 @@ impl<'tcx> TyCtxt<'tcx> {
&& if self.features().collapse_debuginfo {
span.in_macro_expansion_with_collapse_debuginfo()
} else {
span.from_expansion()
// Inlined spans should not be collapsed as that leads to all of the
// inlined code being attributed to the inline callsite.
span.from_expansion() && !span.is_inlined()
}
}

Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
/// it.
pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::Const<'tcx>,
b: ty::Const<'tcx>,
mut a: ty::Const<'tcx>,
mut b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
Expand All @@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
);
}

// HACK(const_generics): We still need to eagerly evaluate consts when
// relating them because during `normalize_param_env_or_error`,
// we may relate an evaluated constant in a obligation against
// an unnormalized (i.e. unevaluated) const in the param-env.
// FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
// these `eval` calls can be removed.
if !relation.tcx().features().generic_const_exprs {
a = a.eval(tcx, relation.param_env());
b = b.eval(tcx, relation.param_env());
}

// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// Use `Reveal::All` here because patterns are always monomorphic even if their function
// isn't.
let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
let substs = self.typeck_results.node_substs(id);
// N.B. There is no guarantee that substs collected in typeck results are fully normalized,
// so they need to be normalized in order to pass to `Instance::resolve`, which will ICE
// if given unnormalized types.
let substs = self
.tcx
.normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id));
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
Ok(Some(i)) => i,
Ok(None) => {
Expand Down
103 changes: 69 additions & 34 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use rustc_span::{BytePos, Span};
use smallvec::{smallvec, SmallVec};

use rustc_span::source_map::{respan, Spanned};
use std::assert_matches::debug_assert_matches;
use std::collections::{hash_map::Entry, BTreeSet};
use std::mem::{replace, take};

Expand Down Expand Up @@ -557,7 +558,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
/// They will be used to determine the correct lifetime for the fn return type.
/// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named
/// lifetimes.
lifetime_elision_candidates: Option<FxIndexMap<LifetimeRes, LifetimeElisionCandidate>>,
lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>,

/// The trait that the current context can refer to.
current_trait_ref: Option<(Module<'a>, TraitRef)>,
Expand Down Expand Up @@ -1819,7 +1820,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
match res {
LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => {
if let Some(ref mut candidates) = self.lifetime_elision_candidates {
candidates.insert(res, candidate);
candidates.push((res, candidate));
}
}
LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
Expand Down Expand Up @@ -1872,74 +1873,108 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
has_self: bool,
inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>,
) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> {
let outer_candidates =
replace(&mut self.lifetime_elision_candidates, Some(Default::default()));
enum Elision {
/// We have not found any candidate.
None,
/// We have a candidate bound to `self`.
Self_(LifetimeRes),
/// We have a candidate bound to a parameter.
Param(LifetimeRes),
/// We failed elision.
Err,
}

let mut elision_lifetime = None;
let mut lifetime_count = 0;
// Save elision state to reinstate it later.
let outer_candidates = self.lifetime_elision_candidates.take();

// Result of elision.
let mut elision_lifetime = Elision::None;
// Information for diagnostics.
let mut parameter_info = Vec::new();
let mut all_candidates = Vec::new();

let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
for (index, (pat, ty)) in inputs.enumerate() {
debug!(?pat, ?ty);
if let Some(pat) = pat {
self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
}

// Record elision candidates only for this parameter.
debug_assert_matches!(self.lifetime_elision_candidates, None);
self.lifetime_elision_candidates = Some(Default::default());
self.visit_ty(ty);
let local_candidates = self.lifetime_elision_candidates.take();

if let Some(ref candidates) = self.lifetime_elision_candidates {
let new_count = candidates.len();
let local_count = new_count - lifetime_count;
if local_count != 0 {
if let Some(candidates) = local_candidates {
let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect();
let lifetime_count = distinct.len();
if lifetime_count != 0 {
parameter_info.push(ElisionFnParameter {
index,
ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind {
Some(ident)
} else {
None
},
lifetime_count: local_count,
lifetime_count,
span: ty.span,
});
all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| {
match candidate {
LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {
None
}
LifetimeElisionCandidate::Missing(missing) => Some(missing),
}
}));
}
let mut distinct_iter = distinct.into_iter();
if let Some(res) = distinct_iter.next() {
match elision_lifetime {
// We are the first parameter to bind lifetimes.
Elision::None => {
if distinct_iter.next().is_none() {
// We have a single lifetime => success.
elision_lifetime = Elision::Param(res)
} else {
// We have have multiple lifetimes => error.
elision_lifetime = Elision::Err;
}
}
// We have 2 parameters that bind lifetimes => error.
Elision::Param(_) => elision_lifetime = Elision::Err,
// `self` elision takes precedence over everything else.
Elision::Self_(_) | Elision::Err => {}
}
}
lifetime_count = new_count;
}

// Handle `self` specially.
if index == 0 && has_self {
let self_lifetime = self.find_lifetime_for_self(ty);
if let Set1::One(lifetime) = self_lifetime {
elision_lifetime = Some(lifetime);
self.lifetime_elision_candidates = None;
// We found `self` elision.
elision_lifetime = Elision::Self_(lifetime);
} else {
self.lifetime_elision_candidates = Some(Default::default());
lifetime_count = 0;
// We do not have `self` elision: disregard the `Elision::Param` that we may
// have found.
elision_lifetime = Elision::None;
}
}
debug!("(resolving function / closure) recorded parameter");
}

let all_candidates = replace(&mut self.lifetime_elision_candidates, outer_candidates);
debug!(?all_candidates);
// Reinstate elision state.
debug_assert_matches!(self.lifetime_elision_candidates, None);
self.lifetime_elision_candidates = outer_candidates;

if let Some(res) = elision_lifetime {
if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime {
return Ok(res);
}

// We do not have a `self` candidate, look at the full list.
let all_candidates = all_candidates.unwrap();
if all_candidates.len() == 1 {
Ok(*all_candidates.first().unwrap().0)
} else {
let all_candidates = all_candidates
.into_iter()
.filter_map(|(_, candidate)| match candidate {
LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => None,
LifetimeElisionCandidate::Missing(missing) => Some(missing),
})
.collect();
Err((all_candidates, parameter_info))
}
// We do not have a candidate.
Err((all_candidates, parameter_info))
}

/// List all the lifetimes that appear in the provided type.
Expand Down Expand Up @@ -2411,7 +2446,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Do not account for the parameters we just bound for function lifetime elision.
if let Some(ref mut candidates) = self.lifetime_elision_candidates {
for (_, res) in function_lifetime_rib.bindings.values() {
candidates.remove(res);
candidates.retain(|(r, _)| r != res);
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(if_let_guard)]
Expand Down