diff --git a/Cargo.lock b/Cargo.lock index e82eb89ef21e9..8a7abafbc90b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -295,7 +295,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.51.0" +version = "0.52.0" dependencies = [ "anyhow", "atty", diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 0550f53a96fb3..00354b42ebb7c 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -1,15 +1,15 @@ //! # Token Streams //! //! `TokenStream`s represent syntactic objects before they are converted into ASTs. -//! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s, -//! which are themselves a single `Token` or a `Delimited` subsequence of tokens. +//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s, +//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens. //! //! ## Ownership //! //! `TokenStream`s are persistent data structures constructed as ropes with reference //! counted-children. In general, this means that calling an operation on a `TokenStream` //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to -//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts, +//! the original. This essentially coerces `TokenStream`s into "views" of their subparts, //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking //! ownership of the original. @@ -24,9 +24,9 @@ use smallvec::{smallvec, SmallVec}; use std::{fmt, iter, mem}; -/// When the main rust parser encounters a syntax-extension invocation, it -/// parses the arguments to the invocation as a token-tree. This is a very -/// loose structure, such that all sorts of different AST-fragments can +/// When the main Rust parser encounters a syntax-extension invocation, it +/// parses the arguments to the invocation as a token tree. This is a very +/// loose structure, such that all sorts of different AST fragments can /// be passed to syntax extensions using a uniform type. /// /// If the syntax extension is an MBE macro, it will attempt to match its @@ -38,9 +38,9 @@ use std::{fmt, iter, mem}; /// Nothing special happens to misnamed or misplaced `SubstNt`s. #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum TokenTree { - /// A single token + /// A single token. Token(Token), - /// A delimited sequence of token trees + /// A delimited sequence of token trees. Delimited(DelimSpan, DelimToken, TokenStream), } @@ -62,7 +62,7 @@ where } impl TokenTree { - /// Checks if this TokenTree is equal to the other, regardless of span information. + /// Checks if this `TokenTree` is equal to the other, regardless of span information. pub fn eq_unspanned(&self, other: &TokenTree) -> bool { match (self, other) { (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind, @@ -73,7 +73,7 @@ impl TokenTree { } } - /// Retrieves the TokenTree's span. + /// Retrieves the `TokenTree`'s span. pub fn span(&self) -> Span { match self { TokenTree::Token(token) => token.span, @@ -140,7 +140,7 @@ impl CreateTokenStream for TokenStream { } } -/// A lazy version of `TokenStream`, which defers creation +/// A lazy version of [`TokenStream`], which defers creation /// of an actual `TokenStream` until it is needed. /// `Box` is here only to reduce the structure size. #[derive(Clone)] @@ -188,11 +188,12 @@ impl HashStable for LazyTokenStream { } } -/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s. +/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. /// /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. -/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. +/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for +/// backwards compatability. #[derive(Clone, Debug, Default, Encodable, Decodable)] pub struct TokenStream(pub(crate) Lrc>); @@ -429,7 +430,7 @@ impl TokenStreamBuilder { } } -/// By-reference iterator over a `TokenStream`. +/// By-reference iterator over a [`TokenStream`]. #[derive(Clone)] pub struct CursorRef<'t> { stream: &'t TokenStream, @@ -457,8 +458,8 @@ impl<'t> Iterator for CursorRef<'t> { } } -/// Owning by-value iterator over a `TokenStream`. -/// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones. +/// Owning by-value iterator over a [`TokenStream`]. +// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones. #[derive(Clone)] pub struct Cursor { pub stream: TokenStream, diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 3fc56eecdd0da..07fde27b5a314 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -9,7 +9,7 @@ use rustc_codegen_ssa::{ }; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Ty; -use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size}; +use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size}; fn round_pointer_up_to_alignment( bx: &mut Builder<'a, 'll, 'tcx>, @@ -52,7 +52,7 @@ fn emit_direct_ptr_va_arg( let next = bx.inbounds_gep(addr, &[full_direct_size]); bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi); - if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.endian == "big" { + if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big { let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32); let adjusted = bx.inbounds_gep(addr, &[adjusted_size]); (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align) @@ -105,7 +105,7 @@ fn emit_aapcs_va_arg( let mut end = bx.build_sibling_block("va_arg.end"); let zero = bx.const_i32(0); let offset_align = Align::from_bytes(4).unwrap(); - assert!(&*bx.tcx().sess.target.endian == "little"); + assert_eq!(bx.tcx().sess.target.endian, Endian::Little); let gr_type = target_ty.is_any_ptr() || target_ty.is_integral(); let (reg_off, reg_top_index, slot_size) = if gr_type { diff --git a/compiler/rustc_error_codes/src/error_codes/E0435.md b/compiler/rustc_error_codes/src/error_codes/E0435.md index 424e5ce1e2e5b..798a20d48b65b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0435.md +++ b/compiler/rustc_error_codes/src/error_codes/E0435.md @@ -7,6 +7,12 @@ let foo = 42; let a: [u8; foo]; // error: attempt to use a non-constant value in a constant ``` +'constant' means 'a compile-time value'. + +More details can be found in the [Variables and Mutability] section of the book. + +[Variables and Mutability]: https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants + To fix this error, please replace the value with a constant. Example: ``` diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index c0045d3f79be1..297f3d19ca178 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -33,7 +33,7 @@ impl<'a> Cursor<'a> { #[cfg(not(debug_assertions))] { - '\0' + EOF_CHAR } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 420c002c5fc46..a6a61ffc5dae5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -359,7 +359,7 @@ impl CheckAttrVisitor<'tcx> { return false; } let item_name = self.tcx.hir().name(hir_id); - if item_name.to_string() == doc_alias { + if &*item_name.as_str() == doc_alias { self.tcx .sess .struct_span_err( diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 809de9beff625..6a181dbab5af7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -398,13 +398,19 @@ impl<'a> Resolver<'a> { err.help("use the `|| { ... }` closure form instead"); err } - ResolutionError::AttemptToUseNonConstantValueInConstant => { + ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg) => { let mut err = struct_span_err!( self.session, span, E0435, "attempt to use a non-constant value in a constant" ); + err.span_suggestion( + ident.span, + &sugg, + "".to_string(), + Applicability::MaybeIncorrect, + ); err.span_label(span, "non-constant value"); err } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2e738ce8daccd..4d956e7f0d2c3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -92,6 +92,12 @@ crate enum HasGenericParams { No, } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +crate enum ConstantItemKind { + Const, + Static, +} + /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -119,7 +125,7 @@ crate enum RibKind<'a> { /// /// The `bool` indicates if this constant may reference generic parameters /// and is used to only allow generic parameters to be used in trivial constant expressions. - ConstantItemRibKind(bool), + ConstantItemRibKind(bool, Option<(Ident, ConstantItemKind)>), /// We passed through a module. ModuleRibKind(Module<'a>), @@ -145,7 +151,7 @@ impl RibKind<'_> { NormalRibKind | ClosureOrAsyncRibKind | FnItemRibKind - | ConstantItemRibKind(_) + | ConstantItemRibKind(..) | ModuleRibKind(_) | MacroDefinition(_) | ConstParamTyRibKind => false, @@ -634,7 +640,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Note that we might not be inside of an repeat expression here, // but considering that `IsRepeatExpr` is only relevant for // non-trivial constants this is doesn't matter. - self.with_constant_rib(IsRepeatExpr::No, true, |this| { + self.with_constant_rib(IsRepeatExpr::No, true, None, |this| { this.smart_resolve_path( ty.id, qself.as_ref(), @@ -843,7 +849,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | ClosureOrAsyncRibKind | FnItemRibKind | ItemRibKind(..) - | ConstantItemRibKind(_) + | ConstantItemRibKind(..) | ModuleRibKind(..) | ForwardTyParamBanRibKind | ConstParamTyRibKind => { @@ -970,6 +976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_constant_rib( IsRepeatExpr::No, true, + None, |this| this.visit_expr(expr), ); } @@ -1012,11 +1019,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); if let Some(expr) = expr { + let constant_item_kind = match item.kind { + ItemKind::Const(..) => ConstantItemKind::Const, + ItemKind::Static(..) => ConstantItemKind::Static, + _ => unreachable!(), + }; // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. - this.with_constant_rib(IsRepeatExpr::No, true, |this| { - this.visit_expr(expr) - }); + this.with_constant_rib( + IsRepeatExpr::No, + true, + Some((item.ident, constant_item_kind)), + |this| this.visit_expr(expr), + ); } }); } @@ -1118,15 +1133,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, is_repeat: IsRepeatExpr, is_trivial: bool, + item: Option<(Ident, ConstantItemKind)>, f: impl FnOnce(&mut Self), ) { debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial); - self.with_rib(ValueNS, ConstantItemRibKind(is_trivial), |this| { + self.with_rib(ValueNS, ConstantItemRibKind(is_trivial, item), |this| { this.with_rib( TypeNS, - ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial), + ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item), |this| { - this.with_label_rib(ConstantItemRibKind(is_trivial), f); + this.with_label_rib(ConstantItemRibKind(is_trivial, item), f); }, ) }); @@ -1266,6 +1282,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_constant_rib( IsRepeatExpr::No, true, + None, |this| { visit::walk_assoc_item( this, @@ -2200,6 +2217,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.with_constant_rib( is_repeat, constant.value.is_potential_trivial_const_param(), + None, |this| { visit::walk_anon_const(this, constant); }, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dba30f6664007..a6d0240b6fdcf 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -64,7 +64,7 @@ use tracing::debug; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; -use late::{HasGenericParams, PathSource, Rib, RibKind::*}; +use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; type Res = def::Res; @@ -210,7 +210,7 @@ enum ResolutionError<'a> { /// Error E0434: can't capture dynamic environment in a fn item. CannotCaptureDynamicEnvironmentInFnItem, /// Error E0435: attempt to use a non-constant value in a constant. - AttemptToUseNonConstantValueInConstant, + AttemptToUseNonConstantValueInConstant(Ident, String), /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>), /// Error E0128: type parameters with a default cannot use forward-declared identifiers. @@ -1837,14 +1837,16 @@ impl<'a> Resolver<'a> { // Use the rib kind to determine whether we are resolving parameters // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; - if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { + if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident) + { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( i, rib_ident, - res, + *res, record_used, path_span, + *original_rib_ident_def, ribs, ))); } @@ -2556,6 +2558,7 @@ impl<'a> Resolver<'a> { mut res: Res, record_used: bool, span: Span, + original_rib_ident_def: Ident, all_ribs: &[Rib<'a>], ) -> Res { const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation"; @@ -2602,10 +2605,31 @@ impl<'a> Resolver<'a> { res_err = Some(CannotCaptureDynamicEnvironmentInFnItem); } } - ConstantItemRibKind(_) => { + ConstantItemRibKind(_, item) => { // Still doesn't deal with upvars if record_used { - self.report_error(span, AttemptToUseNonConstantValueInConstant); + let (span, resolution_error) = + if let Some((ident, constant_item_kind)) = item { + let kind_str = match constant_item_kind { + ConstantItemKind::Const => "const", + ConstantItemKind::Static => "static", + }; + let sugg = format!( + "consider using `let` instead of `{}`", + kind_str + ); + (span, AttemptToUseNonConstantValueInConstant(ident, sugg)) + } else { + let sugg = "consider using `const` instead of `let`"; + ( + rib_ident.span, + AttemptToUseNonConstantValueInConstant( + original_rib_ident_def, + sugg.to_string(), + ), + ) + }; + self.report_error(span, resolution_error); } return Res::Err; } @@ -2641,7 +2665,7 @@ impl<'a> Resolver<'a> { in_ty_param_default = true; continue; } - ConstantItemRibKind(trivial) => { + ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. if !(trivial @@ -2734,7 +2758,7 @@ impl<'a> Resolver<'a> { in_ty_param_default = true; continue; } - ConstantItemRibKind(trivial) => { + ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. if !(trivial diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 62859f4bef430..b653de42b361e 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -819,7 +819,7 @@ pub fn default_configuration(sess: &Session) -> CrateConfig { } } ret.insert((sym::target_arch, Some(Symbol::intern(arch)))); - ret.insert((sym::target_endian, Some(Symbol::intern(end)))); + ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str())))); ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index a43080b09e9a1..61bfd58533a91 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -4,11 +4,14 @@ pub use Primitive::*; use crate::spec::Target; use std::convert::{TryFrom, TryInto}; +use std::fmt; use std::num::NonZeroUsize; use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub}; +use std::str::FromStr; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable_Generic; +use rustc_serialize::json::{Json, ToJson}; use rustc_span::Span; pub mod call; @@ -152,22 +155,19 @@ impl TargetDataLayout { } // Perform consistency checks against the Target information. - let endian_str = match dl.endian { - Endian::Little => "little", - Endian::Big => "big", - }; - if endian_str != target.endian { + if dl.endian != target.endian { return Err(format!( "inconsistent target specification: \"data-layout\" claims \ - architecture is {}-endian, while \"target-endian\" is `{}`", - endian_str, target.endian + architecture is {}-endian, while \"target-endian\" is `{}`", + dl.endian.as_str(), + target.endian.as_str(), )); } if dl.pointer_size.bits() != target.pointer_width.into() { return Err(format!( "inconsistent target specification: \"data-layout\" claims \ - pointers are {}-bit, while \"target-pointer-width\" is `{}`", + pointers are {}-bit, while \"target-pointer-width\" is `{}`", dl.pointer_size.bits(), target.pointer_width )); @@ -234,6 +234,39 @@ pub enum Endian { Big, } +impl Endian { + pub fn as_str(&self) -> &'static str { + match self { + Self::Little => "little", + Self::Big => "big", + } + } +} + +impl fmt::Debug for Endian { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +impl FromStr for Endian { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "little" => Ok(Self::Little), + "big" => Ok(Self::Big), + _ => Err(format!(r#"unknown endian: "{}""#, s)), + } + } +} + +impl ToJson for Endian { + fn to_json(&self) -> Json { + self.as_str().to_json() + } +} + /// Size of a type in bytes. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] #[derive(HashStable_Generic)] diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs index c6586b79b87f8..255740cb9c045 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs @@ -1,5 +1,6 @@ // Targets the Big endian Cortex-R4/R5 processor (ARMv7-R) +use crate::abi::Endian; use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; use crate::spec::{Target, TargetOptions}; @@ -11,7 +12,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs index e3d4397f6123f..eb82e4d17b0ef 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs @@ -1,5 +1,6 @@ // Targets the Cortex-R4F/R5F processor (ARMv7-R) +use crate::abi::Endian; use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; use crate::spec::{Target, TargetOptions}; @@ -11,7 +12,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs index daa0d9da1725e..53398539ac20f 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), features: "+mips64r2".to_string(), diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs index db8d0c04e6f5c..329fbd2272177 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -11,6 +12,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs index a7ec1f19c9de7..b41b28cbc87c2 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, cpu: "mips32r2".to_string(), features: "+mips32r2,+fpxx,+nooddspreg".to_string(), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs index 1ebe577bc1c4a..3713af43d7360 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -11,6 +12,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs index 2123d5e1a0f78..042ec9140fac0 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float".to_string(), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs index 11b3734a10507..a81c90fe0cdec 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), arch: "mips".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, cpu: "mips32r6".to_string(), features: "+mips32r6".to_string(), max_atomic_width: Some(32), diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs index 6282c9e1d54b6..3bf837fbb411e 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { @@ -7,7 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, // NOTE(mips64r6) matches C toolchain cpu: "mips64r6".to_string(), features: "+mips64r6".to_string(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8d72df6850fc2..abc96eb3322ec 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -34,6 +34,7 @@ //! the target's settings, though `target-feature` and `link-args` will *add* //! to the list specified by the target, rather than replace. +use crate::abi::Endian; use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_serialize::json::{Json, ToJson}; @@ -705,8 +706,8 @@ pub struct TargetOptions { /// Whether the target is built-in or loaded from a custom target specification. pub is_builtin: bool, - /// String to use as the `target_endian` `cfg` variable. Defaults to "little". - pub endian: String, + /// Used as the `target_endian` `cfg` variable. Defaults to little endian. + pub endian: Endian, /// Width of c_int type. Defaults to "32". pub c_int_width: String, /// OS name to use for conditional compilation (`target_os`). Defaults to "none". @@ -1010,7 +1011,7 @@ impl Default for TargetOptions { fn default() -> TargetOptions { TargetOptions { is_builtin: false, - endian: "little".to_string(), + endian: Endian::Little, c_int_width: "32".to_string(), os: "none".to_string(), env: String::new(), @@ -1439,8 +1440,10 @@ impl Target { } ); } + if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { + base.endian = s.parse()?; + } key!(is_builtin, bool); - key!(endian = "target-endian"); key!(c_int_width = "target-c-int-width"); key!(os); key!(env); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs index 626865aa242fe..3dddeb1129cbe 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -11,6 +12,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index 03322818d33c3..751022c124baa 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions}; pub fn target() -> Target { @@ -15,6 +16,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index 231539756f375..546dfbab6c701 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -11,6 +12,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index 1c83e3e64d436..bb55872109c33 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -11,6 +12,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64".to_string(), arch: "powerpc64".to_string(), - options: TargetOptions { endian: "big".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs index 3a9271247b042..70dd0b2aee691 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -10,6 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs index 105a0b21aaf01..66118b74955ec 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -10,6 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs index 49d329447893a..679a3a2f6aacb 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -10,6 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs index 387d6cdc456a7..1245098329aee 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -10,10 +11,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { - endian: "big".to_string(), - mcount: "__mcount".to_string(), - ..base - }, + options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs index 20ffa07b9979f..bb943a8825c6c 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -11,10 +12,6 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { - endian: "big".to_string(), - features: "+secure-plt".to_string(), - ..base - }, + options: TargetOptions { endian: Endian::Big, features: "+secure-plt".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs index 0e713fccd23b8..4b4f118ba49bd 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -12,7 +13,7 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), options: TargetOptions { - endian: "big".to_string(), + endian: Endian::Big, // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2 features: "+secure-plt,+msync".to_string(), ..base diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs index d6e8e6ee220e6..4eeea9bedfb50 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs @@ -1,8 +1,9 @@ +use crate::abi::Endian; use crate::spec::Target; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.endian = "big".to_string(); + base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".to_string(); // FIXME: The data_layout string below and the ABI implementation in diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs index e9b5520ac3d37..e1aa48872b906 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs @@ -1,8 +1,9 @@ +use crate::abi::Endian; use crate::spec::Target; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.endian = "big".to_string(); + base.endian = Endian::Big; base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs index c8e90f832d034..7d685c83100d3 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs @@ -1,3 +1,4 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { @@ -11,10 +12,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), arch: "sparc64".to_string(), - options: TargetOptions { - endian: "big".to_string(), - mcount: "__mcount".to_string(), - ..base - }, + options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs index 630ce6123f9ec..63b13fad4f7f6 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs @@ -1,8 +1,9 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::openbsd_base::opts(); - base.endian = "big".to_string(); + base.endian = Endian::Big; base.cpu = "v9".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs index aae186b2293c7..9e8fbff81c538 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs @@ -1,8 +1,9 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); - base.endian = "big".to_string(); + base.endian = Endian::Big; base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string()); diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs index 5f99e0b14f9fb..9ac56cae9168a 100644 --- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs @@ -1,8 +1,9 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, Target}; pub fn target() -> Target { let mut base = super::solaris_base::opts(); - base.endian = "big".to_string(); + base.endian = Endian::Big; base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); // llvm calls this "v9" base.cpu = "v9".to_string(); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 58bf74c8cf470..bd01271ec150f 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1872,19 +1872,24 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_strip)] /// let v = &[10, 40, 30]; /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..])); /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..])); /// assert_eq!(v.strip_prefix(&[50]), None); /// assert_eq!(v.strip_prefix(&[10, 50]), None); + /// + /// let prefix : &str = "he"; + /// assert_eq!(b"hello".strip_prefix(prefix.as_bytes()), + /// Some(b"llo".as_ref())); /// ``` #[must_use = "returns the subslice without modifying the original"] - #[unstable(feature = "slice_strip", issue = "73413")] - pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]> + #[stable(feature = "slice_strip", since = "1.50.0")] + pub fn strip_prefix + ?Sized>(&self, prefix: &P) -> Option<&[T]> where T: PartialEq, { + // This function will need rewriting if and when SlicePattern becomes more sophisticated. + let prefix = prefix.as_slice(); let n = prefix.len(); if n <= self.len() { let (head, tail) = self.split_at(n); @@ -1905,7 +1910,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(slice_strip)] /// let v = &[10, 40, 30]; /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..])); /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..])); @@ -1913,11 +1917,13 @@ impl [T] { /// assert_eq!(v.strip_suffix(&[50, 30]), None); /// ``` #[must_use = "returns the subslice without modifying the original"] - #[unstable(feature = "slice_strip", issue = "73413")] - pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]> + #[stable(feature = "slice_strip", since = "1.50.0")] + pub fn strip_suffix + ?Sized>(&self, suffix: &P) -> Option<&[T]> where T: PartialEq, { + // This function will need rewriting if and when SlicePattern becomes more sophisticated. + let suffix = suffix.as_slice(); let (len, n) = (self.len(), suffix.len()); if n <= len { let (head, tail) = self.split_at(len - n); @@ -3310,3 +3316,35 @@ impl Default for &mut [T] { &mut [] } } + +#[unstable(feature = "slice_pattern", reason = "stopgap trait for slice patterns", issue = "56345")] +/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`. At a future +/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to +/// `str`) to slices, and then this trait will be replaced or abolished. +pub trait SlicePattern { + /// The element type of the slice being matched on. + type Item; + + /// Currently, the consumers of `SlicePattern` need a slice. + fn as_slice(&self) -> &[Self::Item]; +} + +#[stable(feature = "slice_strip", since = "1.50.0")] +impl SlicePattern for [T] { + type Item = T; + + #[inline] + fn as_slice(&self) -> &[Self::Item] { + self + } +} + +#[stable(feature = "slice_strip", since = "1.50.0")] +impl SlicePattern for [T; N] { + type Item = T; + + #[inline] + fn as_slice(&self) -> &[Self::Item] { + self + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2c6f03fe22406..15ef5d1619ba3 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -307,7 +307,6 @@ #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] -#![feature(slice_strip)] #![feature(staged_api)] #![feature(std_internals)] #![feature(stdsimd)] diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index cc31461646cc9..38791fcea5484 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -291,7 +291,9 @@ impl Item { } } - /// See comments on next_def_id + /// See the documentation for [`next_def_id()`]. + /// + /// [`next_def_id()`]: DocContext::next_def_id() crate fn is_fake(&self) -> bool { MAX_DEF_ID.with(|m| { m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4aeca0faea76a..43aaefa087073 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -120,14 +120,20 @@ impl<'tcx> DocContext<'tcx> { r } - // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly - // refactoring either librustdoc or librustc_middle. In particular, allowing new DefIds to be - // registered after the AST is constructed would require storing the defid mapping in a - // RefCell, decreasing the performance for normal compilation for very little gain. - // - // Instead, we construct 'fake' def ids, which start immediately after the last DefId. - // In the Debug impl for clean::Item, we explicitly check for fake - // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds + /// Create a new "fake" [`DefId`]. + /// + /// This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly + /// refactoring either rustdoc or [`rustc_middle`]. In particular, allowing new [`DefId`]s + /// to be registered after the AST is constructed would require storing the [`DefId`] mapping + /// in a [`RefCell`], decreasing the performance for normal compilation for very little gain. + /// + /// Instead, we construct "fake" [`DefId`]s, which start immediately after the last `DefId`. + /// In the [`Debug`] impl for [`clean::Item`], we explicitly check for fake `DefId`s, + /// as we'll end up with a panic if we use the `DefId` `Debug` impl for fake `DefId`s. + /// + /// [`RefCell`]: std::cell::RefCell + /// [`Debug`]: std::fmt::Debug + /// [`clean::Item`]: crate::clean::types::Item crate fn next_def_id(&self, crate_num: CrateNum) -> DefId { let start_def_id = { let num_def_ids = if crate_num == LOCAL_CRATE { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 28b118ea78e61..8dad26dced956 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1412,6 +1412,7 @@ h4 > .notable-traits { .sidebar > .block.version { border-bottom: none; margin-top: 12px; + margin-bottom: 0; } nav.sub { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0cefbb34791b2..11ee59b2401c8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -394,10 +394,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ns, impl_, ) - .map(|item| match item.kind { - ty::AssocKind::Fn => "method", - ty::AssocKind::Const => "associatedconstant", - ty::AssocKind::Type => "associatedtype", + .map(|item| { + let kind = item.kind; + self.kind_side_channel.set(Some((kind.as_def_kind(), item.def_id))); + match kind { + ty::AssocKind::Fn => "method", + ty::AssocKind::Const => "associatedconstant", + ty::AssocKind::Type => "associatedtype", + } }) .map(|out| { ( @@ -1142,55 +1146,75 @@ impl LinkCollector<'_, '_> { callback, ); }; - match res { - Res::Primitive(_) => match disambiguator { - Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => { - Some(ItemLink { link: ori_link.link, link_text, did: None, fragment }) - } - Some(other) => { - report_mismatch(other, Disambiguator::Primitive); - None - } - }, - Res::Def(kind, id) => { - debug!("intra-doc link to {} resolved to {:?}", path_str, res); - - // Disallow e.g. linking to enums with `struct@` - debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator); - match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) { - | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const))) - // NOTE: this allows 'method' to mean both normal functions and associated functions - // This can't cause ambiguity because both are in the same namespace. - | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn))) - // These are namespaces; allow anything in the namespace to match - | (_, Some(Disambiguator::Namespace(_))) - // If no disambiguator given, allow anything - | (_, None) - // All of these are valid, so do nothing - => {} - (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {} - (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => { - report_mismatch(specified, Disambiguator::Kind(kind)); - return None; - } + + let verify = |kind: DefKind, id: DefId| { + debug!("intra-doc link to {} resolved to {:?}", path_str, res); + + // Disallow e.g. linking to enums with `struct@` + debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator); + match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) { + | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const))) + // NOTE: this allows 'method' to mean both normal functions and associated functions + // This can't cause ambiguity because both are in the same namespace. + | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn))) + // These are namespaces; allow anything in the namespace to match + | (_, Some(Disambiguator::Namespace(_))) + // If no disambiguator given, allow anything + | (_, None) + // All of these are valid, so do nothing + => {} + (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {} + (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => { + report_mismatch(specified, Disambiguator::Kind(kind)); + return None; } + } + + // item can be non-local e.g. when using #[doc(primitive = "pointer")] + if let Some((src_id, dst_id)) = id + .as_local() + .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id))) + { + use rustc_hir::def_id::LOCAL_CRATE; - // item can be non-local e.g. when using #[doc(primitive = "pointer")] - if let Some((src_id, dst_id)) = id - .as_local() - .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id))) + let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id); + let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id); + + if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src) + && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst) { - use rustc_hir::def_id::LOCAL_CRATE; + privacy_error(cx, &item, &path_str, dox, &ori_link); + } + } - let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id); - let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id); + Some((kind, id)) + }; - if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src) - && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst) - { - privacy_error(cx, &item, &path_str, dox, &ori_link); + match res { + Res::Primitive(_) => { + if let Some((kind, id)) = self.kind_side_channel.take() { + // We're actually resolving an associated item of a primitive, so we need to + // verify the disambiguator (if any) matches the type of the associated item. + // This case should really follow the same flow as the `Res::Def` branch below, + // but attempting to add a call to `clean::register_res` causes an ICE. @jyn514 + // thinks `register_res` is only needed for cross-crate re-exports, but Rust + // doesn't allow statements like `use str::trim;`, making this a (hopefully) + // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677 + // for discussion on the matter. + verify(kind, id)?; + } else { + match disambiguator { + Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {} + Some(other) => { + report_mismatch(other, Disambiguator::Primitive); + return None; + } } } + Some(ItemLink { link: ori_link.link, link_text, did: None, fragment }) + } + Res::Def(kind, id) => { + let (kind, id) = verify(kind, id)?; let id = clean::register_res(cx, rustc_hir::def::Res::Def(kind, id)); Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment }) } diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index c4700b317efa0..cb87d54d08ec3 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -172,7 +172,7 @@ else # files are redundant, so there is no need to generate `expected_*.json` files or # compare actual JSON results.) - $(DIFF) --ignore-matching-lines='::<.*>.*:$$' \ + $(DIFF) --ignore-matching-lines='^ | .*::<.*>.*:$' --ignore-matching-lines='^ | <.*>::.*:$' \ expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \ ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \ >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \ diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs new file mode 100644 index 0000000000000..0d1d5d1134b7b --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs @@ -0,0 +1,3 @@ +#![deny(broken_intra_doc_links)] +//! [static@u8::MIN] +//~^ ERROR incompatible link kind diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr new file mode 100644 index 0000000000000..ed1c10f9e0cb8 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr @@ -0,0 +1,15 @@ +error: incompatible link kind for `u8::MIN` + --> $DIR/incompatible-primitive-disambiguator.rs:2:6 + | +LL | //! [static@u8::MIN] + | ^^^^^^^^^^^^^^ help: to link to the associated constant, prefix with `const@`: `const@u8::MIN` + | +note: the lint level is defined here + --> $DIR/incompatible-primitive-disambiguator.rs:1:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: this link resolved to an associated constant, which is not a static + +error: aborting due to previous error + diff --git a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs new file mode 100644 index 0000000000000..acdd07566c94d --- /dev/null +++ b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs @@ -0,0 +1,4 @@ +#![deny(broken_intra_doc_links)] +// @has primitive_disambiguators/index.html +// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim' +//! [str::trim()] diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr index 349aa0d07c5d8..21827d1fd8743 100644 --- a/src/test/ui/error-codes/E0435.stderr +++ b/src/test/ui/error-codes/E0435.stderr @@ -1,6 +1,8 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/E0435.rs:3:17 | +LL | let foo = 42u32; + | --- help: consider using `const` instead of `let` LL | let _: [u8; foo]; | ^^^ non-constant value diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr index e983fdecdba79..ad5f13d067230 100644 --- a/src/test/ui/impl-trait/bindings.stderr +++ b/src/test/ui/impl-trait/bindings.stderr @@ -2,25 +2,33 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/bindings.rs:5:29 | LL | const foo: impl Clone = x; - | ^ non-constant value + | --- ^ non-constant value + | | + | help: consider using `let` instead of `const` error[E0435]: attempt to use a non-constant value in a constant --> $DIR/bindings.rs:11:33 | LL | const foo: impl Clone = x; - | ^ non-constant value + | --- ^ non-constant value + | | + | help: consider using `let` instead of `const` error[E0435]: attempt to use a non-constant value in a constant --> $DIR/bindings.rs:18:33 | LL | const foo: impl Clone = x; - | ^ non-constant value + | --- ^ non-constant value + | | + | help: consider using `let` instead of `const` error[E0435]: attempt to use a non-constant value in a constant --> $DIR/bindings.rs:25:33 | LL | const foo: impl Clone = x; - | ^ non-constant value + | --- ^ non-constant value + | | + | help: consider using `let` instead of `const` warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bindings.rs:1:12 diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr index e232d17e6d7a6..201b7e8549cb1 100644 --- a/src/test/ui/issues/issue-27433.stderr +++ b/src/test/ui/issues/issue-27433.stderr @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-27433.rs:3:23 | LL | const FOO : u32 = foo; - | ^^^ non-constant value + | --- ^^^ non-constant value + | | + | help: consider using `let` instead of `const` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr index d54bbbcdc3325..ba29d1becb85a 100644 --- a/src/test/ui/issues/issue-3521-2.stderr +++ b/src/test/ui/issues/issue-3521-2.stderr @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-3521-2.rs:4:23 | LL | static y: isize = foo + 1; - | ^^^ non-constant value + | - ^^^ non-constant value + | | + | help: consider using `let` instead of `static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/issues/issue-3521.stderr index ae1998752693c..8473526006c5c 100644 --- a/src/test/ui/issues/issue-3521.stderr +++ b/src/test/ui/issues/issue-3521.stderr @@ -1,6 +1,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-3521.rs:6:15 | +LL | let foo = 100; + | --- help: consider using `const` instead of `let` +... LL | Bar = foo | ^^^ non-constant value diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr index d6a6e8379602d..7cee497b0bced 100644 --- a/src/test/ui/issues/issue-3668-2.stderr +++ b/src/test/ui/issues/issue-3668-2.stderr @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-3668-2.rs:2:27 | LL | static child: isize = x + 1; - | ^ non-constant value + | ----- ^ non-constant value + | | + | help: consider using `let` instead of `static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr index 98cd3631a5365..e45472929ab31 100644 --- a/src/test/ui/issues/issue-3668.stderr +++ b/src/test/ui/issues/issue-3668.stderr @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-3668.rs:8:34 | LL | static childVal: Box

= self.child.get(); - | ^^^^ non-constant value + | -------- ^^^^ non-constant value + | | + | help: consider using `let` instead of `static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42060.stderr b/src/test/ui/issues/issue-42060.stderr index 72408c7919456..dc089b856bb23 100644 --- a/src/test/ui/issues/issue-42060.stderr +++ b/src/test/ui/issues/issue-42060.stderr @@ -1,12 +1,16 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-42060.rs:3:23 | +LL | let thing = (); + | ----- help: consider using `const` instead of `let` LL | let other: typeof(thing) = thing; | ^^^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-42060.rs:9:13 | +LL | let q = 1; + | - help: consider using `const` instead of `let` LL | ::N | ^ non-constant value diff --git a/src/test/ui/issues/issue-44239.stderr b/src/test/ui/issues/issue-44239.stderr index bc5a6a03f0314..bbd3d116c9634 100644 --- a/src/test/ui/issues/issue-44239.stderr +++ b/src/test/ui/issues/issue-44239.stderr @@ -1,6 +1,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-44239.rs:6:26 | +LL | let n = 0; + | - help: consider using `const` instead of `let` +... LL | const N: usize = n; | ^ non-constant value diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr index b947cb7e19c20..01da6bcf49aaa 100644 --- a/src/test/ui/non-constant-expr-for-arr-len.stderr +++ b/src/test/ui/non-constant-expr-for-arr-len.stderr @@ -1,6 +1,8 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/non-constant-expr-for-arr-len.rs:5:22 | +LL | fn bar(n: usize) { + | - help: consider using `const` instead of `let` LL | let _x = [0; n]; | ^ non-constant value diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index 5fcda348ab3f4..aa1b2e60d51f8 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -1,6 +1,8 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/repeat_count.rs:5:17 | +LL | let n = 1; + | - help: consider using `const` instead of `let` LL | let a = [0; n]; | ^ non-constant value diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr index c5dcfa7a43133..df791435e88b9 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.stderr +++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/type-dependent-def-issue-49241.rs:3:22 | LL | const l: usize = v.count(); - | ^ non-constant value + | - ^ non-constant value + | | + | help: consider using `let` instead of `const` error: aborting due to previous error diff --git a/src/tools/cargo b/src/tools/cargo index 75d5d8cffe346..329895f5b52a3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 75d5d8cffe3464631f82dcd3c470b78dc1dda8bb +Subproject commit 329895f5b52a358e5d9ecb26215708b5cb31d906