Merge from rustc
This commit is contained in:
commit
ac3e349110
93 changed files with 1386 additions and 893 deletions
|
|
@ -599,6 +599,16 @@ impl Step for Std {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let stage = self.stage;
|
||||
let target = self.target;
|
||||
let crates = if self.crates.is_empty() {
|
||||
builder
|
||||
.in_tree_crates("sysroot", Some(target))
|
||||
.iter()
|
||||
.map(|c| c.name.to_string())
|
||||
.collect()
|
||||
} else {
|
||||
self.crates
|
||||
};
|
||||
|
||||
let out = match self.format {
|
||||
DocumentationFormat::Html => builder.doc_out(target),
|
||||
DocumentationFormat::Json => builder.json_doc_out(target),
|
||||
|
|
@ -627,7 +637,7 @@ impl Step for Std {
|
|||
extra_args.push("--disable-minification");
|
||||
}
|
||||
|
||||
doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
|
||||
doc_std(builder, self.format, stage, target, &out, &extra_args, &crates);
|
||||
|
||||
// Don't open if the format is json
|
||||
if let DocumentationFormat::Json = self.format {
|
||||
|
|
@ -639,7 +649,7 @@ impl Step for Std {
|
|||
let index = out.join("std").join("index.html");
|
||||
builder.open_in_browser(index);
|
||||
} else {
|
||||
for requested_crate in &*self.crates {
|
||||
for requested_crate in crates {
|
||||
if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
|
||||
let index = out.join(requested_crate).join("index.html");
|
||||
builder.open_in_browser(index);
|
||||
|
|
|
|||
|
|
@ -536,8 +536,7 @@ pub fn get_closest_merge_base_commit(
|
|||
|
||||
let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into());
|
||||
|
||||
git.arg(Path::new("rev-list"));
|
||||
git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
|
||||
git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
|
||||
|
||||
if !target_paths.is_empty() {
|
||||
git.arg("--").args(target_paths);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no
|
|||
# Needed for apt-key to work:
|
||||
dirmngr \
|
||||
gpg-agent \
|
||||
g++-9-arm-linux-gnueabi
|
||||
g++-9-arm-linux-gnueabi \
|
||||
g++-11-riscv64-linux-gnu
|
||||
|
||||
RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486
|
||||
RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main'
|
||||
|
|
@ -73,6 +74,10 @@ RUN env \
|
|||
CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \
|
||||
CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \
|
||||
bash musl.sh armv7 && \
|
||||
env \
|
||||
CC=riscv64-linux-gnu-gcc-11 \
|
||||
CXX=riscv64-linux-gnu-g++-11 \
|
||||
bash musl.sh riscv64gc && \
|
||||
rm -rf /build/*
|
||||
|
||||
WORKDIR /tmp
|
||||
|
|
@ -125,6 +130,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-none
|
|||
ENV TARGETS=$TARGETS,aarch64-unknown-uefi
|
||||
ENV TARGETS=$TARGETS,i686-unknown-uefi
|
||||
ENV TARGETS=$TARGETS,x86_64-unknown-uefi
|
||||
ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl
|
||||
|
||||
# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
|
||||
# we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the
|
||||
|
|
@ -132,7 +138,11 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
|
|||
# Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there
|
||||
RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
|
||||
|
||||
# musl-gcc can't find libgcc_s.so.1 since it doesn't use the standard search paths.
|
||||
RUN ln -s /usr/riscv64-linux-gnu/lib/libgcc_s.so.1 /usr/lib/gcc-cross/riscv64-linux-gnu/11/
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \
|
||||
--musl-root-armv7=/musl-armv7
|
||||
--musl-root-armv7=/musl-armv7 \
|
||||
--musl-root-riscv64gc=/musl-riscv64gc
|
||||
|
||||
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
|
||||
- [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
|
||||
- [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
|
||||
- [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
|
||||
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
|
||||
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
|
||||
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ target | notes
|
|||
`powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
|
||||
`powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
|
||||
[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
|
||||
[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
|
||||
`s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
|
||||
`x86_64-unknown-freebsd` | 64-bit FreeBSD
|
||||
`x86_64-unknown-illumos` | illumos
|
||||
|
|
@ -354,7 +355,6 @@ target | std | host | notes
|
|||
[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit
|
||||
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
|
||||
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
|
||||
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.3)
|
||||
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
|
||||
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
|
||||
[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
# riscv64gc-unknown-linux-musl
|
||||
|
||||
**Tier: 2**
|
||||
|
||||
Target for RISC-V Linux programs using musl libc.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- [@Amanieu](https://github.com/Amanieu)
|
||||
- [@kraj](https://github.com/kraj)
|
||||
|
||||
## Requirements
|
||||
|
||||
Building the target itself requires a RISC-V compiler that is supported by `cc-rs`.
|
||||
|
||||
## Building the target
|
||||
|
||||
The target can be built by enabling it for a `rustc` build.
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = ["riscv64gc-unknown-linux-musl"]
|
||||
```
|
||||
|
||||
Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`:
|
||||
|
||||
```toml
|
||||
[target.riscv64gc-unknown-linux-musl]
|
||||
cc = "riscv64-linux-gnu-gcc"
|
||||
cxx = "riscv64-linux-gnu-g++"
|
||||
ar = "riscv64-linux-gnu-ar"
|
||||
linker = "riscv64-linux-gnu-gcc"
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
This target are distributed through `rustup`, and otherwise require no
|
||||
special configuration.
|
||||
|
||||
## Cross-compilation
|
||||
|
||||
This target can be cross-compiled from any host.
|
||||
|
||||
## Testing
|
||||
|
||||
This target can be tested as normal with `x.py` on a RISC-V host or via QEMU
|
||||
emulation.
|
||||
|
|
@ -12,7 +12,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
|
|||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
@ -792,11 +792,7 @@ fn build_macro(
|
|||
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
||||
for pred in &mut g.where_predicates {
|
||||
match *pred {
|
||||
clean::WherePredicate::BoundPredicate {
|
||||
ty: clean::Generic(ref s),
|
||||
ref mut bounds,
|
||||
..
|
||||
} if *s == kw::SelfUpper => {
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => {
|
||||
bounds.retain(|bound| match bound {
|
||||
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
|
||||
trait_.def_id() != trait_did
|
||||
|
|
@ -812,13 +808,13 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
|||
clean::WherePredicate::BoundPredicate {
|
||||
ty:
|
||||
clean::QPath(box clean::QPathData {
|
||||
self_type: clean::Generic(ref s),
|
||||
self_type: clean::Generic(_),
|
||||
trait_: Some(trait_),
|
||||
..
|
||||
}),
|
||||
bounds,
|
||||
..
|
||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
||||
} => !bounds.is_empty() && trait_.def_id() != trait_did,
|
||||
_ => true,
|
||||
});
|
||||
g
|
||||
|
|
@ -832,9 +828,7 @@ fn separate_supertrait_bounds(
|
|||
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||
let mut ty_bounds = Vec::new();
|
||||
g.where_predicates.retain(|pred| match *pred {
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
|
||||
if *s == kw::SelfUpper =>
|
||||
{
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
|
||||
ty_bounds.extend(bounds.iter().cloned());
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1351,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
|||
let self_arg_ty =
|
||||
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
|
||||
item.decl.inputs.values[0].type_ = SelfTy;
|
||||
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
|
||||
if ty == self_ty {
|
||||
match item.decl.inputs.values[0].type_ {
|
||||
BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
|
||||
BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1439,9 +1439,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
|||
if trait_.def_id() != assoc_item.container_id(tcx) {
|
||||
return true;
|
||||
}
|
||||
match *self_type {
|
||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
||||
_ => return true,
|
||||
if *self_type != SelfTy {
|
||||
return true;
|
||||
}
|
||||
match &assoc.args {
|
||||
GenericArgs::AngleBracketed { args, constraints } => {
|
||||
|
|
@ -2228,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||
ty::Param(ref p) => {
|
||||
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
|
||||
ImplTrait(bounds)
|
||||
} else if p.name == kw::SelfUpper {
|
||||
SelfTy
|
||||
} else {
|
||||
Generic(p.name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,6 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi
|
|||
// should be handled when cleaning associated types.
|
||||
generics.where_predicates.retain(|pred| {
|
||||
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
|
||||
&& *param != rustc_span::symbol::kw::SelfUpper
|
||||
&& bounds.iter().any(|b| b.is_sized_bound(cx))
|
||||
{
|
||||
sized_params.insert(*param);
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@ use thin_vec::ThinVec;
|
|||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
pub(crate) use self::ItemKind::*;
|
||||
pub(crate) use self::SelfTy::*;
|
||||
pub(crate) use self::Type::{
|
||||
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
};
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::clean::clean_middle_path;
|
||||
|
|
@ -1384,8 +1383,8 @@ pub(crate) struct FnDecl {
|
|||
}
|
||||
|
||||
impl FnDecl {
|
||||
pub(crate) fn self_type(&self) -> Option<SelfTy> {
|
||||
self.inputs.values.get(0).and_then(|v| v.to_self())
|
||||
pub(crate) fn receiver_type(&self) -> Option<&Type> {
|
||||
self.inputs.values.get(0).and_then(|v| v.to_receiver())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1403,27 +1402,9 @@ pub(crate) struct Argument {
|
|||
pub(crate) is_const: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub(crate) enum SelfTy {
|
||||
SelfValue,
|
||||
SelfBorrowed(Option<Lifetime>, Mutability),
|
||||
SelfExplicit(Type),
|
||||
}
|
||||
|
||||
impl Argument {
|
||||
pub(crate) fn to_self(&self) -> Option<SelfTy> {
|
||||
if self.name != kw::SelfLower {
|
||||
return None;
|
||||
}
|
||||
if self.type_.is_self_type() {
|
||||
return Some(SelfValue);
|
||||
}
|
||||
match self.type_ {
|
||||
BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
|
||||
Some(SelfBorrowed(lifetime.clone(), mutability))
|
||||
}
|
||||
_ => Some(SelfExplicit(self.type_.clone())),
|
||||
}
|
||||
pub(crate) fn to_receiver(&self) -> Option<&Type> {
|
||||
if self.name == kw::SelfLower { Some(&self.type_) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1477,6 +1458,8 @@ pub(crate) enum Type {
|
|||
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
|
||||
/// A type parameter.
|
||||
Generic(Symbol),
|
||||
/// The `Self` type.
|
||||
SelfTy,
|
||||
/// A primitive (aka, builtin) type.
|
||||
Primitive(PrimitiveType),
|
||||
/// A function pointer: `extern "ABI" fn(...) -> ...`
|
||||
|
|
@ -1571,6 +1554,8 @@ impl Type {
|
|||
// If both sides are generic, this returns true.
|
||||
(_, Type::Generic(_)) => true,
|
||||
(Type::Generic(_), _) => false,
|
||||
// `Self` only matches itself.
|
||||
(Type::SelfTy, Type::SelfTy) => true,
|
||||
// Paths account for both the path itself and its generics.
|
||||
(Type::Path { path: a }, Type::Path { path: b }) => {
|
||||
a.def_id() == b.def_id()
|
||||
|
|
@ -1642,7 +1627,7 @@ impl Type {
|
|||
|
||||
pub(crate) fn is_self_type(&self) -> bool {
|
||||
match *self {
|
||||
Generic(name) => name == kw::SelfUpper,
|
||||
SelfTy => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -1700,7 +1685,7 @@ impl Type {
|
|||
Type::Pat(..) => PrimitiveType::Pat,
|
||||
RawPointer(..) => PrimitiveType::RawPointer,
|
||||
QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
|
||||
Generic(_) | Infer | ImplTrait(_) => return None,
|
||||
Generic(_) | SelfTy | Infer | ImplTrait(_) => return None,
|
||||
};
|
||||
Primitive(t).def_id(cache)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
|
|||
match path.res {
|
||||
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
|
||||
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
|
||||
Generic(kw::SelfUpper)
|
||||
Type::SelfTy
|
||||
}
|
||||
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -310,16 +310,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||
// `public_items` map, so we can skip inserting into the
|
||||
// paths map if there was already an entry present and we're
|
||||
// not a public item.
|
||||
if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
|
||||
let item_def_id = item.item_id.expect_def_id();
|
||||
if !self.cache.paths.contains_key(&item_def_id)
|
||||
|| self
|
||||
.cache
|
||||
.effective_visibilities
|
||||
.is_directly_public(self.tcx, item.item_id.expect_def_id())
|
||||
.is_directly_public(self.tcx, item_def_id)
|
||||
{
|
||||
self.cache.paths.insert(
|
||||
item.item_id.expect_def_id(),
|
||||
(self.cache.stack.clone(), item.type_()),
|
||||
);
|
||||
self.cache
|
||||
.paths
|
||||
.insert(item_def_id, (self.cache.stack.clone(), item.type_()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -381,9 +381,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||
&& adt.is_fundamental()
|
||||
{
|
||||
for ty in generics {
|
||||
if let Some(did) = ty.def_id(self.cache) {
|
||||
dids.insert(did);
|
||||
}
|
||||
dids.extend(ty.def_id(self.cache));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -396,32 +394,26 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||
.primitive_type()
|
||||
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
|
||||
|
||||
if let Some(did) = did {
|
||||
dids.insert(did);
|
||||
}
|
||||
dids.extend(did);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
|
||||
for bound in generics {
|
||||
if let Some(did) = bound.def_id(self.cache) {
|
||||
dids.insert(did);
|
||||
}
|
||||
dids.extend(bound.def_id(self.cache));
|
||||
}
|
||||
}
|
||||
let impl_item = Impl { impl_item: item };
|
||||
if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
|
||||
let impl_did = impl_item.def_id();
|
||||
let trait_did = impl_item.trait_did();
|
||||
if trait_did.map_or(true, |d| self.cache.traits.contains_key(&d)) {
|
||||
for did in dids {
|
||||
if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) {
|
||||
self.cache
|
||||
.impls
|
||||
.entry(did)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(impl_item.clone());
|
||||
if self.impl_ids.entry(did).or_default().insert(impl_did) {
|
||||
self.cache.impls.entry(did).or_default().push(impl_item.clone());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let trait_did = impl_item.trait_did().expect("no trait did");
|
||||
let trait_did = trait_did.expect("no trait did");
|
||||
self.cache.orphan_trait_impls.push((trait_did, dids, impl_item));
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,7 @@ fn fmt_type<'cx>(
|
|||
|
||||
match *t {
|
||||
clean::Generic(name) => f.write_str(name.as_str()),
|
||||
clean::SelfTy => f.write_str("Self"),
|
||||
clean::Type::Path { ref path } => {
|
||||
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
|
||||
let did = path.def_id();
|
||||
|
|
@ -1452,29 +1453,22 @@ impl clean::FnDecl {
|
|||
|
||||
let last_input_index = self.inputs.values.len().checked_sub(1);
|
||||
for (i, input) in self.inputs.values.iter().enumerate() {
|
||||
if let Some(selfty) = input.to_self() {
|
||||
if let Some(selfty) = input.to_receiver() {
|
||||
match selfty {
|
||||
clean::SelfValue => {
|
||||
clean::SelfTy => {
|
||||
write!(f, "self")?;
|
||||
}
|
||||
clean::SelfBorrowed(Some(ref lt), mutability) => {
|
||||
write!(
|
||||
f,
|
||||
"{amp}{lifetime} {mutability}self",
|
||||
lifetime = lt.print(),
|
||||
mutability = mutability.print_with_space(),
|
||||
)?;
|
||||
clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
|
||||
write!(f, "{amp}")?;
|
||||
match lifetime {
|
||||
Some(lt) => write!(f, "{lt} ", lt = lt.print())?,
|
||||
None => {}
|
||||
}
|
||||
write!(f, "{mutability}self", mutability = mutability.print_with_space())?;
|
||||
}
|
||||
clean::SelfBorrowed(None, mutability) => {
|
||||
write!(
|
||||
f,
|
||||
"{amp}{mutability}self",
|
||||
mutability = mutability.print_with_space(),
|
||||
)?;
|
||||
}
|
||||
clean::SelfExplicit(ref typ) => {
|
||||
_ => {
|
||||
write!(f, "self: ")?;
|
||||
typ.print(cx).fmt(f)?;
|
||||
selfty.print(cx).fmt(f)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ use serde::{Serialize, Serializer};
|
|||
|
||||
pub(crate) use self::context::*;
|
||||
pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
|
||||
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
|
||||
use crate::clean::{self, ItemId, RenderedLink};
|
||||
use crate::error::Error;
|
||||
use crate::formats::cache::Cache;
|
||||
use crate::formats::item_type::ItemType;
|
||||
|
|
@ -1372,21 +1372,20 @@ fn render_deref_methods(
|
|||
|
||||
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
|
||||
let self_type_opt = match *item.kind {
|
||||
clean::MethodItem(ref method, _) => method.decl.self_type(),
|
||||
clean::TyMethodItem(ref method) => method.decl.self_type(),
|
||||
clean::MethodItem(ref method, _) => method.decl.receiver_type(),
|
||||
clean::TyMethodItem(ref method) => method.decl.receiver_type(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(self_ty) = self_type_opt {
|
||||
let (by_mut_ref, by_box, by_value) = match self_ty {
|
||||
SelfTy::SelfBorrowed(_, mutability)
|
||||
| SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
|
||||
let (by_mut_ref, by_box, by_value) = match *self_ty {
|
||||
clean::Type::BorrowedRef { mutability, .. } => {
|
||||
(mutability == Mutability::Mut, false, false)
|
||||
}
|
||||
SelfTy::SelfExplicit(clean::Type::Path { path }) => {
|
||||
clean::Type::Path { ref path } => {
|
||||
(false, Some(path.def_id()) == tcx.lang_items().owned_box(), false)
|
||||
}
|
||||
SelfTy::SelfValue => (false, false, true),
|
||||
clean::Type::SelfTy => (false, false, true),
|
||||
_ => (false, false, false),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -797,7 +797,11 @@ fn get_index_type_id(
|
|||
}
|
||||
}
|
||||
// Not supported yet
|
||||
clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
|
||||
clean::Type::Pat(..)
|
||||
| clean::Generic(_)
|
||||
| clean::SelfTy
|
||||
| clean::ImplTrait(_)
|
||||
| clean::Infer => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -850,15 +854,70 @@ fn simplify_fn_type<'tcx, 'a>(
|
|||
|
||||
// If this argument is a type parameter and not a trait bound or a type, we need to look
|
||||
// for its bounds.
|
||||
if let Type::Generic(arg_s) = *arg {
|
||||
// First we check if the bounds are in a `where` predicate...
|
||||
let mut type_bounds = Vec::new();
|
||||
for where_pred in generics.where_predicates.iter().filter(|g| match g {
|
||||
WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s,
|
||||
_ => false,
|
||||
}) {
|
||||
let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
|
||||
for bound in bounds.iter() {
|
||||
match *arg {
|
||||
Type::Generic(arg_s) => {
|
||||
// First we check if the bounds are in a `where` predicate...
|
||||
let mut type_bounds = Vec::new();
|
||||
for where_pred in generics.where_predicates.iter().filter(|g| match g {
|
||||
WherePredicate::BoundPredicate { ty, .. } => *ty == *arg,
|
||||
_ => false,
|
||||
}) {
|
||||
let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
|
||||
for bound in bounds.iter() {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
|
||||
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
|
||||
for bound in bound.get_bounds().unwrap_or(&[]) {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(*idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
} else {
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
Type::ImplTrait(ref bounds) => {
|
||||
let mut type_bounds = Vec::new();
|
||||
for bound in bounds {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
|
|
@ -874,103 +933,22 @@ fn simplify_fn_type<'tcx, 'a>(
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
|
||||
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
|
||||
for bound in bound.get_bounds().unwrap_or(&[]) {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
if is_return && !type_bounds.is_empty() {
|
||||
// In return position, `impl Trait` is a unique thing.
|
||||
res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None });
|
||||
} else {
|
||||
// In parameter position, `impl Trait` is the same as an unnamed generic parameter.
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(*idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
} else {
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
} else if let Type::ImplTrait(ref bounds) = *arg {
|
||||
let mut type_bounds = Vec::new();
|
||||
for bound in bounds {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
if is_return && !type_bounds.is_empty() {
|
||||
// In parameter position, `impl Trait` is a unique thing.
|
||||
res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None });
|
||||
} else {
|
||||
// In parameter position, `impl Trait` is the same as an unnamed generic parameter.
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
|
||||
res.push(RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
} else if let Type::Slice(ref ty) = *arg {
|
||||
let mut ty_generics = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
} else if let Type::Array(ref ty, _) = *arg {
|
||||
let mut ty_generics = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
} else if let Type::Tuple(ref tys) = *arg {
|
||||
let mut ty_generics = Vec::new();
|
||||
for ty in tys {
|
||||
Type::Slice(ref ty) => {
|
||||
let mut ty_generics = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
|
|
@ -982,15 +960,14 @@ fn simplify_fn_type<'tcx, 'a>(
|
|||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
}
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
} else if let Type::BareFunction(ref bf) = *arg {
|
||||
let mut ty_generics = Vec::new();
|
||||
for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) {
|
||||
Type::Array(ref ty, _) => {
|
||||
let mut ty_generics = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
ty,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
|
|
@ -998,62 +975,11 @@ fn simplify_fn_type<'tcx, 'a>(
|
|||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
}
|
||||
// The search index, for simplicity's sake, represents fn pointers and closures
|
||||
// the same way: as a tuple for the parameters, and an associated type for the
|
||||
// return type.
|
||||
let mut ty_output = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&bf.decl.output,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_output,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
|
||||
res.push(RenderType {
|
||||
id: get_index_type_id(&arg, rgen),
|
||||
bindings: Some(ty_bindings),
|
||||
generics: Some(ty_generics),
|
||||
});
|
||||
} else if let Type::BorrowedRef { lifetime: _, mutability, ref type_ } = *arg {
|
||||
let mut ty_generics = Vec::new();
|
||||
if mutability.is_mut() {
|
||||
ty_generics.push(RenderType {
|
||||
id: Some(RenderTypeId::Mut),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&type_,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
} else {
|
||||
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
|
||||
// looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
|
||||
//
|
||||
// So in here, we can add it directly and look for its own type parameters (so for `Option`,
|
||||
// we will look for them but not for `T`).
|
||||
let mut ty_generics = Vec::new();
|
||||
let mut ty_constraints = Vec::new();
|
||||
if let Some(arg_generics) = arg.generic_args() {
|
||||
for ty in arg_generics.into_iter().filter_map(|param| match param {
|
||||
clean::GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}) {
|
||||
Type::Tuple(ref tys) => {
|
||||
let mut ty_generics = Vec::new();
|
||||
for ty in tys {
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
|
|
@ -1066,94 +992,181 @@ fn simplify_fn_type<'tcx, 'a>(
|
|||
cache,
|
||||
);
|
||||
}
|
||||
for constraint in arg_generics.constraints() {
|
||||
simplify_fn_constraint(
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
}
|
||||
Type::BareFunction(ref bf) => {
|
||||
let mut ty_generics = Vec::new();
|
||||
for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) {
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&constraint,
|
||||
ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_constraints,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
// The search index, for simplicity's sake, represents fn pointers and closures
|
||||
// the same way: as a tuple for the parameters, and an associated type for the
|
||||
// return type.
|
||||
let mut ty_output = Vec::new();
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&bf.decl.output,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_output,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
|
||||
res.push(RenderType {
|
||||
id: get_index_type_id(&arg, rgen),
|
||||
bindings: Some(ty_bindings),
|
||||
generics: Some(ty_generics),
|
||||
});
|
||||
}
|
||||
// Every trait associated type on self gets assigned to a type parameter index
|
||||
// this same one is used later for any appearances of these types
|
||||
//
|
||||
// for example, Iterator::next is:
|
||||
//
|
||||
// trait Iterator {
|
||||
// fn next(&mut self) -> Option<Self::Item>
|
||||
// }
|
||||
//
|
||||
// Self is technically just Iterator, but we want to pretend it's more like this:
|
||||
//
|
||||
// fn next<T>(self: Iterator<Item=T>) -> Option<T>
|
||||
if is_self
|
||||
&& let Type::Path { path } = arg
|
||||
&& let def_id = path.def_id()
|
||||
&& let Some(trait_) = cache.traits.get(&def_id)
|
||||
&& trait_.items.iter().any(|at| at.is_ty_associated_type())
|
||||
{
|
||||
for assoc_ty in &trait_.items {
|
||||
if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
|
||||
&& let Some(name) = assoc_ty.name
|
||||
{
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
let (idx, stored_bounds) = rgen
|
||||
.entry(SimplifiedParam::AssociatedType(def_id, name))
|
||||
.or_insert_with(|| (idx, Vec::new()));
|
||||
let idx = *idx;
|
||||
if stored_bounds.is_empty() {
|
||||
// Can't just pass stored_bounds to simplify_fn_type,
|
||||
// because it also accepts rgen as a parameter.
|
||||
// Instead, have it fill in this local, then copy it into the map afterward.
|
||||
let mut type_bounds = Vec::new();
|
||||
for bound in bounds {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
let stored_bounds = &mut rgen
|
||||
.get_mut(&SimplifiedParam::AssociatedType(def_id, name))
|
||||
.unwrap()
|
||||
.1;
|
||||
if stored_bounds.is_empty() {
|
||||
*stored_bounds = type_bounds;
|
||||
}
|
||||
}
|
||||
ty_constraints.push((
|
||||
RenderTypeId::AssociatedType(name),
|
||||
vec![RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
}],
|
||||
))
|
||||
Type::BorrowedRef { lifetime: _, mutability, ref type_ } => {
|
||||
let mut ty_generics = Vec::new();
|
||||
if mutability.is_mut() {
|
||||
ty_generics.push(RenderType {
|
||||
id: Some(RenderTypeId::Mut),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
});
|
||||
}
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&type_,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
res.push(get_index_type(arg, ty_generics, rgen));
|
||||
}
|
||||
_ => {
|
||||
// This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
|
||||
// looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
|
||||
//
|
||||
// So in here, we can add it directly and look for its own type parameters (so for `Option`,
|
||||
// we will look for them but not for `T`).
|
||||
let mut ty_generics = Vec::new();
|
||||
let mut ty_constraints = Vec::new();
|
||||
if let Some(arg_generics) = arg.generic_args() {
|
||||
for ty in arg_generics.into_iter().filter_map(|param| match param {
|
||||
clean::GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}) {
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_generics,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
for constraint in arg_generics.constraints() {
|
||||
simplify_fn_constraint(
|
||||
self_,
|
||||
generics,
|
||||
&constraint,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut ty_constraints,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let id = get_index_type_id(&arg, rgen);
|
||||
if id.is_some() || !ty_generics.is_empty() {
|
||||
res.push(RenderType {
|
||||
id,
|
||||
bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
|
||||
generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
|
||||
});
|
||||
// Every trait associated type on self gets assigned to a type parameter index
|
||||
// this same one is used later for any appearances of these types
|
||||
//
|
||||
// for example, Iterator::next is:
|
||||
//
|
||||
// trait Iterator {
|
||||
// fn next(&mut self) -> Option<Self::Item>
|
||||
// }
|
||||
//
|
||||
// Self is technically just Iterator, but we want to pretend it's more like this:
|
||||
//
|
||||
// fn next<T>(self: Iterator<Item=T>) -> Option<T>
|
||||
if is_self
|
||||
&& let Type::Path { path } = arg
|
||||
&& let def_id = path.def_id()
|
||||
&& let Some(trait_) = cache.traits.get(&def_id)
|
||||
&& trait_.items.iter().any(|at| at.is_ty_associated_type())
|
||||
{
|
||||
for assoc_ty in &trait_.items {
|
||||
if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
|
||||
&& let Some(name) = assoc_ty.name
|
||||
{
|
||||
let idx = -isize::try_from(rgen.len() + 1).unwrap();
|
||||
let (idx, stored_bounds) = rgen
|
||||
.entry(SimplifiedParam::AssociatedType(def_id, name))
|
||||
.or_insert_with(|| (idx, Vec::new()));
|
||||
let idx = *idx;
|
||||
if stored_bounds.is_empty() {
|
||||
// Can't just pass stored_bounds to simplify_fn_type,
|
||||
// because it also accepts rgen as a parameter.
|
||||
// Instead, have it fill in this local, then copy it into the map afterward.
|
||||
let mut type_bounds = Vec::new();
|
||||
for bound in bounds {
|
||||
if let Some(path) = bound.get_trait_path() {
|
||||
let ty = Type::Path { path };
|
||||
simplify_fn_type(
|
||||
self_,
|
||||
generics,
|
||||
&ty,
|
||||
tcx,
|
||||
recurse + 1,
|
||||
&mut type_bounds,
|
||||
rgen,
|
||||
is_return,
|
||||
cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
let stored_bounds = &mut rgen
|
||||
.get_mut(&SimplifiedParam::AssociatedType(def_id, name))
|
||||
.unwrap()
|
||||
.1;
|
||||
if stored_bounds.is_empty() {
|
||||
*stored_bounds = type_bounds;
|
||||
}
|
||||
}
|
||||
ty_constraints.push((
|
||||
RenderTypeId::AssociatedType(name),
|
||||
vec![RenderType {
|
||||
id: Some(RenderTypeId::Index(idx)),
|
||||
generics: None,
|
||||
bindings: None,
|
||||
}],
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
let id = get_index_type_id(&arg, rgen);
|
||||
if id.is_some() || !ty_generics.is_empty() {
|
||||
res.push(RenderType {
|
||||
id,
|
||||
bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
|
||||
generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ impl FromWithTcx<clean::Type> for Type {
|
|||
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
||||
use clean::Type::{
|
||||
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
};
|
||||
|
||||
match ty {
|
||||
|
|
@ -588,6 +588,8 @@ impl FromWithTcx<clean::Type> for Type {
|
|||
traits: bounds.into_tcx(tcx),
|
||||
}),
|
||||
Generic(s) => Type::Generic(s.to_string()),
|
||||
// FIXME: add dedicated variant to json Type?
|
||||
SelfTy => Type::Generic("Self".to_owned()),
|
||||
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
|
||||
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
||||
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
||||
|
|
|
|||
|
|
@ -216,13 +216,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
fn after_krate(&mut self) -> Result<(), Error> {
|
||||
debug!("Done with crate");
|
||||
|
||||
debug!("Adding Primitive impls");
|
||||
for primitive in Rc::clone(&self.cache).primitive_locations.values() {
|
||||
self.get_impls(*primitive);
|
||||
}
|
||||
|
||||
let e = ExternalCrate { crate_num: LOCAL_CRATE };
|
||||
|
||||
let index = (*self.index).clone().into_inner();
|
||||
|
||||
debug!("Constructing Output");
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ static TARGETS: &[&str] = &[
|
|||
"riscv64gc-unknown-hermit",
|
||||
"riscv64gc-unknown-none-elf",
|
||||
"riscv64gc-unknown-linux-gnu",
|
||||
"riscv64gc-unknown-linux-musl",
|
||||
"s390x-unknown-linux-gnu",
|
||||
"sparc64-unknown-linux-gnu",
|
||||
"sparcv9-sun-solaris",
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let this = self.eval_context_mut();
|
||||
|
||||
// See if the core engine can handle this intrinsic.
|
||||
if this.emulate_intrinsic(instance, args, dest, ret)? {
|
||||
if this.eval_intrinsic(instance, args, dest, ret)? {
|
||||
return Ok(None);
|
||||
}
|
||||
let intrinsic_name = this.tcx.item_name(instance.def_id());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use super::cygpath::get_windows_path;
|
||||
use crate::artifact_names::{dynamic_lib_name, static_lib_name};
|
||||
use crate::external_deps::cc::{cc, cxx};
|
||||
use crate::external_deps::llvm::llvm_ar;
|
||||
|
|
@ -44,8 +43,7 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf {
|
|||
};
|
||||
let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") };
|
||||
if is_msvc() {
|
||||
let mut out_arg = "-out:".to_owned();
|
||||
out_arg.push_str(&get_windows_path(&lib_path));
|
||||
let out_arg = format!("-out:{lib_path}");
|
||||
cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run();
|
||||
} else if is_darwin() {
|
||||
cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use std::path::Path;
|
||||
|
||||
// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency?
|
||||
use super::cygpath::get_windows_path;
|
||||
use crate::command::Command;
|
||||
use crate::{env_var, is_msvc, is_windows, uname};
|
||||
|
||||
|
|
@ -97,12 +95,12 @@ impl Cc {
|
|||
|
||||
if is_msvc() {
|
||||
path.set_extension("exe");
|
||||
let fe_path = get_windows_path(&path);
|
||||
let fe_path = path.clone();
|
||||
path.set_extension("");
|
||||
path.set_extension("obj");
|
||||
let fo_path = get_windows_path(path);
|
||||
self.cmd.arg(format!("-Fe:{fe_path}"));
|
||||
self.cmd.arg(format!("-Fo:{fo_path}"));
|
||||
let fo_path = path;
|
||||
self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap()));
|
||||
self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap()));
|
||||
} else {
|
||||
self.cmd.arg("-o");
|
||||
self.cmd.arg(name);
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
use std::panic;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::command::Command;
|
||||
use crate::util::handle_failed_output;
|
||||
|
||||
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
|
||||
/// available on the platform!
|
||||
///
|
||||
/// # FIXME
|
||||
///
|
||||
/// FIXME(jieyouxu): we should consider not depending on `cygpath`.
|
||||
///
|
||||
/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style
|
||||
/// > pathnames and vice versa.
|
||||
/// >
|
||||
/// > [irrelevant entries omitted...]
|
||||
/// >
|
||||
/// > `-w, --windows print Windows form of NAMEs (C:\WINNT)`
|
||||
/// >
|
||||
/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*.
|
||||
#[track_caller]
|
||||
#[must_use]
|
||||
pub fn get_windows_path<P: AsRef<Path>>(path: P) -> String {
|
||||
let caller = panic::Location::caller();
|
||||
let mut cygpath = Command::new("cygpath");
|
||||
cygpath.arg("-w");
|
||||
cygpath.arg(path.as_ref());
|
||||
let output = cygpath.run();
|
||||
if !output.status().success() {
|
||||
handle_failed_output(&cygpath, output, caller.line());
|
||||
}
|
||||
// cygpath -w can attach a newline
|
||||
output.stdout_utf8().trim().to_string()
|
||||
}
|
||||
|
|
@ -151,7 +151,8 @@ impl LlvmReadobj {
|
|||
self
|
||||
}
|
||||
|
||||
/// Pass `--symbols` to display the symbol.
|
||||
/// Pass `--symbols` to display the symbol table, including both local
|
||||
/// and global symbols.
|
||||
pub fn symbols(&mut self) -> &mut Self {
|
||||
self.cmd.arg("--symbols");
|
||||
self
|
||||
|
|
|
|||
|
|
@ -9,6 +9,3 @@ pub mod llvm;
|
|||
pub mod python;
|
||||
pub mod rustc;
|
||||
pub mod rustdoc;
|
||||
|
||||
// Library-internal external dependency.
|
||||
mod cygpath;
|
||||
|
|
|
|||
|
|
@ -9,11 +9,19 @@ pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
|
|||
if link.as_ref().exists() {
|
||||
std::fs::remove_dir(link.as_ref()).unwrap();
|
||||
}
|
||||
std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
|
||||
"failed to create symlink {:?} for {:?}",
|
||||
link.as_ref().display(),
|
||||
original.as_ref().display(),
|
||||
));
|
||||
if original.as_ref().is_file() {
|
||||
std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
|
||||
"failed to create symlink {:?} for {:?}",
|
||||
link.as_ref().display(),
|
||||
original.as_ref().display(),
|
||||
));
|
||||
} else {
|
||||
std::os::windows::fs::symlink_dir(original.as_ref(), link.as_ref()).expect(&format!(
|
||||
"failed to create symlink {:?} for {:?}",
|
||||
link.as_ref().display(),
|
||||
original.as_ref().display(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
|
||||
|
|
@ -41,6 +49,8 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
|
|||
let ty = entry.file_type()?;
|
||||
if ty.is_dir() {
|
||||
copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
|
||||
} else if ty.is_symlink() {
|
||||
copy_symlink(entry.path(), dst.join(entry.file_name()))?;
|
||||
} else {
|
||||
std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
|
||||
}
|
||||
|
|
@ -59,6 +69,12 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn copy_symlink<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
|
||||
let target_path = std::fs::read_link(from).unwrap();
|
||||
create_symlink(target_path, to);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper for reading entries in a given directory.
|
||||
pub fn read_dir_entries<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
|
||||
for entry in read_dir(dir) {
|
||||
|
|
|
|||
|
|
@ -27,12 +27,10 @@ run-make/raw-dylib-alt-calling-convention/Makefile
|
|||
run-make/raw-dylib-c/Makefile
|
||||
run-make/redundant-libs/Makefile
|
||||
run-make/remap-path-prefix-dwarf/Makefile
|
||||
run-make/reproducible-build-2/Makefile
|
||||
run-make/reproducible-build/Makefile
|
||||
run-make/rlib-format-packed-bundled-libs/Makefile
|
||||
run-make/simd-ffi/Makefile
|
||||
run-make/split-debuginfo/Makefile
|
||||
run-make/stable-symbol-names/Makefile
|
||||
run-make/staticlib-dylib-linkage/Makefile
|
||||
run-make/symbol-mangling-hashed/Makefile
|
||||
run-make/sysroot-crates-are-unstable/Makefile
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue