mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #128673 - matthiaskrgr:rollup-gtvpkm7, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128026 (std:🧵 available_parallelism implementation for vxWorks proposal.) - #128471 (rustdoc: Fix handling of `Self` type in search index and refactor its representation) - #128607 (Use `object` in `run-make/symbols-visibility`) - #128609 (Remove unnecessary constants from flt2dec dragon) - #128611 (run-make: Remove cygpath) - #128619 (Correct the const stabilization of `<[T]>::last_chunk`) - #128630 (docs(resolve): more explain about `target`) - #128660 (tests: more crashes) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4d48a6be74
@ -48,6 +48,7 @@ pub(crate) enum ImportKind<'a> {
|
||||
/// `source` in `use prefix::source as target`.
|
||||
source: Ident,
|
||||
/// `target` in `use prefix::source as target`.
|
||||
/// It will directly use `source` when the format is `use prefix::source`.
|
||||
target: Ident,
|
||||
/// Bindings to which `source` refers to.
|
||||
source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
|
||||
|
@ -12,48 +12,51 @@ use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
|
||||
|
||||
static POW10: [Digit; 10] =
|
||||
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
|
||||
static TWOPOW10: [Digit; 10] =
|
||||
[2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000];
|
||||
|
||||
// precalculated arrays of `Digit`s for 10^(2^n)
|
||||
static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2];
|
||||
static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee];
|
||||
static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
|
||||
static POW10TO128: [Digit; 14] = [
|
||||
0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da,
|
||||
0xa6337f19, 0xe91f2603, 0x24e,
|
||||
// precalculated arrays of `Digit`s for 5^(2^n).
|
||||
static POW5TO16: [Digit; 2] = [0x86f26fc1, 0x23];
|
||||
static POW5TO32: [Digit; 3] = [0x85acef81, 0x2d6d415b, 0x4ee];
|
||||
static POW5TO64: [Digit; 5] = [0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
|
||||
static POW5TO128: [Digit; 10] = [
|
||||
0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19,
|
||||
0xe91f2603, 0x24e,
|
||||
];
|
||||
static POW10TO256: [Digit; 27] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70,
|
||||
0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
|
||||
0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7,
|
||||
static POW5TO256: [Digit; 19] = [
|
||||
0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e,
|
||||
0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7,
|
||||
0xf46eeddc, 0x5fdcefce, 0x553f7,
|
||||
];
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big {
|
||||
debug_assert!(n < 512);
|
||||
// Save ourself the left shift for the smallest cases.
|
||||
if n < 8 {
|
||||
return x.mul_small(POW10[n & 7]);
|
||||
}
|
||||
// Multiply by the powers of 5 and shift the 2s in at the end.
|
||||
// This keeps the intermediate products smaller and faster.
|
||||
if n & 7 != 0 {
|
||||
x.mul_small(POW10[n & 7]);
|
||||
x.mul_small(POW10[n & 7] >> (n & 7));
|
||||
}
|
||||
if n & 8 != 0 {
|
||||
x.mul_small(POW10[8]);
|
||||
x.mul_small(POW10[8] >> 8);
|
||||
}
|
||||
if n & 16 != 0 {
|
||||
x.mul_digits(&POW10TO16);
|
||||
x.mul_digits(&POW5TO16);
|
||||
}
|
||||
if n & 32 != 0 {
|
||||
x.mul_digits(&POW10TO32);
|
||||
x.mul_digits(&POW5TO32);
|
||||
}
|
||||
if n & 64 != 0 {
|
||||
x.mul_digits(&POW10TO64);
|
||||
x.mul_digits(&POW5TO64);
|
||||
}
|
||||
if n & 128 != 0 {
|
||||
x.mul_digits(&POW10TO128);
|
||||
x.mul_digits(&POW5TO128);
|
||||
}
|
||||
if n & 256 != 0 {
|
||||
x.mul_digits(&POW10TO256);
|
||||
x.mul_digits(&POW5TO256);
|
||||
}
|
||||
x
|
||||
x.mul_pow2(n)
|
||||
}
|
||||
|
||||
fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
|
||||
@ -62,7 +65,7 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
|
||||
x.div_rem_small(POW10[largest]);
|
||||
n -= largest;
|
||||
}
|
||||
x.div_rem_small(TWOPOW10[n]);
|
||||
x.div_rem_small(POW10[n] << 1);
|
||||
x
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ impl<T> [T] {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
|
||||
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
|
||||
#[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")]
|
||||
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
||||
if self.len() < N {
|
||||
None
|
||||
|
@ -455,8 +455,18 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||
|
||||
Ok(NonZero::new_unchecked(sinfo.cpu_count as usize))
|
||||
}
|
||||
} else if #[cfg(target_os = "vxworks")] {
|
||||
// Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF
|
||||
// expectations than the actual cores availability.
|
||||
extern "C" {
|
||||
fn vxCpuEnabledGet() -> libc::cpuset_t;
|
||||
}
|
||||
|
||||
// always fetches a valid bitmask
|
||||
let set = unsafe { vxCpuEnabledGet() };
|
||||
Ok(NonZero::new_unchecked(set.count_ones() as usize))
|
||||
} else {
|
||||
// FIXME: implement on vxWorks, Redox, l4re
|
||||
// FIXME: implement on Redox, l4re
|
||||
Err(io::const_io_error!(io::ErrorKind::Unsupported, "Getting the number of hardware threads is not supported on the target platform"))
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
_ => {
|
||||
|
@ -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)),
|
||||
|
@ -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()
|
||||
}
|
@ -9,6 +9,3 @@ pub mod llvm;
|
||||
pub mod python;
|
||||
pub mod rustc;
|
||||
pub mod rustdoc;
|
||||
|
||||
// Library-internal external dependency.
|
||||
mod cygpath;
|
||||
|
14
tests/crashes/128094.rs
Normal file
14
tests/crashes/128094.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//@ known-bug: rust-lang/rust#128094
|
||||
//@ compile-flags: -Zmir-opt-level=5 --edition=2018
|
||||
|
||||
pub enum Request {
|
||||
TestSome(T),
|
||||
}
|
||||
|
||||
pub async fn handle_event(event: Request) {
|
||||
async move {
|
||||
static instance: Request = Request { bar: 17 };
|
||||
&instance
|
||||
}
|
||||
.await;
|
||||
}
|
13
tests/crashes/128176.rs
Normal file
13
tests/crashes/128176.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//@ known-bug: rust-lang/rust#128176
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
trait X {
|
||||
type Y<const N: i16>;
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
|
||||
};
|
||||
|
||||
fn main() {}
|
7
tests/crashes/128190.rs
Normal file
7
tests/crashes/128190.rs
Normal file
@ -0,0 +1,7 @@
|
||||
//@ known-bug: rust-lang/rust#128190
|
||||
|
||||
fn a(&self) {
|
||||
15
|
||||
}
|
||||
|
||||
reuse a as b { struct S; }
|
5
tests/crashes/128327.rs
Normal file
5
tests/crashes/128327.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//@ known-bug: rust-lang/rust#128327
|
||||
|
||||
use std::ops::Deref;
|
||||
struct Apple((Apple, <&'static [f64] as Deref>::Target(Banana ? Citron)));
|
||||
fn main(){}
|
13
tests/crashes/128346.rs
Normal file
13
tests/crashes/128346.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//@ known-bug: rust-lang/rust#128346
|
||||
|
||||
macro_rules! one_rep {
|
||||
( $($a:ident)* ) => {
|
||||
A(
|
||||
const ${concat($a, Z)}: i32 = 3;
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
one_rep!(A B C);
|
||||
}
|
16
tests/crashes/128621-2.rs
Normal file
16
tests/crashes/128621-2.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ known-bug: rust-lang/rust#128621
|
||||
|
||||
#![feature(ptr_metadata)]
|
||||
use std::{ops::FnMut, ptr::Pointee};
|
||||
|
||||
pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(<T as Pointee>::Metadata) + 'a;
|
||||
|
||||
pub struct Emplacer<'a, T>(EmplacerFn<'a, T>);
|
||||
|
||||
impl<'a, T> Emplacer<'a, T> {
|
||||
pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self {
|
||||
unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
19
tests/crashes/128621.rs
Normal file
19
tests/crashes/128621.rs
Normal file
@ -0,0 +1,19 @@
|
||||
//@ known-bug: rust-lang/rust#128621
|
||||
|
||||
trait Trait {
|
||||
type Associated;
|
||||
}
|
||||
|
||||
impl Trait for i32 {
|
||||
type Associated = i64;
|
||||
}
|
||||
|
||||
trait Generic<T> {}
|
||||
|
||||
type TraitObject = dyn Generic<<i32 as Trait>::Associated>;
|
||||
|
||||
struct Wrap(TraitObject);
|
||||
|
||||
fn cast(x: *mut TraitObject) {
|
||||
x as *mut Wrap;
|
||||
}
|
@ -4,12 +4,8 @@
|
||||
// are exported, and that generics are only shown if explicitely requested.
|
||||
// See https://github.com/rust-lang/rust/issues/37530
|
||||
|
||||
//@ ignore-windows-msvc
|
||||
|
||||
//FIXME(Oneirical): This currently uses llvm-nm for symbol detection. However,
|
||||
// the custom Rust-based solution of #128314 may prove to be an interesting alternative.
|
||||
|
||||
use run_make_support::{bin_name, dynamic_lib_name, is_darwin, is_windows, llvm_nm, regex, rustc};
|
||||
use run_make_support::object::read::Object;
|
||||
use run_make_support::{bin_name, dynamic_lib_name, is_msvc, object, regex, rfs, rustc};
|
||||
|
||||
fn main() {
|
||||
let cdylib_name = dynamic_lib_name("a_cdylib");
|
||||
@ -64,16 +60,15 @@ fn main() {
|
||||
);
|
||||
|
||||
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
|
||||
// if is_windows() {
|
||||
// // Check that an executable does not export any dynamic symbols
|
||||
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
|
||||
//, false);
|
||||
// symbols_check(
|
||||
// &exe_name,
|
||||
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
// false,
|
||||
// );
|
||||
// }
|
||||
if is_msvc() {
|
||||
// Check that an executable does not export any dynamic symbols
|
||||
symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
|
||||
symbols_check(
|
||||
&exe_name,
|
||||
SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// Check the combined case, where we generate a cdylib and an rlib in the same
|
||||
// compilation session:
|
||||
@ -131,44 +126,37 @@ fn main() {
|
||||
);
|
||||
|
||||
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
|
||||
// if is_windows() {
|
||||
// // Check that an executable does not export any dynamic symbols
|
||||
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
|
||||
//, false);
|
||||
// symbols_check(
|
||||
// &exe_name,
|
||||
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
// false,
|
||||
// );
|
||||
// }
|
||||
if is_msvc() {
|
||||
// Check that an executable does not export any dynamic symbols
|
||||
symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
|
||||
symbols_check(
|
||||
&exe_name,
|
||||
SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) {
|
||||
let mut nm = llvm_nm();
|
||||
if is_windows() {
|
||||
nm.arg("--extern-only");
|
||||
} else if is_darwin() {
|
||||
nm.arg("--extern-only").arg("--defined-only");
|
||||
} else {
|
||||
nm.arg("--dynamic");
|
||||
let binary_data = rfs::read(path);
|
||||
let file = object::File::parse(&*binary_data).unwrap();
|
||||
let mut found: u64 = 0;
|
||||
for export in file.exports().unwrap() {
|
||||
let name = std::str::from_utf8(export.name()).unwrap();
|
||||
if has_symbol(name, symbol_check_type) {
|
||||
found += 1;
|
||||
}
|
||||
}
|
||||
let out = nm.input(path).run().stdout_utf8();
|
||||
assert_eq!(
|
||||
out.lines()
|
||||
.filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type))
|
||||
.count()
|
||||
== 1,
|
||||
exists_once
|
||||
);
|
||||
assert_eq!(found, exists_once as u64);
|
||||
}
|
||||
|
||||
fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool {
|
||||
fn has_symbol(name: &str, symbol_check_type: SymbolCheckType) -> bool {
|
||||
if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {
|
||||
line.contains(expected)
|
||||
name.contains(expected)
|
||||
} else {
|
||||
let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();
|
||||
regex.is_match(line)
|
||||
regex.is_match(name)
|
||||
}
|
||||
}
|
||||
|
||||
|
22
tests/rustdoc-js/self-is-not-generic.js
Normal file
22
tests/rustdoc-js/self-is-not-generic.js
Normal file
@ -0,0 +1,22 @@
|
||||
// exact-check
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'query': 'A -> A',
|
||||
'others': [
|
||||
{ 'path': 'self_is_not_generic::Thing', 'name': 'from' }
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'A -> B',
|
||||
'others': [
|
||||
{ 'path': 'self_is_not_generic::Thing', 'name': 'try_from' }
|
||||
],
|
||||
},
|
||||
{
|
||||
'query': 'Combine -> Combine',
|
||||
'others': [
|
||||
{ 'path': 'self_is_not_generic::Combine', 'name': 'combine' }
|
||||
],
|
||||
}
|
||||
];
|
11
tests/rustdoc-js/self-is-not-generic.rs
Normal file
11
tests/rustdoc-js/self-is-not-generic.rs
Normal file
@ -0,0 +1,11 @@
|
||||
pub trait Combine {
|
||||
fn combine(&self, other: &Self) -> Self;
|
||||
}
|
||||
|
||||
pub struct Thing;
|
||||
|
||||
impl Combine for Thing {
|
||||
fn combine(&self, other: &Self) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user