Skip to content

Commit 428943c

Browse files
committed
Auto merge of rust-lang#59636 - Centril:rollup, r=Centril
Rollup of 4 pull requests Successful merges: - rust-lang#59166 (resolve: collect trait aliases along with traits) - rust-lang#59341 (Fix custom relative libdir) - rust-lang#59446 (Fix stack overflow when generating debuginfo for 'recursive' type) - rust-lang#59529 (Added documentation on the remainder (Rem) operator for floating points.) Failed merges: r? @ghost
2 parents e008e4f + 21e2e98 commit 428943c

File tree

18 files changed

+377
-65
lines changed

18 files changed

+377
-65
lines changed

src/bootstrap/builder.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,28 @@ impl<'a> Builder<'a> {
634634
if compiler.is_snapshot(self) {
635635
self.rustc_snapshot_libdir()
636636
} else {
637-
self.sysroot(compiler).join(libdir(&compiler.host))
637+
match self.config.libdir_relative() {
638+
Some(relative_libdir) if compiler.stage >= 1
639+
=> self.sysroot(compiler).join(relative_libdir),
640+
_ => self.sysroot(compiler).join(libdir(&compiler.host))
641+
}
642+
}
643+
}
644+
645+
/// Returns the compiler's relative libdir where it stores the dynamic libraries that
646+
/// it itself links against.
647+
///
648+
/// For example this returns `lib` on Unix and `bin` on
649+
/// Windows.
650+
pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
651+
if compiler.is_snapshot(self) {
652+
libdir(&self.config.build).as_ref()
653+
} else {
654+
match self.config.libdir_relative() {
655+
Some(relative_libdir) if compiler.stage >= 1
656+
=> relative_libdir,
657+
_ => libdir(&compiler.host).as_ref()
658+
}
638659
}
639660
}
640661

src/bootstrap/compile.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use filetime::FileTime;
2020
use serde_json;
2121

2222
use crate::dist;
23-
use crate::util::{exe, libdir, is_dylib};
23+
use crate::util::{exe, is_dylib};
2424
use crate::{Compiler, Mode, GitRepo};
2525
use crate::native;
2626

@@ -1005,13 +1005,13 @@ impl Step for Assemble {
10051005

10061006
// Link in all dylibs to the libdir
10071007
let sysroot = builder.sysroot(target_compiler);
1008-
let sysroot_libdir = sysroot.join(libdir(&*host));
1009-
t!(fs::create_dir_all(&sysroot_libdir));
1008+
let rustc_libdir = builder.rustc_libdir(target_compiler);
1009+
t!(fs::create_dir_all(&rustc_libdir));
10101010
let src_libdir = builder.sysroot_libdir(build_compiler, host);
10111011
for f in builder.read_dir(&src_libdir) {
10121012
let filename = f.file_name().into_string().unwrap();
10131013
if is_dylib(&filename) {
1014-
builder.copy(&f.path(), &sysroot_libdir.join(&filename));
1014+
builder.copy(&f.path(), &rustc_libdir.join(&filename));
10151015
}
10161016
}
10171017

src/bootstrap/dist.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use build_helper::output;
1818

1919
use crate::{Compiler, Mode, LLVM_TOOLS};
2020
use crate::channel;
21-
use crate::util::{libdir, is_dylib, exe};
21+
use crate::util::{is_dylib, exe};
2222
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
2323
use crate::compile;
2424
use crate::tool::{self, Tool};
@@ -473,21 +473,23 @@ impl Step for Rustc {
473473
fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
474474
let host = compiler.host;
475475
let src = builder.sysroot(compiler);
476-
let libdir = libdir(&host);
476+
let libdir = builder.rustc_libdir(compiler);
477477

478478
// Copy rustc/rustdoc binaries
479479
t!(fs::create_dir_all(image.join("bin")));
480480
builder.cp_r(&src.join("bin"), &image.join("bin"));
481481

482482
builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
483483

484+
let libdir_relative = builder.libdir_relative(compiler);
485+
484486
// Copy runtime DLLs needed by the compiler
485-
if libdir != "bin" {
486-
for entry in builder.read_dir(&src.join(libdir)) {
487+
if libdir_relative.to_str() != Some("bin") {
488+
for entry in builder.read_dir(&libdir) {
487489
let name = entry.file_name();
488490
if let Some(s) = name.to_str() {
489491
if is_dylib(s) {
490-
builder.install(&entry.path(), &image.join(libdir), 0o644);
492+
builder.install(&entry.path(), &image.join(&libdir_relative), 0o644);
491493
}
492494
}
493495
}
@@ -516,7 +518,8 @@ impl Step for Rustc {
516518
.join("bin")
517519
.join(&exe);
518520
// for the rationale about this rename check `compile::copy_lld_to_sysroot`
519-
let dst = image.join("lib/rustlib")
521+
let dst = image.join(libdir_relative)
522+
.join("rustlib")
520523
.join(&*host)
521524
.join("bin")
522525
.join(&exe);

src/bootstrap/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,7 @@ impl Build {
12751275
fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
12761276
if self.config.dry_run { return; }
12771277
let dst = dstdir.join(src.file_name().unwrap());
1278+
self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
12781279
t!(fs::create_dir_all(dstdir));
12791280
drop(fs::remove_file(&dst));
12801281
{

src/libcore/ops/arith.rs

+15
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,21 @@ rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
537537

538538
macro_rules! rem_impl_float {
539539
($($t:ty)*) => ($(
540+
541+
/// The remainder from the division of two floats.
542+
///
543+
/// The remainder has the same sign as the dividend and is computed as:
544+
/// `x - (x / y).trunc() * y`.
545+
///
546+
/// # Examples
547+
/// ```
548+
/// let x: f32 = 50.50;
549+
/// let y: f32 = 8.125;
550+
/// let remainder = x - (x / y).trunc() * y;
551+
///
552+
/// // The answer to both operations is 1.75
553+
/// assert_eq!(x % y, remainder);
554+
/// ```
540555
#[stable(feature = "rust1", since = "1.0.0")]
541556
impl Rem for $t {
542557
type Output = $t;

src/librustc_codegen_llvm/debuginfo/metadata.rs

+62-4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,32 @@ impl TypeMap<'ll, 'tcx> {
117117
}
118118
}
119119

120+
// Removes a Ty to metadata mapping
121+
// This is useful when computing the metadata for a potentially
122+
// recursive type (e.g. a function ptr of the form:
123+
//
124+
// fn foo() -> impl Copy { foo }
125+
//
126+
// This kind of type cannot be properly represented
127+
// via LLVM debuginfo. As a workaround,
128+
// we register a temporary Ty to metadata mapping
129+
// for the function before we compute its actual metadata.
130+
// If the metadata computation ends up recursing back to the
131+
// original function, it will use the temporary mapping
132+
// for the inner self-reference, preventing us from
133+
// recursing forever.
134+
//
135+
// This function is used to remove the temporary metadata
136+
// mapping after we've computed the actual metadata
137+
fn remove_type(
138+
&mut self,
139+
type_: Ty<'tcx>,
140+
) {
141+
if self.type_to_metadata.remove(type_).is_none() {
142+
bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
143+
}
144+
}
145+
120146
// Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
121147
// fail if the mapping already exists.
122148
fn register_unique_id_with_metadata(
@@ -608,17 +634,49 @@ pub fn type_metadata(
608634
}
609635
}
610636
ty::FnDef(..) | ty::FnPtr(_) => {
611-
let fn_metadata = subroutine_type_metadata(cx,
612-
unique_type_id,
613-
t.fn_sig(cx.tcx),
614-
usage_site_span).metadata;
637+
615638
if let Some(metadata) = debug_context(cx).type_map
616639
.borrow()
617640
.find_metadata_for_unique_id(unique_type_id)
618641
{
619642
return metadata;
620643
}
621644

645+
// It's possible to create a self-referential
646+
// type in Rust by using 'impl trait':
647+
//
648+
// fn foo() -> impl Copy { foo }
649+
//
650+
// See TypeMap::remove_type for more detals
651+
// about the workaround
652+
653+
let temp_type = {
654+
unsafe {
655+
// The choice of type here is pretty arbitrary -
656+
// anything reading the debuginfo for a recursive
657+
// type is going to see *somthing* weird - the only
658+
// question is what exactly it will see
659+
let (size, align) = cx.size_and_align_of(t);
660+
llvm::LLVMRustDIBuilderCreateBasicType(
661+
DIB(cx),
662+
SmallCStr::new("<recur_type>").as_ptr(),
663+
size.bits(),
664+
align.bits() as u32,
665+
DW_ATE_unsigned)
666+
}
667+
};
668+
669+
let type_map = &debug_context(cx).type_map;
670+
type_map.borrow_mut().register_type_with_metadata(t, temp_type);
671+
672+
let fn_metadata = subroutine_type_metadata(cx,
673+
unique_type_id,
674+
t.fn_sig(cx.tcx),
675+
usage_site_span).metadata;
676+
677+
type_map.borrow_mut().remove_type(t);
678+
679+
622680
// This is actually a function pointer, so wrap it in pointer DI
623681
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
624682

src/librustc_codegen_llvm/debuginfo/type_names.rs

+49-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc::hir::def_id::DefId;
55
use rustc::ty::subst::SubstsRef;
66
use rustc::ty::{self, Ty};
77
use rustc_codegen_ssa::traits::*;
8+
use rustc_data_structures::fx::FxHashSet;
89

910
use rustc::hir;
1011

@@ -17,7 +18,8 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
1718
qualified: bool)
1819
-> String {
1920
let mut result = String::with_capacity(64);
20-
push_debuginfo_type_name(cx, t, qualified, &mut result);
21+
let mut visited = FxHashSet::default();
22+
push_debuginfo_type_name(cx, t, qualified, &mut result, &mut visited);
2123
result
2224
}
2325

@@ -26,7 +28,9 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
2628
pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
2729
t: Ty<'tcx>,
2830
qualified: bool,
29-
output: &mut String) {
31+
output: &mut String,
32+
visited: &mut FxHashSet<Ty<'tcx>>) {
33+
3034
// When targeting MSVC, emit C++ style type names for compatibility with
3135
// .natvis visualizers (and perhaps other existing native debuggers?)
3236
let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
@@ -42,12 +46,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
4246
ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
4347
ty::Adt(def, substs) => {
4448
push_item_name(cx, def.did, qualified, output);
45-
push_type_params(cx, substs, output);
49+
push_type_params(cx, substs, output, visited);
4650
},
4751
ty::Tuple(component_types) => {
4852
output.push('(');
4953
for &component_type in component_types {
50-
push_debuginfo_type_name(cx, component_type, true, output);
54+
push_debuginfo_type_name(cx, component_type, true, output, visited);
5155
output.push_str(", ");
5256
}
5357
if !component_types.is_empty() {
@@ -65,7 +69,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
6569
hir::MutMutable => output.push_str("mut "),
6670
}
6771

68-
push_debuginfo_type_name(cx, inner_type, true, output);
72+
push_debuginfo_type_name(cx, inner_type, true, output, visited);
6973

7074
if cpp_like_names {
7175
output.push('*');
@@ -79,15 +83,15 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
7983
output.push_str("mut ");
8084
}
8185

82-
push_debuginfo_type_name(cx, inner_type, true, output);
86+
push_debuginfo_type_name(cx, inner_type, true, output, visited);
8387

8488
if cpp_like_names {
8589
output.push('*');
8690
}
8791
},
8892
ty::Array(inner_type, len) => {
8993
output.push('[');
90-
push_debuginfo_type_name(cx, inner_type, true, output);
94+
push_debuginfo_type_name(cx, inner_type, true, output, visited);
9195
output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
9296
output.push(']');
9397
},
@@ -98,7 +102,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
98102
output.push('[');
99103
}
100104

101-
push_debuginfo_type_name(cx, inner_type, true, output);
105+
push_debuginfo_type_name(cx, inner_type, true, output, visited);
102106

103107
if cpp_like_names {
104108
output.push('>');
@@ -113,12 +117,31 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
113117
&principal,
114118
);
115119
push_item_name(cx, principal.def_id, false, output);
116-
push_type_params(cx, principal.substs, output);
120+
push_type_params(cx, principal.substs, output, visited);
117121
} else {
118122
output.push_str("dyn '_");
119123
}
120124
},
121125
ty::FnDef(..) | ty::FnPtr(_) => {
126+
// We've encountered a weird 'recursive type'
127+
// Currently, the only way to generate such a type
128+
// is by using 'impl trait':
129+
//
130+
// fn foo() -> impl Copy { foo }
131+
//
132+
// There's not really a sensible name we can generate,
133+
// since we don't include 'impl trait' types (e.g. ty::Opaque)
134+
// in the output
135+
//
136+
// Since we need to generate *something*, we just
137+
// use a dummy string that should make it clear
138+
// that something unusual is going on
139+
if !visited.insert(t) {
140+
output.push_str("<recursive_type>");
141+
return;
142+
}
143+
144+
122145
let sig = t.fn_sig(cx.tcx);
123146
if sig.unsafety() == hir::Unsafety::Unsafe {
124147
output.push_str("unsafe ");
@@ -136,7 +159,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
136159
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
137160
if !sig.inputs().is_empty() {
138161
for &parameter_type in sig.inputs() {
139-
push_debuginfo_type_name(cx, parameter_type, true, output);
162+
push_debuginfo_type_name(cx, parameter_type, true, output, visited);
140163
output.push_str(", ");
141164
}
142165
output.pop();
@@ -155,8 +178,20 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
155178

156179
if !sig.output().is_unit() {
157180
output.push_str(" -> ");
158-
push_debuginfo_type_name(cx, sig.output(), true, output);
181+
push_debuginfo_type_name(cx, sig.output(), true, output, visited);
159182
}
183+
184+
185+
// We only keep the type in 'visited'
186+
// for the duration of the body of this method.
187+
// It's fine for a particular function type
188+
// to show up multiple times in one overall type
189+
// (e.g. MyType<fn() -> u8, fn() -> u8>
190+
//
191+
// We only care about avoiding recursing
192+
// directly back to the type we're currently
193+
// processing
194+
visited.remove(t);
160195
},
161196
ty::Closure(..) => {
162197
output.push_str("closure");
@@ -200,15 +235,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
200235
// common denominator - otherwise we would run into conflicts.
201236
fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
202237
substs: SubstsRef<'tcx>,
203-
output: &mut String) {
238+
output: &mut String,
239+
visited: &mut FxHashSet<Ty<'tcx>>) {
204240
if substs.types().next().is_none() {
205241
return;
206242
}
207243

208244
output.push('<');
209245

210246
for type_parameter in substs.types() {
211-
push_debuginfo_type_name(cx, type_parameter, true, output);
247+
push_debuginfo_type_name(cx, type_parameter, true, output, visited);
212248
output.push_str(", ");
213249
}
214250

0 commit comments

Comments
 (0)