提交 2dc5b602 编写于 作者: B bors

Auto merge of #71410 - JohnTitor:rollup-vh6dut5, r=JohnTitor

Rollup of 7 pull requests

Successful merges:

 - #70998 (Suggest `-> impl Trait` and `-> Box<dyn Trait>` on fn that doesn't return)
 - #71236 (Remove unused rustc_serialize::hex module)
 - #71366 (Use assoc int consts3)
 - #71372 (Fix #! (shebang) stripping account space issue)
 - #71384 (Fix stage0.txt version number comment)
 - #71390 (Fix incorrect description of E0690)
 - #71399 (Clean up E0554 explanation)

Failed merges:

r? @ghost
......@@ -3577,7 +3577,6 @@ version = "0.0.0"
dependencies = [
"log",
"rustc_ast",
"rustc_data_structures",
"rustc_span",
]
......@@ -3594,7 +3593,6 @@ dependencies = [
"rustc_session",
"rustc_span",
"serialize",
"smallvec 1.0.0",
]
[[package]]
......@@ -3666,7 +3664,6 @@ dependencies = [
"rustc_hir",
"rustc_incremental",
"rustc_index",
"rustc_metadata",
"rustc_middle",
"rustc_session",
"rustc_span",
......@@ -3809,7 +3806,6 @@ version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_hir",
"rustc_span",
"rustc_target",
......@@ -3879,7 +3875,6 @@ dependencies = [
"rustc_expand",
"rustc_hir",
"rustc_incremental",
"rustc_infer",
"rustc_lint",
"rustc_metadata",
"rustc_middle",
......@@ -3924,7 +3919,6 @@ dependencies = [
"rustc_feature",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
......@@ -3986,10 +3980,8 @@ dependencies = [
"backtrace",
"bitflags",
"byteorder",
"jobserver",
"log",
"measureme",
"parking_lot 0.10.2",
"polonius-engine",
"rustc-rayon",
"rustc-rayon-core",
......@@ -4023,7 +4015,6 @@ dependencies = [
"polonius-engine",
"rustc_apfloat",
"rustc_ast",
"rustc_ast_pretty",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
......@@ -4079,7 +4070,6 @@ dependencies = [
"rustc_lexer",
"rustc_session",
"rustc_span",
"smallvec 1.0.0",
"unicode-normalization",
]
......@@ -4092,10 +4082,8 @@ dependencies = [
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
......@@ -4143,7 +4131,6 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_macros",
"rustc_span",
"serialize",
"smallvec 1.0.0",
......@@ -4296,10 +4283,8 @@ dependencies = [
"rustc_data_structures",
"rustc_hir",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"smallvec 1.0.0",
]
......
......@@ -2,7 +2,6 @@
use crate::fmt;
use crate::intrinsics;
use crate::ops::{Add, AddAssign, Try};
use crate::usize;
use super::{from_fn, LoopState};
use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
......
use crate::convert::TryFrom;
use crate::mem;
use crate::ops::{self, Add, Sub, Try};
use crate::usize;
use super::{FusedIterator, TrustedLen};
......
use crate::fmt;
use crate::marker;
use crate::usize;
use super::{FusedIterator, TrustedLen};
......
......@@ -265,7 +265,7 @@ fn abs_private(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool {
self.abs_private() == INFINITY
self.abs_private() == Self::INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
......@@ -287,7 +287,7 @@ pub fn is_infinite(self) -> bool {
pub fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
self.abs_private() < INFINITY
self.abs_private() < Self::INFINITY
}
/// Returns `true` if the number is neither zero, infinite,
......
......@@ -264,7 +264,7 @@ fn abs_private(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool {
self.abs_private() == INFINITY
self.abs_private() == Self::INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
......@@ -286,7 +286,7 @@ pub fn is_infinite(self) -> bool {
pub fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
self.abs_private() < INFINITY
self.abs_private() < Self::INFINITY
}
/// Returns `true` if the number is neither zero, infinite,
......
......@@ -2,7 +2,6 @@
use crate::num::dec2flt::rawfp::RawFloat;
use crate::num::FpCategory;
use crate::{f32, f64};
/// Decoded unsigned finite value, such that:
///
......
......@@ -123,7 +123,6 @@
)]
pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
use crate::i16;
pub mod decoder;
pub mod estimator;
......
......@@ -14,14 +14,14 @@
concat!("The smallest value that can be represented by this integer type.
Use [`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN) instead."),
#[$attr]
pub const MIN: $T = $T::min_value();
pub const MIN: $T = $T::MIN;
}
doc_comment! {
concat!("The largest value that can be represented by this integer type.
Use [`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX) instead."),
#[$attr]
pub const MAX: $T = $T::max_value();
pub const MAX: $T = $T::MAX;
}
)
}
......@@ -34,7 +34,7 @@ fn repeat_byte(b: u8) -> usize {
#[cfg(not(target_pointer_width = "16"))]
#[inline]
fn repeat_byte(b: u8) -> usize {
(b as usize) * (crate::usize::MAX / 255)
(b as usize) * (usize::MAX / 255)
}
/// Returns the first index matching the byte `x` in `text`.
......
......@@ -28,7 +28,6 @@
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::fmt;
use crate::intrinsics::{assume, exact_div, is_aligned_and_not_null, unchecked_sub};
use crate::isize;
use crate::iter::*;
use crate::marker::{self, Copy, Send, Sized, Sync};
use crate::mem;
......
......@@ -46,7 +46,6 @@
use crate::cmp;
use crate::fmt;
use crate::slice::memchr;
use crate::usize;
// Pattern
......
......@@ -12,9 +12,9 @@
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
//! ```
use crate::fmt;
use crate::iter::Sum;
use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use crate::{fmt, u64};
const NANOS_PER_SEC: u32 = 1_000_000_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
......
......@@ -12,5 +12,4 @@ doctest = false
[dependencies]
log = "0.4"
rustc_span = { path = "../librustc_span" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_ast = { path = "../librustc_ast" }
......@@ -17,6 +17,5 @@ rustc_span = { path = "../librustc_span" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_macros = { path = "../librustc_macros" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_session = { path = "../librustc_session" }
rustc_ast = { path = "../librustc_ast" }
......@@ -34,4 +34,3 @@ rustc_incremental = { path = "../librustc_incremental" }
rustc_index = { path = "../librustc_index" }
rustc_target = { path = "../librustc_target" }
rustc_session = { path = "../librustc_session" }
rustc_metadata = { path = "../librustc_metadata" }
......@@ -29,8 +29,6 @@
#[macro_use]
extern crate cfg_if;
pub use rustc_serialize::hex::ToHex;
#[inline(never)]
#[cold]
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
......
Feature attributes are only allowed on the nightly release channel. Stable or
beta compilers will not comply.
Example of erroneous code (on a stable compiler):
Erroneous code example:
```ignore (depends on release channel)
#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the
......
......@@ -14,7 +14,7 @@ struct LengthWithUnit<U> { // error: transparent struct needs exactly one
Because transparent structs are represented exactly like one of their fields at
run time, said field must be uniquely determined. If there is no field, or if
there are multiple fields, it is not clear how the struct should be represented.
Note that fields of zero-typed types (e.g., `PhantomData`) can also exist
Note that fields of zero-sized types (e.g., `PhantomData`) can also exist
alongside the field that contains the actual data, they do not count for this
error. When generic types are involved (as in the above example), an error is
reported because the type parameter could be non-zero-sized.
......
......@@ -2,8 +2,7 @@ Return types cannot be `dyn Trait`s as they must be `Sized`.
Erroneous code example:
```compile_fail,E0277
# // FIXME: after E0746 is in beta, change the above
```compile_fail,E0746
trait T {
fn bar(&self);
}
......
......@@ -13,6 +13,5 @@ doctest = false
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
rustc_hir = { path = "../librustc_hir" }
rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_span = { path = "../librustc_span" }
rustc_ast = { path = "../librustc_ast" }
......@@ -32,7 +32,6 @@ rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
rustc_symbol_mangling = { path = "../librustc_symbol_mangling" }
rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true }
rustc_hir = { path = "../librustc_hir" }
rustc_infer = { path = "../librustc_infer" }
rustc_metadata = { path = "../librustc_metadata" }
rustc_mir = { path = "../librustc_mir" }
rustc_mir_build = { path = "../librustc_mir_build" }
......
......@@ -236,12 +236,17 @@ pub enum Base {
/// (e.g. "#![deny(missing_docs)]").
pub fn strip_shebang(input: &str) -> Option<usize> {
debug_assert!(!input.is_empty());
if !input.starts_with("#!") || input.starts_with("#![") {
let s: &str = &remove_whitespace(input);
if !s.starts_with("#!") || s.starts_with("#![") {
return None;
}
Some(input.find('\n').unwrap_or(input.len()))
}
fn remove_whitespace(s: &str) -> String {
s.chars().filter(|c| !c.is_whitespace()).collect()
}
/// Parses the first token from the provided input string.
pub fn first_token(input: &str) -> Token {
debug_assert!(!input.is_empty());
......
......@@ -145,4 +145,22 @@ fn test_unterminated_no_pound() {
}),
);
}
#[test]
fn test_valid_shebang() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#!/usr/bin/rustrun";
let actual = strip_shebang(input);
let expected: Option<usize> = Some(18);
assert_eq!(expected, actual);
}
#[test]
fn test_invalid_shebang_valid_rust_syntax() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#! [bad_attribute]";
let actual = strip_shebang(input);
let expected: Option<usize> = None;
assert_eq!(expected, actual);
}
}
......@@ -23,5 +23,4 @@ rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_index = { path = "../librustc_index" }
rustc_session = { path = "../librustc_session" }
rustc_infer = { path = "../librustc_infer" }
rustc_trait_selection = { path = "../librustc_trait_selection" }
......@@ -12,7 +12,6 @@ doctest = false
[dependencies]
arena = { path = "../libarena" }
bitflags = "1.2.1"
jobserver = "0.1"
scoped-tls = "1.0"
log = { version = "0.4", features = ["release_max_level_info", "std"] }
rustc-rayon = "0.3.0"
......@@ -32,7 +31,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc_ast = { path = "../librustc_ast" }
rustc_span = { path = "../librustc_span" }
backtrace = "0.3.40"
parking_lot = "0.10"
byteorder = { version = "1.3" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
measureme = "0.7.1"
......
......@@ -17,7 +17,6 @@ log = "0.4"
log_settings = "0.1.1"
polonius-engine = "0.12.0"
rustc_middle = { path = "../librustc_middle" }
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
rustc_attr = { path = "../librustc_attr" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
......
......@@ -17,7 +17,6 @@ rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_lexer = { path = "../librustc_lexer" }
rustc_errors = { path = "../librustc_errors" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_session = { path = "../librustc_session" }
rustc_span = { path = "../librustc_span" }
rustc_ast = { path = "../librustc_ast" }
......
......@@ -14,10 +14,8 @@ rustc_middle = { path = "../librustc_middle" }
rustc_attr = { path = "../librustc_attr" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_feature = { path = "../librustc_feature" }
rustc_hir = { path = "../librustc_hir" }
rustc_index = { path = "../librustc_index" }
rustc_infer = { path = "../librustc_infer" }
rustc_session = { path = "../librustc_session" }
rustc_target = { path = "../librustc_target" }
rustc_ast = { path = "../librustc_ast" }
......
......@@ -15,7 +15,6 @@ rustc-rayon-core = "0.3.0"
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_index = { path = "../librustc_index" }
rustc_macros = { path = "../librustc_macros" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc_span = { path = "../librustc_span" }
parking_lot = "0.10"
......
......@@ -13,7 +13,7 @@
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
use rustc_middle::ty::TypeckTables;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
self, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
......@@ -826,12 +826,28 @@ fn suggest_impl_trait(
.iter()
.filter_map(|expr| tables.node_type_opt(expr.hir_id))
.map(|ty| self.resolve_vars_if_possible(&ty));
let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
(None, true),
|(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold(
(None, true, true),
|(last_ty, mut same, only_never_return): (std::option::Option<Ty<'_>>, bool, bool),
ty| {
let ty = self.resolve_vars_if_possible(&ty);
same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
(Some(ty), same)
same &=
ty.kind != ty::Error
&& last_ty.map_or(true, |last_ty| {
// FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
// *after* in the dependency graph.
match (&ty.kind, &last_ty.kind) {
(Infer(InferTy::IntVar(_)), Infer(InferTy::IntVar(_)))
| (Infer(InferTy::FloatVar(_)), Infer(InferTy::FloatVar(_)))
| (Infer(InferTy::FreshIntTy(_)), Infer(InferTy::FreshIntTy(_)))
| (
Infer(InferTy::FreshFloatTy(_)),
Infer(InferTy::FreshFloatTy(_)),
) => true,
_ => ty == last_ty,
}
});
(Some(ty), same, only_never_return && matches!(ty.kind, ty::Never))
},
);
let all_returns_conform_to_trait =
......@@ -840,13 +856,14 @@ fn suggest_impl_trait(
ty::Dynamic(predicates, _) => {
let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
let param_env = ty::ParamEnv::empty();
ret_types.all(|returned_ty| {
predicates.iter().all(|predicate| {
let pred = predicate.with_self_ty(self.tcx, returned_ty);
let obl = Obligation::new(cause.clone(), param_env, pred);
self.predicate_may_hold(&obl)
only_never_return
|| ret_types.all(|returned_ty| {
predicates.iter().all(|predicate| {
let pred = predicate.with_self_ty(self.tcx, returned_ty);
let obl = Obligation::new(cause.clone(), param_env, pred);
self.predicate_may_hold(&obl)
})
})
})
}
_ => false,
}
......@@ -855,21 +872,19 @@ fn suggest_impl_trait(
};
let sm = self.tcx.sess.source_map();
let (snippet, last_ty) =
if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
// Verify that we're dealing with a return `dyn Trait`
ret_ty.span.overlaps(span),
&ret_ty.kind,
sm.span_to_snippet(ret_ty.span),
// If any of the return types does not conform to the trait, then we can't
// suggest `impl Trait` nor trait objects, it is a type mismatch error.
all_returns_conform_to_trait,
last_ty,
) {
(snippet, last_ty)
} else {
return false;
};
let snippet = if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = (
// Verify that we're dealing with a return `dyn Trait`
ret_ty.span.overlaps(span),
&ret_ty.kind,
sm.span_to_snippet(ret_ty.span),
// If any of the return types does not conform to the trait, then we can't
// suggest `impl Trait` nor trait objects: it is a type mismatch error.
all_returns_conform_to_trait,
) {
snippet
} else {
return false;
};
err.code(error_code!(E0746));
err.set_primary_message("return type cannot have an unboxed trait object");
err.children.clear();
......@@ -881,13 +896,22 @@ fn suggest_impl_trait(
#using-trait-objects-that-allow-for-values-of-different-types>";
let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
if all_returns_have_same_type {
if only_never_return {
// No return paths, probably using `panic!()` or similar.
// Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
suggest_trait_object_return_type_alternatives(
err,
ret_ty.span,
trait_obj,
is_object_safe,
);
} else if let (Some(last_ty), true) = (last_ty, all_returns_have_same_type) {
// Suggest `-> impl Trait`.
err.span_suggestion(
ret_ty.span,
&format!(
"return `impl {1}` instead, as all return paths are of type `{}`, \
which implements `{1}`",
"use `impl {1}` as the return type, as all return paths are of type `{}`, \
which implements `{1}`",
last_ty, trait_obj,
),
format!("impl {}", trait_obj),
......@@ -925,8 +949,8 @@ fn suggest_impl_trait(
}
err.note(trait_obj_msg);
err.note(&format!(
"if all the returned values were of the same type you could use \
`impl {}` as the return type",
"if all the returned values were of the same type you could use `impl {}` as the \
return type",
trait_obj,
));
err.note(impl_trait_msg);
......@@ -1813,3 +1837,39 @@ fn next_type_param_name(&self, name: Option<&str>) -> String {
.to_string()
}
}
fn suggest_trait_object_return_type_alternatives(
err: &mut DiagnosticBuilder<'tcx>,
ret_ty: Span,
trait_obj: &str,
is_object_safe: bool,
) {
err.span_suggestion(
ret_ty,
"use some type `T` that is `T: Sized` as the return type if all return paths have the \
same type",
"T".to_string(),
Applicability::MaybeIncorrect,
);
err.span_suggestion(
ret_ty,
&format!(
"use `impl {}` as the return type if all return paths have the same type but you \
want to expose only the trait in the signature",
trait_obj,
),
format!("impl {}", trait_obj),
Applicability::MaybeIncorrect,
);
if is_object_safe {
err.span_suggestion(
ret_ty,
&format!(
"use a boxed trait object if all return paths implement trait `{}`",
trait_obj,
),
format!("Box<dyn {}>", trait_obj),
Applicability::MaybeIncorrect,
);
}
}
......@@ -13,8 +13,6 @@ log = { version = "0.4" }
rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_hir = { path = "../librustc_hir" }
rustc_macros = { path = "../librustc_macros" }
rustc_target = { path = "../librustc_target" }
rustc_ast = { path = "../librustc_ast" }
rustc_span = { path = "../librustc_span" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
......
......@@ -1305,7 +1305,6 @@ fn check_fn<'a, 'tcx>(
let hir = tcx.hir();
let declared_ret_ty = fn_sig.output();
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
let revealed_ret_ty =
fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty, decl.output.span());
debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
......@@ -1374,7 +1373,25 @@ fn check_fn<'a, 'tcx>(
inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
fcx.check_return_expr(&body.value);
if let ty::Dynamic(..) = declared_ret_ty.kind {
// FIXME: We need to verify that the return type is `Sized` after the return expression has
// been evaluated so that we have types available for all the nodes being returned, but that
// requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
// causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
// while keeping the current ordering we will ignore the tail expression's type because we
// don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
// because we will trigger "unreachable expression" lints unconditionally.
// Because of all of this, we perform a crude check to know whether the simplest `!Sized`
// case that a newcomer might make, returning a bare trait, and in that case we populate
// the tail expression's type so that the suggestion will be correct, but ignore all other
// possible cases.
fcx.check_expr(&body.value);
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
tcx.sess.delay_span_bug(decl.output.span(), "`!Sized` return type");
} else {
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
fcx.check_return_expr(&body.value);
}
// We insert the deferred_generator_interiors entry after visiting the body.
// This ensures that all nested generators appear before the entry of this generator.
......
//! Hex binary-to-text encoding
pub use self::FromHexError::*;
use std::error;
use std::fmt;
/// A trait for converting a value to hexadecimal encoding
pub trait ToHex {
/// Converts the value of `self` to a hex value, returning the owned
/// string.
fn to_hex(&self) -> String;
}
const CHARS: &[u8] = b"0123456789abcdef";
impl ToHex for [u8] {
/// Turn a vector of `u8` bytes into a hexadecimal string.
///
/// # Examples
///
/// ```
/// #![feature(rustc_private)]
///
/// extern crate serialize;
/// use serialize::hex::ToHex;
///
/// fn main () {
/// let str = [52,32].to_hex();
/// println!("{}", str);
/// }
/// ```
fn to_hex(&self) -> String {
let mut v = Vec::with_capacity(self.len() * 2);
for &byte in self {
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
}
unsafe { String::from_utf8_unchecked(v) }
}
}
/// A trait for converting hexadecimal encoded values
pub trait FromHex {
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
/// into an owned vector of bytes, returning the vector.
fn from_hex(&self) -> Result<Vec<u8>, FromHexError>;
}
/// Errors that can occur when decoding a hex encoded string
#[derive(Copy, Clone, Debug)]
pub enum FromHexError {
/// The input contained a character not part of the hex format
InvalidHexCharacter(char, usize),
/// The input had an invalid length
InvalidHexLength,
}
impl fmt::Display for FromHexError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
InvalidHexCharacter(ch, idx) => {
write!(f, "Invalid character '{}' at position {}", ch, idx)
}
InvalidHexLength => write!(f, "Invalid input length"),
}
}
}
impl error::Error for FromHexError {}
impl FromHex for str {
/// Converts any hexadecimal encoded string (literal, `@`, `&`, or `~`)
/// to the byte values it encodes.
///
/// You can use the `String::from_utf8` function to turn a
/// `Vec<u8>` into a string with characters corresponding to those values.
///
/// # Examples
///
/// This converts a string literal to hexadecimal and back.
///
/// ```
/// #![feature(rustc_private)]
///
/// extern crate serialize;
/// use serialize::hex::{FromHex, ToHex};
///
/// fn main () {
/// let hello_str = "Hello, World".as_bytes().to_hex();
/// println!("{}", hello_str);
/// let bytes = hello_str.from_hex().unwrap();
/// println!("{:?}", bytes);
/// let result_str = String::from_utf8(bytes).unwrap();
/// println!("{}", result_str);
/// }
/// ```
fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
// This may be an overestimate if there is any whitespace
let mut b = Vec::with_capacity(self.len() / 2);
let mut modulus = 0;
let mut buf = 0;
for (idx, byte) in self.bytes().enumerate() {
buf <<= 4;
match byte {
b'A'..=b'F' => buf |= byte - b'A' + 10,
b'a'..=b'f' => buf |= byte - b'a' + 10,
b'0'..=b'9' => buf |= byte - b'0',
b' ' | b'\r' | b'\n' | b'\t' => {
buf >>= 4;
continue;
}
_ => {
let ch = self[idx..].chars().next().unwrap();
return Err(InvalidHexCharacter(ch, idx));
}
}
modulus += 1;
if modulus == 2 {
modulus = 0;
b.push(buf);
}
}
match modulus {
0 => Ok(b),
_ => Err(InvalidHexLength),
}
}
}
#[cfg(test)]
mod tests;
extern crate test;
use crate::hex::{FromHex, ToHex};
use test::Bencher;
#[test]
pub fn test_to_hex() {
assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172");
}
#[test]
pub fn test_from_hex_okay() {
assert_eq!("666f6f626172".from_hex().unwrap(), b"foobar");
assert_eq!("666F6F626172".from_hex().unwrap(), b"foobar");
}
#[test]
pub fn test_from_hex_odd_len() {
assert!("666".from_hex().is_err());
assert!("66 6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_invalid_char() {
assert!("66y6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_ignores_whitespace() {
assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(), b"foobar");
}
#[test]
pub fn test_to_hex_all_bytes() {
for i in 0..256 {
assert_eq!([i as u8].to_hex(), format!("{:02x}", i as usize));
}
}
#[test]
pub fn test_from_hex_all_bytes() {
for i in 0..256 {
let ii: &[u8] = &[i as u8];
assert_eq!(format!("{:02x}", i as usize).from_hex().unwrap(), ii);
assert_eq!(format!("{:02X}", i as usize).from_hex().unwrap(), ii);
}
}
#[bench]
pub fn bench_to_hex(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
b.iter(|| {
s.as_bytes().to_hex();
});
b.bytes = s.len() as u64;
}
#[bench]
pub fn bench_from_hex(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
let sb = s.as_bytes().to_hex();
b.iter(|| {
sb.from_hex().unwrap();
});
b.bytes = sb.len() as u64;
}
......@@ -25,7 +25,6 @@
mod collection_impls;
mod serialize;
pub mod hex;
pub mod json;
pub mod leb128;
......
......@@ -171,7 +171,7 @@ pub fn abs(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f32 {
if self.is_nan() { NAN } else { 1.0_f32.copysign(self) }
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
}
/// Returns a number composed of the magnitude of `self` and the sign of
......@@ -832,8 +832,8 @@ pub fn tanh(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asinh(self) -> f32 {
if self == NEG_INFINITY {
NEG_INFINITY
if self == Self::NEG_INFINITY {
Self::NEG_INFINITY
} else {
(self + ((self * self) + 1.0).sqrt()).ln().copysign(self)
}
......@@ -855,7 +855,7 @@ pub fn asinh(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acosh(self) -> f32 {
if self < 1.0 { crate::f32::NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
if self < 1.0 { Self::NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
}
/// Inverse hyperbolic tangent function.
......
......@@ -171,7 +171,7 @@ pub fn abs(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn signum(self) -> f64 {
if self.is_nan() { NAN } else { 1.0_f64.copysign(self) }
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
}
/// Returns a number composed of the magnitude of `self` and the sign of
......@@ -834,8 +834,8 @@ pub fn tanh(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asinh(self) -> f64 {
if self == NEG_INFINITY {
NEG_INFINITY
if self == Self::NEG_INFINITY {
Self::NEG_INFINITY
} else {
(self + ((self * self) + 1.0).sqrt()).ln().copysign(self)
}
......@@ -857,7 +857,7 @@ pub fn asinh(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acosh(self) -> f64 {
if self < 1.0 { NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
if self < 1.0 { Self::NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
}
/// Inverse hyperbolic tangent function.
......@@ -926,16 +926,16 @@ fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
if self > 0.0 {
log_fn(self)
} else if self == 0.0 {
NEG_INFINITY // log(0) = -Inf
Self::NEG_INFINITY // log(0) = -Inf
} else {
NAN // log(-n) = NaN
Self::NAN // log(-n) = NaN
}
} else if self.is_nan() {
self // log(NaN) = NaN
} else if self > 0.0 {
self // log(Inf) = Inf
} else {
NAN // log(-Inf) = NaN
Self::NAN // log(-Inf) = NaN
}
}
}
......
......@@ -1062,7 +1062,7 @@ fn new() -> ThreadId {
// If we somehow use up all our bits, panic so that we're not
// covering up subtle bugs of IDs being reused.
if COUNTER == crate::u64::MAX {
if COUNTER == u64::MAX {
panic!("failed to generate unique thread ID: bitspace exhausted");
}
......
......@@ -10,7 +10,7 @@
# If you're looking at this file on the master branch, you'll likely see that
# rustc and cargo are configured to `beta`, whereas if you're looking at a
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
# `0.(x+1).0` for Cargo where they were released on `date`.
date: 2020-03-12
rustc: beta
......
......@@ -51,7 +51,7 @@
// @has show_const_contents/constant.PI.html '; // 3.14159274f32'
pub use std::f32::consts::PI;
// @has show_const_contents/constant.MAX.html '= i32::max_value(); // 2_147_483_647i32'
// @has show_const_contents/constant.MAX.html '= i32::MAX; // 2_147_483_647i32'
pub use std::i32::MAX;
macro_rules! int_module {
......
......@@ -5,7 +5,7 @@ LL | fn foo() -> dyn Trait { Struct }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn foo() -> impl Trait { Struct }
| ^^^^^^^^^^
......@@ -17,7 +17,7 @@ LL | fn bar() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
|
LL | fn bar() -> impl Trait {
| ^^^^^^^^^^
......
......@@ -14,7 +14,7 @@ fn bap() -> Trait { Struct }
//~^ ERROR E0746
fn ban() -> dyn Trait { Struct }
//~^ ERROR E0746
fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0277
fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0746
// Suggest using `Box<dyn Trait>`
fn bal() -> dyn Trait { //~ ERROR E0746
if true {
......@@ -26,7 +26,7 @@ fn bax() -> dyn Trait { //~ ERROR E0746
if true {
Struct
} else {
42
42 //~ ERROR `if` and `else` have incompatible types
}
}
fn bam() -> Box<dyn Trait> {
......
......@@ -49,7 +49,7 @@ LL | fn bap() -> Trait { Struct }
| ^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn bap() -> impl Trait { Struct }
| ^^^^^^^^^^
......@@ -61,20 +61,29 @@ LL | fn ban() -> dyn Trait { Struct }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn ban() -> impl Trait { Struct }
| ^^^^^^^^^^
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
|
LL | fn bak() -> dyn Trait { unimplemented!() }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the return type of a function must have a statically known size
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
LL | fn bak() -> T { unimplemented!() }
| ^
help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | fn bak() -> impl Trait { unimplemented!() }
| ^^^^^^^^^^
help: use a boxed trait object if all return paths implement trait `Trait`
|
LL | fn bak() -> Box<dyn Trait> { unimplemented!() }
| ^^^^^^^^^^^^^^
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
......@@ -95,6 +104,18 @@ LL | }
LL | Box::new(42)
|
error[E0308]: `if` and `else` have incompatible types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
|
LL | / if true {
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | 42
| | ^^ expected struct `Struct`, found integer
LL | | }
| |_____- `if` and `else` have incompatible types
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
|
......@@ -249,7 +270,7 @@ LL | fn bat() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
|
LL | fn bat() -> impl Trait {
| ^^^^^^^^^^
......@@ -261,12 +282,12 @@ LL | fn bay() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
|
LL | fn bay() -> impl Trait {
| ^^^^^^^^^^
error: aborting due to 19 previous errors
error: aborting due to 20 previous errors
Some errors have detailed explanations: E0277, E0308, E0746.
For more information about an error, try `rustc --explain E0277`.
......@@ -2,7 +2,7 @@ pub trait AbstractRenderer {}
fn _create_render(_: &()) ->
dyn AbstractRenderer
//~^ ERROR the size for values of type
//~^ ERROR return type cannot have an unboxed trait object
{
match 0 {
_ => unimplemented!()
......
error[E0277]: the size for values of type `(dyn AbstractRenderer + 'static)` cannot be known at compilation time
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/issue-18107.rs:4:5
|
LL | dyn AbstractRenderer
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn AbstractRenderer + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the return type of a function must have a statically known size
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
LL | T
|
help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | impl AbstractRenderer
|
help: use a boxed trait object if all return paths implement trait `AbstractRenderer`
|
LL | Box<dyn AbstractRenderer>
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0746`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册