diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0fa5cde9424b5..c7af21027b8d3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -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, Determinacy>>>, diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs index 751edd3c79383..f8db6370653ab 100644 --- a/library/core/src/num/flt2dec/strategy/dragon.rs +++ b/library/core/src/num/flt2dec/strategy/dragon.rs @@ -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 } diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 83034761f3d16..44cb7b7b7ce5b 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -455,8 +455,18 @@ pub fn available_parallelism() -> io::Result> { 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")) } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d92bc8456649f..f8953f0ebcfb5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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) { 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 } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 324b633e8ea7e..cffadc7c10a91 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 739f6eb8cc89d..1d81ae3eb8ba7 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -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); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7d5a16bc7e3d5..4850500a1bfae 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -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 { - 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, Mutability), - SelfExplicit(Type), -} - impl Argument { - pub(crate) fn to_self(&self) -> Option { - 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, Option), /// 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) } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 2dd3041ab4c61..68266f3506a01 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -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), _ => { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bb5ac303ffd63..b5ab6a35fdb9d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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::SelfBorrowed(None, mutability) => { - write!( - f, - "{amp}{mutability}self", - 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::SelfExplicit(ref typ) => { + _ => { write!(f, "self: ")?; - typ.print(cx).fmt(f)?; + selfty.print(cx).fmt(f)?; } } } else { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9617f0d9a1f25..9074e40a53614 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -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), }; diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b3f4d82e054b8..8a2f31f7413e1 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -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,34 +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() { - 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, - ); + 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`... + 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, + }); + } } - // Otherwise we check if the trait bounds are "inlined" like `T: Option`... - if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { - for bound in bound.get_bounds().unwrap_or(&[]) { + 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( @@ -893,84 +933,22 @@ fn simplify_fn_type<'tcx, 'a>( ); } } - } - 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 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 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`, 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 is technically just Iterator, but we want to pretend it's more like this: - // - // fn next(self: Iterator) -> Option - 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; + 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`, 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, + ); + } + } + // 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 is technically just Iterator, but we want to pretend it's more like this: + // + // fn next(self: Iterator) -> Option + 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() { - *stored_bounds = type_bounds; + // 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, + }], + )) } - 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) }, - }); + 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) }, + }); + } } } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b56244f2d3b6d..b97d710c007ce 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -578,7 +578,7 @@ impl FromWithTcx 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 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)), diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 15e02d04393ce..f8d1666adda45 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -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; @@ -13,14 +12,31 @@ use crate::targets::{is_darwin, is_msvc, is_windows}; /// Built from a C file. #[track_caller] pub fn build_native_static_lib(lib_name: &str) -> PathBuf { + build_native_static_lib_internal(lib_name, false) +} + +/// Builds an optimized static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. +/// Built from a C file. +#[track_caller] +pub fn build_native_static_lib_optimized(lib_name: &str) -> PathBuf { + build_native_static_lib_internal(lib_name, true) +} + +#[track_caller] +fn build_native_static_lib_internal(lib_name: &str, optimzed: bool) -> PathBuf { let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; let src = format!("{lib_name}.c"); let lib_path = static_lib_name(lib_name); - if is_msvc() { - cc().arg("-c").out_exe(&obj_file).input(src).run(); - } else { - cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run(); - }; + + let mut cc = cc(); + if !is_msvc() { + cc.arg("-v"); + } + if optimzed { + cc.optimize(); + } + cc.arg("-c").out_exe(&obj_file).input(src).optimize().run(); + let obj_file = if is_msvc() { PathBuf::from(format!("{lib_name}.obj")) } else { @@ -44,8 +60,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(); diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 39ac3efef3948..011ad89e170a6 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -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); @@ -117,6 +115,17 @@ impl Cc { self.cmd.arg(path.as_ref()); self } + + /// Optimize the output. + /// Equivalent to `-O3` for GNU-compatible linkers or `-O2` for MSVC linkers. + pub fn optimize(&mut self) -> &mut Self { + if is_msvc() { + self.cmd.arg("-O2"); + } else { + self.cmd.arg("-O3"); + } + self + } } /// `EXTRACFLAGS` diff --git a/src/tools/run-make-support/src/external_deps/cygpath.rs b/src/tools/run-make-support/src/external_deps/cygpath.rs deleted file mode 100644 index 07d8e840a63a8..0000000000000 --- a/src/tools/run-make-support/src/external_deps/cygpath.rs +++ /dev/null @@ -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>(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() -} diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index a2dc426f3f229..f7c84724d0e07 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -9,6 +9,3 @@ pub mod llvm; pub mod python; pub mod rustc; pub mod rustdoc; - -// Library-internal external dependency. -mod cygpath; diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 63c4c4d88638a..244ffa17ecf45 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -45,7 +45,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust // These rely on external dependencies. pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; -pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_cxx}; +pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs new file mode 100644 index 0000000000000..105a1c84a6565 --- /dev/null +++ b/tests/crashes/128094.rs @@ -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; +} diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs new file mode 100644 index 0000000000000..70fada4f0fec2 --- /dev/null +++ b/tests/crashes/128176.rs @@ -0,0 +1,13 @@ +//@ known-bug: rust-lang/rust#128176 + +#![feature(generic_const_exprs)] +#![feature(object_safe_for_dispatch)] +trait X { + type Y; +} + +const _: () = { + fn f2<'a>(arg: Box = &'a ()>>) {} +}; + +fn main() {} diff --git a/tests/crashes/128190.rs b/tests/crashes/128190.rs new file mode 100644 index 0000000000000..0fa7027ae6091 --- /dev/null +++ b/tests/crashes/128190.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#128190 + +fn a(&self) { + 15 +} + +reuse a as b { struct S; } diff --git a/tests/crashes/128327.rs b/tests/crashes/128327.rs new file mode 100644 index 0000000000000..a63f758c317cf --- /dev/null +++ b/tests/crashes/128327.rs @@ -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(){} diff --git a/tests/crashes/128346.rs b/tests/crashes/128346.rs new file mode 100644 index 0000000000000..93d9c40a544e9 --- /dev/null +++ b/tests/crashes/128346.rs @@ -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); +} diff --git a/tests/crashes/128621-2.rs b/tests/crashes/128621-2.rs new file mode 100644 index 0000000000000..b1cdaf94984a8 --- /dev/null +++ b/tests/crashes/128621-2.rs @@ -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(::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() {} diff --git a/tests/crashes/128621.rs b/tests/crashes/128621.rs new file mode 100644 index 0000000000000..0a02352236dbb --- /dev/null +++ b/tests/crashes/128621.rs @@ -0,0 +1,19 @@ +//@ known-bug: rust-lang/rust#128621 + +trait Trait { + type Associated; +} + +impl Trait for i32 { + type Associated = i64; +} + +trait Generic {} + +type TraitObject = dyn Generic<::Associated>; + +struct Wrap(TraitObject); + +fn cast(x: *mut TraitObject) { + x as *mut Wrap; +} diff --git a/tests/run-make/link-args-order/rmake.rs b/tests/run-make/link-args-order/rmake.rs index d238ad23f27c7..b7ef8333267f2 100644 --- a/tests/run-make/link-args-order/rmake.rs +++ b/tests/run-make/link-args-order/rmake.rs @@ -3,15 +3,14 @@ // checks that linker arguments remain intact and in the order they were originally passed in. // See https://github.com/rust-lang/rust/pull/70665 -//@ ignore-msvc -// Reason: the ld linker does not exist on Windows. - -use run_make_support::rustc; +use run_make_support::{is_msvc, rustc}; fn main() { + let linker = if is_msvc() { "msvc" } else { "ld" }; + rustc() .input("empty.rs") - .linker_flavor("ld") + .linker_flavor(linker) .link_arg("a") .link_args("b c") .link_args("d e") @@ -20,7 +19,7 @@ fn main() { .assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#); rustc() .input("empty.rs") - .linker_flavor("ld") + .linker_flavor(linker) .arg("-Zpre-link-arg=a") .arg("-Zpre-link-args=b c") .arg("-Zpre-link-args=d e") diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs index 9bff3a4b44c7d..6075f31095424 100644 --- a/tests/run-make/link-dedup/rmake.rs +++ b/tests/run-make/link-dedup/rmake.rs @@ -5,20 +5,37 @@ // Without the --cfg flag, there should be a single -ltesta, no more, no less. // See https://github.com/rust-lang/rust/pull/84794 -//@ ignore-msvc +use std::fmt::Write; -use run_make_support::rustc; +use run_make_support::{is_msvc, rustc}; fn main() { rustc().input("depa.rs").run(); rustc().input("depb.rs").run(); rustc().input("depc.rs").run(); + let output = rustc().input("empty.rs").cfg("bar").run_fail(); - output.assert_stderr_contains(r#""-ltesta" "-ltestb" "-ltesta""#); - let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_contains(r#""-ltesta""#); - let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_not_contains(r#""-ltestb""#); + output.assert_stderr_contains(needle_from_libs(&["testa", "testb", "testa"])); + let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_not_contains(r#""-ltesta" "-ltesta" "-ltesta""#); + output.assert_stderr_contains(needle_from_libs(&["testa"])); + output.assert_stderr_not_contains(needle_from_libs(&["testb"])); + output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa", "testa"])); + // Adjacent identical native libraries are no longer deduplicated if + // they come from different crates (https://github.com/rust-lang/rust/pull/103311) + // so the following will fail: + //output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa"])); +} + +fn needle_from_libs(libs: &[&str]) -> String { + let mut needle = String::new(); + for lib in libs { + if is_msvc() { + let _ = needle.write_fmt(format_args!(r#""{lib}.lib" "#)); + } else { + let _ = needle.write_fmt(format_args!(r#""-l{lib}" "#)); + } + } + needle.pop(); // remove trailing space + needle } diff --git a/tests/run-make/no-duplicate-libs/main.rs b/tests/run-make/no-duplicate-libs/main.rs index b25ef35ada68e..d8d5d58bc477a 100644 --- a/tests/run-make/no-duplicate-libs/main.rs +++ b/tests/run-make/no-duplicate-libs/main.rs @@ -1,6 +1,6 @@ -#[link(name = "foo")] // linker should drop this library, no symbols used -#[link(name = "bar")] // symbol comes from this library -#[link(name = "foo")] // now linker picks up `foo` b/c `bar` library needs it +#[link(name = "foo", kind = "static")] // linker should drop this library, no symbols used +#[link(name = "bar", kind = "static")] // symbol comes from this library +#[link(name = "foo", kind = "static")] // now linker picks up `foo` b/c `bar` library needs it extern "C" { fn bar(); } diff --git a/tests/run-make/no-duplicate-libs/rmake.rs b/tests/run-make/no-duplicate-libs/rmake.rs index 469348e266cb8..b67067909b24b 100644 --- a/tests/run-make/no-duplicate-libs/rmake.rs +++ b/tests/run-make/no-duplicate-libs/rmake.rs @@ -9,9 +9,6 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -//@ ignore-msvc -// Reason: native compilation results in an unresolved external symbol - use run_make_support::{build_native_static_lib, run, rustc}; fn main() { diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index 87477c122301d..73e651ae26035 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -2,15 +2,17 @@ // see https://github.com/rust-lang/compiler-team/issues/510 for more info //@ needs-rust-lld -//@ ignore-msvc //@ ignore-s390x lld does not yet support s390x as target use std::process::Output; use run_make_support::regex::Regex; -use run_make_support::rustc; +use run_make_support::{is_msvc, rustc}; fn main() { + // lld-link is used if msvc, otherwise a gnu-compatible lld is used. + let linker_version_flag = if is_msvc() { "--version" } else { "Wl,-v" }; + // Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by // asking the linker to display its version number with a link-arg. let output = rustc() @@ -18,7 +20,7 @@ fn main() { .arg("-Zlinker-features=+lld") .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") - .link_arg("-Wl,-v") + .link_arg(linker_version_flag) .input("main.rs") .run(); assert!( @@ -27,10 +29,10 @@ fn main() { output.stderr_utf8() ); - // It should not be used when we explictly opt-out of lld. + // It should not be used when we explicitly opt-out of lld. let output = rustc() .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") - .link_arg("-Wl,-v") + .link_arg(linker_version_flag) .arg("-Zlinker-features=-lld") .input("main.rs") .run(); @@ -44,7 +46,7 @@ fn main() { // times to rustc. let output = rustc() .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") - .link_arg("-Wl,-v") + .link_arg(linker_version_flag) .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") .arg("-Zlinker-features=-lld") diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index b37ff44f4ead6..f84e63ef74e8d 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -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) } } diff --git a/tests/run-make/zero-extend-abi-param-passing/param_passing.rs b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs index c11f3cc72bdf2..addde6b8ee36f 100644 --- a/tests/run-make/zero-extend-abi-param-passing/param_passing.rs +++ b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs @@ -2,7 +2,7 @@ // LLVM optimization choices. See additional note below for an // example. -#[link(name = "bad")] +#[link(name = "bad", kind = "static")] extern "C" { pub fn c_read_value(a: u32, b: u32, c: u32) -> u16; } diff --git a/tests/run-make/zero-extend-abi-param-passing/rmake.rs b/tests/run-make/zero-extend-abi-param-passing/rmake.rs index aed27f7f5ab8a..96dbbd0627c25 100644 --- a/tests/run-make/zero-extend-abi-param-passing/rmake.rs +++ b/tests/run-make/zero-extend-abi-param-passing/rmake.rs @@ -6,20 +6,13 @@ // while simultaneously interfacing with a C library and using the -O3 flag. // See https://github.com/rust-lang/rust/issues/97463 -//@ ignore-msvc -// Reason: the rustc compilation fails due to an unresolved external symbol - //@ ignore-cross-compile // Reason: The compiled binary is executed. - -use run_make_support::{cc, is_msvc, llvm_ar, run, rustc, static_lib_name}; +use run_make_support::{build_native_static_lib_optimized, run, rustc}; fn main() { - // The issue exercised by this test specifically needs needs `-O` - // flags (like `-O3`) to reproduce. Thus, we call `cc()` instead of - // the nicer `build_native_static_lib`. - cc().arg("-c").arg("-O3").out_exe("bad.o").input("bad.c").run(); - llvm_ar().obj_to_ar().output_input(static_lib_name("bad"), "bad.o").run(); - rustc().input("param_passing.rs").arg("-lbad").opt_level("3").run(); + // The issue exercised by this test specifically needs an optimized native static lib. + build_native_static_lib_optimized("bad"); + rustc().input("param_passing.rs").opt_level("3").run(); run("param_passing"); } diff --git a/tests/rustdoc-js/self-is-not-generic.js b/tests/rustdoc-js/self-is-not-generic.js new file mode 100644 index 0000000000000..0fdf5b4117d8f --- /dev/null +++ b/tests/rustdoc-js/self-is-not-generic.js @@ -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' } + ], + } +]; diff --git a/tests/rustdoc-js/self-is-not-generic.rs b/tests/rustdoc-js/self-is-not-generic.rs new file mode 100644 index 0000000000000..d6a96acb73caf --- /dev/null +++ b/tests/rustdoc-js/self-is-not-generic.rs @@ -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 + } +}