Auto merge of #60510 - Centril:rollup-gsndjbp, r=Centril
Rollup of 12 pull requests Successful merges: - #59928 (Make deprecation lint `ambiguous_associated_items` deny-by-default) - #60220 (report fatal errors during doctest parsing) - #60373 (Tidy: ensure lang features are sorted by since) - #60388 (Disallow non-explicit elided lifetimes in async fn) - #60393 ( Do not suggest incorrect syntax on pattern type error due to borrow) - #60401 (Rename `RUST_LOG` to `RUSTC_LOG`) - #60409 (Require a trait in the bounds of existential types) - #60455 (Resolve match arm ty when arms diverge) - #60457 (Const prop refactoring) - #60467 (Avoid repeated interning of static strings.) - #60478 (minor compiler doc tweaks) - #60501 (Propagate mutability from arguments to local bindings in async fn) Failed merges: r? @ghost
This commit is contained in:
commit
3af1bdc4bc
66 changed files with 891 additions and 297 deletions
|
@ -3556,6 +3556,7 @@ dependencies = [
|
|||
name = "tidy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -436,7 +436,7 @@ fn configure_cmake(builder: &Builder<'_>,
|
|||
}
|
||||
|
||||
if env::var_os("SCCACHE_ERROR_LOG").is_some() {
|
||||
cfg.env("RUST_LOG", "sccache=warn");
|
||||
cfg.env("RUSTC_LOG", "sccache=warn");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -362,10 +362,6 @@ struct Foo1 { x: &bool }
|
|||
// ^ expected lifetime parameter
|
||||
struct Foo2<'a> { x: &'a bool } // correct
|
||||
|
||||
impl Foo2 {}
|
||||
// ^^^^ expected lifetime parameter
|
||||
impl<'a> Foo2<'a> {} // correct
|
||||
|
||||
struct Bar1 { x: Foo2 }
|
||||
// ^^^^ expected lifetime parameter
|
||||
struct Bar2<'a> { x: Foo2<'a> } // correct
|
||||
|
@ -2208,4 +2204,5 @@ register_diagnostics! {
|
|||
E0710, // an unknown tool name found in scoped lint
|
||||
E0711, // a feature has been declared with conflicting stability attributes
|
||||
// E0702, // replaced with a generic attribute input check
|
||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||
}
|
||||
|
|
|
@ -2110,15 +2110,49 @@ impl<'a> LoweringContext<'a> {
|
|||
.expect("already checked that type args or bindings exist");
|
||||
(false, first_generic_span.shrink_to_lo(), format!("{}, ", anon_lt_suggestion))
|
||||
};
|
||||
self.sess.buffer_lint_with_diagnostic(
|
||||
ELIDED_LIFETIMES_IN_PATHS,
|
||||
CRATE_NODE_ID,
|
||||
path_span,
|
||||
"hidden lifetime parameters in types are deprecated",
|
||||
builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
expected_lifetimes, path_span, incl_angl_brckt, insertion_span, suggestion
|
||||
)
|
||||
);
|
||||
match self.anonymous_lifetime_mode {
|
||||
// In create-parameter mode we error here because we don't want to support
|
||||
// deprecated impl elision in new features like impl elision and `async fn`,
|
||||
// both of which work using the `CreateParameter` mode:
|
||||
//
|
||||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||
AnonymousLifetimeMode::CreateParameter => {
|
||||
let mut err = struct_span_err!(
|
||||
self.sess,
|
||||
path_span,
|
||||
E0726,
|
||||
"implicit elided lifetime not allowed here"
|
||||
);
|
||||
crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
|
||||
&self.sess,
|
||||
&mut err,
|
||||
expected_lifetimes,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
suggestion,
|
||||
);
|
||||
err.emit();
|
||||
}
|
||||
AnonymousLifetimeMode::PassThrough |
|
||||
AnonymousLifetimeMode::ReportError |
|
||||
AnonymousLifetimeMode::Replace(_) => {
|
||||
self.sess.buffer_lint_with_diagnostic(
|
||||
ELIDED_LIFETIMES_IN_PATHS,
|
||||
CRATE_NODE_ID,
|
||||
path_span,
|
||||
"hidden lifetime parameters in types are deprecated",
|
||||
builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
expected_lifetimes,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
suggestion,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5335,13 +5369,15 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
|
||||
match self.anonymous_lifetime_mode {
|
||||
// N.B., We intentionally ignore the create-parameter mode here
|
||||
// and instead "pass through" to resolve-lifetimes, which will then
|
||||
// report an error. This is because we don't want to support
|
||||
// impl elision for deprecated forms like
|
||||
//
|
||||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||
AnonymousLifetimeMode::CreateParameter |
|
||||
AnonymousLifetimeMode::CreateParameter => {
|
||||
// We should have emitted E0726 when processing this path above
|
||||
self.sess.delay_span_bug(
|
||||
span,
|
||||
"expected 'implicit elided lifetime not allowed' error",
|
||||
);
|
||||
let id = self.sess.next_node_id();
|
||||
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
|
||||
}
|
||||
// This is the normal case.
|
||||
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
|
||||
|
||||
|
|
|
@ -1927,6 +1927,9 @@ pub enum ArgSource {
|
|||
/// Represents the header (not the body) of a function declaration.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub struct FnDecl {
|
||||
/// The types of the function's arguments.
|
||||
///
|
||||
/// Additional argument data is stored in the function's [body](Body::arguments).
|
||||
pub inputs: HirVec<Ty>,
|
||||
pub output: FunctionRetTy,
|
||||
pub c_variadic: bool,
|
||||
|
|
|
@ -644,7 +644,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
for sp in prior_arms {
|
||||
err.span_label(*sp, format!(
|
||||
"this is found to be of type `{}`",
|
||||
last_ty,
|
||||
self.resolve_type_vars_if_possible(&last_ty),
|
||||
));
|
||||
}
|
||||
} else if let Some(sp) = prior_arms.last() {
|
||||
|
|
|
@ -704,7 +704,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
/// potentially leaving "dangling type variables" behind.
|
||||
/// In such cases, an assertion will fail when attempting to
|
||||
/// register obligations, within a snapshot. Very useful, much
|
||||
/// better than grovelling through megabytes of `RUST_LOG` output.
|
||||
/// better than grovelling through megabytes of `RUSTC_LOG` output.
|
||||
///
|
||||
/// HOWEVER, in some cases the flag is unhelpful. In particular, we
|
||||
/// sometimes create a "mini-fulfilment-cx" in which we enroll
|
||||
|
|
|
@ -376,7 +376,7 @@ declare_lint! {
|
|||
|
||||
declare_lint! {
|
||||
pub AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||
Warn,
|
||||
Deny,
|
||||
"ambiguous associated items"
|
||||
}
|
||||
|
||||
|
@ -477,6 +477,48 @@ pub enum BuiltinLintDiagnostics {
|
|||
RedundantImport(Vec<(Span, bool)>, ast::Ident),
|
||||
}
|
||||
|
||||
pub(crate) fn add_elided_lifetime_in_path_suggestion(
|
||||
sess: &Session,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
n: usize,
|
||||
path_span: Span,
|
||||
incl_angl_brckt: bool,
|
||||
insertion_span: Span,
|
||||
anon_lts: String,
|
||||
) {
|
||||
let (replace_span, suggestion) = if incl_angl_brckt {
|
||||
(insertion_span, anon_lts)
|
||||
} else {
|
||||
// When possible, prefer a suggestion that replaces the whole
|
||||
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
|
||||
// at a point (which makes for an ugly/confusing label)
|
||||
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
|
||||
// But our spans can get out of whack due to macros; if the place we think
|
||||
// we want to insert `'_` isn't even within the path expression's span, we
|
||||
// should bail out of making any suggestion rather than panicking on a
|
||||
// subtract-with-overflow or string-slice-out-out-bounds (!)
|
||||
// FIXME: can we do better?
|
||||
if insertion_span.lo().0 < path_span.lo().0 {
|
||||
return;
|
||||
}
|
||||
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
|
||||
if insertion_index > snippet.len() {
|
||||
return;
|
||||
}
|
||||
let (before, after) = snippet.split_at(insertion_index);
|
||||
(path_span, format!("{}{}{}", before, anon_lts, after))
|
||||
} else {
|
||||
(insertion_span, anon_lts)
|
||||
}
|
||||
};
|
||||
db.span_suggestion(
|
||||
replace_span,
|
||||
&format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
|
||||
impl BuiltinLintDiagnostics {
|
||||
pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
|
||||
match self {
|
||||
|
@ -521,36 +563,14 @@ impl BuiltinLintDiagnostics {
|
|||
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
n, path_span, incl_angl_brckt, insertion_span, anon_lts
|
||||
) => {
|
||||
let (replace_span, suggestion) = if incl_angl_brckt {
|
||||
(insertion_span, anon_lts)
|
||||
} else {
|
||||
// When possible, prefer a suggestion that replaces the whole
|
||||
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
|
||||
// at a point (which makes for an ugly/confusing label)
|
||||
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
|
||||
// But our spans can get out of whack due to macros; if the place we think
|
||||
// we want to insert `'_` isn't even within the path expression's span, we
|
||||
// should bail out of making any suggestion rather than panicking on a
|
||||
// subtract-with-overflow or string-slice-out-out-bounds (!)
|
||||
// FIXME: can we do better?
|
||||
if insertion_span.lo().0 < path_span.lo().0 {
|
||||
return;
|
||||
}
|
||||
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
|
||||
if insertion_index > snippet.len() {
|
||||
return;
|
||||
}
|
||||
let (before, after) = snippet.split_at(insertion_index);
|
||||
(path_span, format!("{}{}{}", before, anon_lts, after))
|
||||
} else {
|
||||
(insertion_span, anon_lts)
|
||||
}
|
||||
};
|
||||
db.span_suggestion(
|
||||
replace_span,
|
||||
&format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable
|
||||
add_elided_lifetime_in_path_suggestion(
|
||||
sess,
|
||||
db,
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
anon_lts,
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
|
||||
|
|
|
@ -757,12 +757,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||
/// Check if a `DefId`'s path matches the given absolute type path usage.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust,ignore (no `cx` or `def_id` available)
|
||||
///
|
||||
/// ```rust,ignore (no context or def id available)
|
||||
/// if cx.match_def_path(def_id, &["core", "option", "Option"]) {
|
||||
/// // The given `def_id` is that of an `Option` type
|
||||
/// }
|
||||
/// ```
|
||||
// Uplifted from rust-lang/rust-clippy
|
||||
pub fn match_def_path(&self, def_id: DefId, path: &[&str]) -> bool {
|
||||
let names = self.get_def_path(def_id);
|
||||
|
||||
|
@ -772,13 +772,13 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||
/// Gets the absolute path of `def_id` as a vector of `&str`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust,ignore (no `cx` or `def_id` available)
|
||||
///
|
||||
/// ```rust,ignore (no context or def id available)
|
||||
/// let def_path = cx.get_def_path(def_id);
|
||||
/// if let &["core", "option", "Option"] = &def_path[..] {
|
||||
/// // The given `def_id` is that of an `Option` type
|
||||
/// }
|
||||
/// ```
|
||||
// Uplifted from rust-lang/rust-clippy
|
||||
pub fn get_def_path(&self, def_id: DefId) -> Vec<LocalInternedString> {
|
||||
pub struct AbsolutePathPrinter<'a, 'tcx> {
|
||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
|
|
@ -784,26 +784,30 @@ pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
|
|||
file_name,
|
||||
defining_crate);
|
||||
|
||||
let directory = if defining_crate == LOCAL_CRATE {
|
||||
&cx.sess().working_dir.0
|
||||
let file_name = &file_name.to_string();
|
||||
let file_name_symbol = Symbol::intern(file_name);
|
||||
if defining_crate == LOCAL_CRATE {
|
||||
let directory = &cx.sess().working_dir.0.to_string_lossy();
|
||||
file_metadata_raw(cx, file_name, Some(file_name_symbol),
|
||||
directory, Some(Symbol::intern(directory)))
|
||||
} else {
|
||||
// If the path comes from an upstream crate we assume it has been made
|
||||
// independent of the compiler's working directory one way or another.
|
||||
Path::new("")
|
||||
};
|
||||
|
||||
file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
|
||||
file_metadata_raw(cx, file_name, Some(file_name_symbol), "", None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
|
||||
file_metadata_raw(cx, "<unknown>", "")
|
||||
file_metadata_raw(cx, "<unknown>", None, "", None)
|
||||
}
|
||||
|
||||
fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
|
||||
file_name: &str,
|
||||
directory: &str)
|
||||
file_name_symbol: Option<Symbol>,
|
||||
directory: &str,
|
||||
directory_symbol: Option<Symbol>)
|
||||
-> &'ll DIFile {
|
||||
let key = (Symbol::intern(file_name), Symbol::intern(directory));
|
||||
let key = (file_name_symbol, directory_symbol);
|
||||
|
||||
if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) {
|
||||
return *file_metadata;
|
||||
|
|
|
@ -63,7 +63,7 @@ pub struct CrateDebugContext<'a, 'tcx> {
|
|||
llcontext: &'a llvm::Context,
|
||||
llmod: &'a llvm::Module,
|
||||
builder: &'a mut DIBuilder<'a>,
|
||||
created_files: RefCell<FxHashMap<(Symbol, Symbol), &'a DIFile>>,
|
||||
created_files: RefCell<FxHashMap<(Option<Symbol>, Option<Symbol>), &'a DIFile>>,
|
||||
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
|
||||
|
||||
type_map: RefCell<TypeMap<'a, 'tcx>>,
|
||||
|
|
|
@ -1163,7 +1163,7 @@ pub fn report_ices_to_stderr_if_any<F: FnOnce() -> R, R>(f: F) -> Result<R, Erro
|
|||
/// This allows tools to enable rust logging without having to magically match rustc's
|
||||
/// log crate version
|
||||
pub fn init_rustc_env_logger() {
|
||||
env_logger::init();
|
||||
env_logger::init_from_env("RUSTC_LOG");
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
//! Propagates constants for early reporting of statically known
|
||||
//! assertion failures
|
||||
|
||||
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
|
||||
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind};
|
||||
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
||||
use rustc::mir::{
|
||||
Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
|
||||
NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
|
||||
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
|
||||
SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
|
||||
};
|
||||
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
|
||||
use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult};
|
||||
use rustc::ty::{self, Instance, Ty, TyCtxt};
|
||||
use syntax::source_map::{Span, DUMMY_SP};
|
||||
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||
use syntax::source_map::DUMMY_SP;
|
||||
use rustc::ty::subst::InternalSubsts;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc::ty::ParamEnv;
|
||||
use rustc::ty::layout::{
|
||||
LayoutOf, TyLayout, LayoutError,
|
||||
HasTyCtxt, TargetDataLayout, HasDataLayout,
|
||||
|
@ -62,21 +63,33 @@ impl MirPass for ConstProp {
|
|||
let mut optimization_finder = ConstPropagator::new(mir, tcx, source);
|
||||
optimization_finder.visit_mir(mir);
|
||||
|
||||
// put back the data we stole from `mir`
|
||||
std::mem::replace(
|
||||
&mut mir.source_scope_local_data,
|
||||
optimization_finder.source_scope_local_data
|
||||
);
|
||||
std::mem::replace(
|
||||
&mut mir.promoted,
|
||||
optimization_finder.promoted
|
||||
);
|
||||
|
||||
trace!("ConstProp done for {:?}", source.def_id());
|
||||
}
|
||||
}
|
||||
|
||||
type Const<'tcx> = (OpTy<'tcx>, Span);
|
||||
type Const<'tcx> = OpTy<'tcx>;
|
||||
|
||||
/// Finds optimization opportunities on the MIR.
|
||||
struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
|
||||
ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
|
||||
mir: &'mir Mir<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
places: IndexVec<Local, Option<Const<'tcx>>>,
|
||||
can_const_prop: IndexVec<Local, bool>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
promoted: IndexVec<Promoted, Mir<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> LayoutOf for ConstPropagator<'a, 'b, 'tcx> {
|
||||
|
@ -104,20 +117,33 @@ impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'a, 'b, 'tcx> {
|
|||
|
||||
impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
||||
fn new(
|
||||
mir: &'mir Mir<'tcx>,
|
||||
mir: &mut Mir<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
) -> ConstPropagator<'a, 'mir, 'tcx> {
|
||||
let param_env = tcx.param_env(source.def_id());
|
||||
let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id()), param_env);
|
||||
let can_const_prop = CanConstProp::check(mir);
|
||||
let source_scope_local_data = std::mem::replace(
|
||||
&mut mir.source_scope_local_data,
|
||||
ClearCrossCrate::Clear
|
||||
);
|
||||
let promoted = std::mem::replace(
|
||||
&mut mir.promoted,
|
||||
IndexVec::new()
|
||||
);
|
||||
|
||||
ConstPropagator {
|
||||
ecx,
|
||||
mir,
|
||||
tcx,
|
||||
source,
|
||||
param_env,
|
||||
can_const_prop: CanConstProp::check(mir),
|
||||
can_const_prop,
|
||||
places: IndexVec::from_elem(None, &mir.local_decls),
|
||||
source_scope_local_data,
|
||||
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_mir()` needs it
|
||||
local_decls: mir.local_decls.clone(),
|
||||
promoted,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +156,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
|
||||
{
|
||||
self.ecx.tcx.span = source_info.span;
|
||||
let lint_root = match self.mir.source_scope_local_data {
|
||||
let lint_root = match self.source_scope_local_data {
|
||||
ClearCrossCrate::Set(ref ivs) => {
|
||||
//FIXME(#51314): remove this check
|
||||
if source_info.scope.index() >= ivs.len() {
|
||||
|
@ -252,12 +278,11 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
fn eval_constant(
|
||||
&mut self,
|
||||
c: &Constant<'tcx>,
|
||||
source_info: SourceInfo,
|
||||
) -> Option<Const<'tcx>> {
|
||||
self.ecx.tcx.span = source_info.span;
|
||||
self.ecx.tcx.span = c.span;
|
||||
match self.ecx.eval_const_to_op(*c.literal, None) {
|
||||
Ok(op) => {
|
||||
Some((op, c.span))
|
||||
Some(op)
|
||||
},
|
||||
Err(error) => {
|
||||
let err = error_to_const_error(&self.ecx, error);
|
||||
|
@ -273,11 +298,11 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Field(field, _) => {
|
||||
trace!("field proj on {:?}", proj.base);
|
||||
let (base, span) = self.eval_place(&proj.base, source_info)?;
|
||||
let base = self.eval_place(&proj.base, source_info)?;
|
||||
let res = self.use_ecx(source_info, |this| {
|
||||
this.ecx.operand_field(base, field.index() as u64)
|
||||
})?;
|
||||
Some((res, span))
|
||||
Some(res)
|
||||
},
|
||||
// We could get more projections by using e.g., `operand_projection`,
|
||||
// but we do not even have the stack frame set up properly so
|
||||
|
@ -301,11 +326,11 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
// cannot use `const_eval` here, because that would require having the MIR
|
||||
// for the current function available, but we're producing said MIR right now
|
||||
let res = self.use_ecx(source_info, |this| {
|
||||
let mir = &this.mir.promoted[promoted];
|
||||
let mir = &this.promoted[promoted];
|
||||
eval_promoted(this.tcx, cid, mir, this.param_env)
|
||||
})?;
|
||||
trace!("evaluated promoted {:?} to {:?}", promoted, res);
|
||||
Some((res.into(), source_info.span))
|
||||
Some(res.into())
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
|
@ -313,7 +338,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
|
||||
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
|
||||
match *op {
|
||||
Operand::Constant(ref c) => self.eval_constant(c, source_info),
|
||||
Operand::Constant(ref c) => self.eval_constant(c),
|
||||
| Operand::Move(ref place)
|
||||
| Operand::Copy(ref place) => self.eval_place(place, source_info),
|
||||
}
|
||||
|
@ -337,18 +362,18 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
Rvalue::Discriminant(..) => None,
|
||||
|
||||
Rvalue::Cast(kind, ref operand, _) => {
|
||||
let (op, span) = self.eval_operand(operand, source_info)?;
|
||||
let op = self.eval_operand(operand, source_info)?;
|
||||
self.use_ecx(source_info, |this| {
|
||||
let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
|
||||
this.ecx.cast(op, kind, dest.into())?;
|
||||
Ok((dest.into(), span))
|
||||
Ok(dest.into())
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME(oli-obk): evaluate static/constant slice lengths
|
||||
Rvalue::Len(_) => None,
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
|
||||
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
|
||||
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
|
||||
ImmTy {
|
||||
imm: Immediate::Scalar(
|
||||
Scalar::Bits {
|
||||
|
@ -357,9 +382,8 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
}.into()
|
||||
),
|
||||
layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
|
||||
}.into(),
|
||||
span,
|
||||
)))
|
||||
}.into()
|
||||
))
|
||||
}
|
||||
Rvalue::UnaryOp(op, ref arg) => {
|
||||
let def_id = if self.tcx.is_closure(self.source.def_id()) {
|
||||
|
@ -373,7 +397,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let (arg, _) = self.eval_operand(arg, source_info)?;
|
||||
let arg = self.eval_operand(arg, source_info)?;
|
||||
let val = self.use_ecx(source_info, |this| {
|
||||
let prim = this.ecx.read_immediate(arg)?;
|
||||
match op {
|
||||
|
@ -395,7 +419,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
imm: Immediate::Scalar(val.into()),
|
||||
layout: place_layout,
|
||||
};
|
||||
Some((res.into(), span))
|
||||
Some(res.into())
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(op, ref left, ref right) |
|
||||
Rvalue::BinaryOp(op, ref left, ref right) => {
|
||||
|
@ -413,20 +437,20 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
}
|
||||
|
||||
let r = self.use_ecx(source_info, |this| {
|
||||
this.ecx.read_immediate(right.0)
|
||||
this.ecx.read_immediate(right)
|
||||
})?;
|
||||
if op == BinOp::Shr || op == BinOp::Shl {
|
||||
let left_ty = left.ty(self.mir, self.tcx);
|
||||
let left_ty = left.ty(&self.local_decls, self.tcx);
|
||||
let left_bits = self
|
||||
.tcx
|
||||
.layout_of(self.param_env.and(left_ty))
|
||||
.unwrap()
|
||||
.size
|
||||
.bits();
|
||||
let right_size = right.0.layout.size;
|
||||
let right_size = right.layout.size;
|
||||
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
|
||||
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
|
||||
let source_scope_local_data = match self.mir.source_scope_local_data {
|
||||
let source_scope_local_data = match self.source_scope_local_data {
|
||||
ClearCrossCrate::Set(ref data) => data,
|
||||
ClearCrossCrate::Clear => return None,
|
||||
};
|
||||
|
@ -446,7 +470,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
}
|
||||
let left = self.eval_operand(left, source_info)?;
|
||||
let l = self.use_ecx(source_info, |this| {
|
||||
this.ecx.read_immediate(left.0)
|
||||
this.ecx.read_immediate(left)
|
||||
})?;
|
||||
trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
|
||||
let (val, overflow) = self.use_ecx(source_info, |this| {
|
||||
|
@ -469,7 +493,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||
imm: val,
|
||||
layout: place_layout,
|
||||
};
|
||||
Some((res.into(), span))
|
||||
Some(res.into())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -544,8 +568,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
) {
|
||||
trace!("visit_constant: {:?}", constant);
|
||||
self.super_constant(constant, location);
|
||||
let source_info = *self.mir.source_info(location);
|
||||
self.eval_constant(constant, source_info);
|
||||
self.eval_constant(constant);
|
||||
}
|
||||
|
||||
fn visit_statement(
|
||||
|
@ -556,7 +579,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
trace!("visit_statement: {:?}", statement);
|
||||
if let StatementKind::Assign(ref place, ref rval) = statement.kind {
|
||||
let place_ty: Ty<'tcx> = place
|
||||
.ty(&self.mir.local_decls, self.tcx)
|
||||
.ty(&self.local_decls, self.tcx)
|
||||
.ty;
|
||||
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
|
||||
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
|
||||
|
@ -574,18 +597,18 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
self.super_statement(statement, location);
|
||||
}
|
||||
|
||||
fn visit_terminator_kind(
|
||||
fn visit_terminator(
|
||||
&mut self,
|
||||
kind: &TerminatorKind<'tcx>,
|
||||
terminator: &Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_terminator_kind(kind, location);
|
||||
let source_info = *self.mir.source_info(location);
|
||||
if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
|
||||
if let Some(value) = self.eval_operand(cond, source_info) {
|
||||
self.super_terminator(terminator, location);
|
||||
let source_info = terminator.source_info;;
|
||||
if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
|
||||
if let Some(value) = self.eval_operand(&cond, source_info) {
|
||||
trace!("assertion on {:?} should be {:?}", value, expected);
|
||||
let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
|
||||
if expected != self.ecx.read_scalar(value.0).unwrap() {
|
||||
if expected != self.ecx.read_scalar(value).unwrap() {
|
||||
// poison all places this operand references so that further code
|
||||
// doesn't use the invalid value
|
||||
match cond {
|
||||
|
@ -600,12 +623,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
},
|
||||
Operand::Constant(_) => {}
|
||||
}
|
||||
let span = self.mir[location.block]
|
||||
.terminator
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.source_info
|
||||
.span;
|
||||
let span = terminator.source_info.span;
|
||||
let hir_id = self
|
||||
.tcx
|
||||
.hir()
|
||||
|
@ -621,7 +639,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
let len = self
|
||||
.eval_operand(len, source_info)
|
||||
.expect("len must be const");
|
||||
let len = match self.ecx.read_scalar(len.0) {
|
||||
let len = match self.ecx.read_scalar(len) {
|
||||
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
bits, ..
|
||||
})) => bits,
|
||||
|
@ -630,7 +648,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
let index = self
|
||||
.eval_operand(index, source_info)
|
||||
.expect("index must be const");
|
||||
let index = match self.ecx.read_scalar(index.0) {
|
||||
let index = match self.ecx.read_scalar(index) {
|
||||
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
|
||||
bits, ..
|
||||
})) => bits,
|
||||
|
|
|
@ -20,7 +20,7 @@ use syntax::ptr::P;
|
|||
use syntax::visit::{self, Visitor};
|
||||
use syntax::{span_err, struct_span_err, walk_list};
|
||||
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{Span, MultiSpan};
|
||||
use errors::Applicability;
|
||||
use log::debug;
|
||||
|
||||
|
@ -679,6 +679,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
"unions cannot have zero fields");
|
||||
}
|
||||
}
|
||||
ItemKind::Existential(ref bounds, _) => {
|
||||
if !bounds.iter()
|
||||
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
|
||||
let msp = MultiSpan::from_spans(bounds.iter()
|
||||
.map(|bound| bound.span()).collect());
|
||||
self.err_handler().span_err(msp, "at least one trait must be specified");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::check::{FnCtxt, Expectation, Diverges, Needs};
|
||||
use crate::check::coercion::CoerceMany;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
use errors::Applicability;
|
||||
use rustc::hir::{self, PatKind};
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc::hir::{self, PatKind, Pat};
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::infer;
|
||||
|
@ -377,15 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Ok(snippet) = tcx.sess.source_map()
|
||||
.span_to_snippet(pat.span)
|
||||
{
|
||||
err.help(&format!("did you mean `{}: &{}`?",
|
||||
&snippet[1..],
|
||||
expected));
|
||||
}
|
||||
}
|
||||
self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
|
||||
err.emit();
|
||||
}
|
||||
(rptr_ty, inner_ty)
|
||||
|
@ -517,6 +509,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// subtyping.
|
||||
}
|
||||
|
||||
fn borrow_pat_suggestion(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
pat: &Pat,
|
||||
inner: &Pat,
|
||||
expected: Ty<'tcx>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
|
||||
let parent = tcx.hir().get_by_hir_id(parent_id);
|
||||
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
|
||||
match parent {
|
||||
hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
|
||||
hir::Node::ForeignItem(hir::ForeignItem {
|
||||
node: hir::ForeignItemKind::Fn(..), ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
|
||||
hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
|
||||
// this pat is likely an argument
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
|
||||
// FIXME: turn into structured suggestion, will need a span that also
|
||||
// includes the the arg's type.
|
||||
err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
|
||||
}
|
||||
}
|
||||
hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
|
||||
hir::Node::Pat(_) => {
|
||||
// rely on match ergonomics or it might be nested `&&pat`
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
|
||||
err.span_suggestion(
|
||||
pat.span,
|
||||
"you can probably remove the explicit borrow",
|
||||
snippet,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {} // don't provide suggestions in other cases #55175
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
|
||||
|
|
|
@ -166,9 +166,18 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
|||
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
|
||||
maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
|
||||
persist_doctests: Option<PathBuf>) {
|
||||
// The test harness wants its own `main` and top-level functions, so
|
||||
// never wrap the test in `fn main() { ... }`.
|
||||
let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
|
||||
let (test, line_offset) = match panic::catch_unwind(|| {
|
||||
make_test(test, Some(cratename), as_test_harness, opts)
|
||||
}) {
|
||||
Ok((test, line_offset)) => (test, line_offset),
|
||||
Err(cause) if cause.is::<errors::FatalErrorMarker>() => {
|
||||
// If the parser used by `make_test` panicked due to a fatal error, pass the test code
|
||||
// through unchanged. The error will be reported during compilation.
|
||||
(test.to_owned(), 0)
|
||||
},
|
||||
Err(cause) => panic::resume_unwind(cause),
|
||||
};
|
||||
|
||||
// FIXME(#44940): if doctests ever support path remapping, then this filename
|
||||
// needs to be the result of `SourceMap::span_to_unmapped_path`.
|
||||
let path = match filename {
|
||||
|
@ -337,7 +346,13 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
|||
}
|
||||
}
|
||||
|
||||
/// Makes the test file. Also returns the number of lines before the code begins
|
||||
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
|
||||
/// lines before the test code begins.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function uses the compiler's parser internally. The parser will panic if it encounters a
|
||||
/// fatal error while parsing the test.
|
||||
pub fn make_test(s: &str,
|
||||
cratename: Option<&str>,
|
||||
dont_insert_main: bool,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#![stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
|
||||
//! Unix-specific networking functionality
|
||||
|
||||
|
@ -27,7 +27,7 @@ use crate::sys::{cvt, fd::FileDesc, syscall};
|
|||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub struct SocketAddr(());
|
||||
|
||||
impl SocketAddr {
|
||||
|
@ -55,7 +55,7 @@ impl SocketAddr {
|
|||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.as_pathname(), None);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn as_pathname(&self) -> Option<&Path> {
|
||||
None
|
||||
}
|
||||
|
@ -83,12 +83,12 @@ impl SocketAddr {
|
|||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// assert_eq!(addr.is_unnamed(), true);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn is_unnamed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl fmt::Debug for SocketAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "SocketAddr")
|
||||
|
@ -109,10 +109,10 @@ impl fmt::Debug for SocketAddr {
|
|||
/// stream.read_to_string(&mut response).unwrap();
|
||||
/// println!("{}", response);
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub struct UnixStream(FileDesc);
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl fmt::Debug for UnixStream {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut builder = fmt.debug_struct("UnixStream");
|
||||
|
@ -143,7 +143,7 @@ impl UnixStream {
|
|||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
|
||||
if let Some(s) = path.as_ref().to_str() {
|
||||
cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC))
|
||||
|
@ -174,7 +174,7 @@ impl UnixStream {
|
|||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
|
||||
let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC))
|
||||
.map(FileDesc::new)?;
|
||||
|
@ -198,7 +198,7 @@ impl UnixStream {
|
|||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn try_clone(&self) -> io::Result<UnixStream> {
|
||||
self.0.duplicate().map(UnixStream)
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ impl UnixStream {
|
|||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let addr = socket.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox"))
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ impl UnixStream {
|
|||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// let addr = socket.peer_addr().expect("Couldn't get peer address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox"))
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ impl UnixStream {
|
|||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn set_read_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox"))
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ impl UnixStream {
|
|||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn set_write_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox"))
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ impl UnixStream {
|
|||
/// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
|
||||
/// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox"))
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ impl UnixStream {
|
|||
/// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
|
||||
/// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox"))
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ impl UnixStream {
|
|||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ impl UnixStream {
|
|||
///
|
||||
/// # Platform specific
|
||||
/// On Redox this always returns `None`.
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -397,13 +397,13 @@ impl UnixStream {
|
|||
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
|
||||
/// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox"))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl io::Read for UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
io::Read::read(&mut &*self, buf)
|
||||
|
@ -415,7 +415,7 @@ impl io::Read for UnixStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl<'a> io::Read for &'a UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
|
@ -427,7 +427,7 @@ impl<'a> io::Read for &'a UnixStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl io::Write for UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
io::Write::write(&mut &*self, buf)
|
||||
|
@ -438,7 +438,7 @@ impl io::Write for UnixStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl<'a> io::Write for &'a UnixStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
|
@ -449,21 +449,21 @@ impl<'a> io::Write for &'a UnixStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl AsRawFd for UnixStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl FromRawFd for UnixStream {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
|
||||
UnixStream(FileDesc::new(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl IntoRawFd for UnixStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw()
|
||||
|
@ -498,10 +498,10 @@ impl IntoRawFd for UnixStream {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub struct UnixListener(FileDesc);
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl fmt::Debug for UnixListener {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut builder = fmt.debug_struct("UnixListener");
|
||||
|
@ -529,7 +529,7 @@ impl UnixListener {
|
|||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
|
||||
if let Some(s) = path.as_ref().to_str() {
|
||||
cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC))
|
||||
|
@ -563,7 +563,7 @@ impl UnixListener {
|
|||
/// Err(e) => println!("accept function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
|
||||
self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(())))
|
||||
}
|
||||
|
@ -583,7 +583,7 @@ impl UnixListener {
|
|||
///
|
||||
/// let listener_copy = listener.try_clone().expect("try_clone failed");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn try_clone(&self) -> io::Result<UnixListener> {
|
||||
self.0.duplicate().map(UnixListener)
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ impl UnixListener {
|
|||
///
|
||||
/// let addr = listener.local_addr().expect("Couldn't get local address");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox"))
|
||||
}
|
||||
|
@ -615,7 +615,7 @@ impl UnixListener {
|
|||
///
|
||||
/// listener.set_nonblocking(true).expect("Couldn't set non blocking");
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
}
|
||||
|
@ -636,7 +636,7 @@ impl UnixListener {
|
|||
///
|
||||
/// # Platform specific
|
||||
/// On Redox this always returns `None`.
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
@ -672,34 +672,34 @@ impl UnixListener {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
|
||||
Incoming { listener: self }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl AsRawFd for UnixListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl FromRawFd for UnixListener {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
|
||||
UnixListener(FileDesc::new(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl IntoRawFd for UnixListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl<'a> IntoIterator for &'a UnixListener {
|
||||
type Item = io::Result<UnixStream>;
|
||||
type IntoIter = Incoming<'a>;
|
||||
|
@ -740,12 +740,12 @@ impl<'a> IntoIterator for &'a UnixListener {
|
|||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
pub struct Incoming<'a> {
|
||||
listener: &'a UnixListener,
|
||||
}
|
||||
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29")]
|
||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||
impl<'a> Iterator for Incoming<'a> {
|
||||
type Item = io::Result<UnixStream>;
|
||||
|
||||
|
|
|
@ -109,15 +109,14 @@ macro_rules! declare_features {
|
|||
// stable (active).
|
||||
//
|
||||
// Note that the features should be grouped into internal/user-facing
|
||||
// and then sorted by version inside those groups.
|
||||
// FIXME(60361): Enforce ^-- with tidy.
|
||||
// and then sorted by version inside those groups. This is inforced with tidy.
|
||||
//
|
||||
// N.B., `tools/tidy/src/features.rs` parses this information directly out of the
|
||||
// source, so take care when modifying it.
|
||||
|
||||
declare_features! (
|
||||
// -------------------------------------------------------------------------
|
||||
// Internal feature gates.
|
||||
// feature-group-start: internal feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// no tracking issue START
|
||||
|
@ -211,12 +210,12 @@ declare_features! (
|
|||
|
||||
// no tracking issue END
|
||||
|
||||
// Allows using the `may_dangle` attribute (RFC 1327).
|
||||
(active, dropck_eyepatch, "1.10.0", Some(34761), None),
|
||||
|
||||
// Allows using `#[structural_match]` which indicates that a type is structurally matchable.
|
||||
(active, structural_match, "1.8.0", Some(31434), None),
|
||||
|
||||
// Allows using the `may_dangle` attribute (RFC 1327).
|
||||
(active, dropck_eyepatch, "1.10.0", Some(34761), None),
|
||||
|
||||
// Allows using the `#![panic_runtime]` attribute.
|
||||
(active, panic_runtime, "1.10.0", Some(32837), None),
|
||||
|
||||
|
@ -252,7 +251,11 @@ declare_features! (
|
|||
(active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Actual feature gates (target features).
|
||||
// feature-group-end: internal feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-start: actual feature gates (target features)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// FIXME: Document these and merge with the list below.
|
||||
|
@ -275,7 +278,11 @@ declare_features! (
|
|||
(active, f16c_target_feature, "1.36.0", Some(44839), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Actual feature gates.
|
||||
// feature-group-end: actual feature gates (target features)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-start: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Allows using `asm!` macro with which inline assembly can be embedded.
|
||||
|
@ -340,9 +347,6 @@ declare_features! (
|
|||
// Permits specifying whether a function should permit unwinding or abort on unwind.
|
||||
(active, unwind_attributes, "1.4.0", Some(58760), None),
|
||||
|
||||
// Allows using `#[naked]` on functions.
|
||||
(active, naked_functions, "1.9.0", Some(32408), None),
|
||||
|
||||
// Allows `#[no_debug]`.
|
||||
(active, no_debug, "1.5.0", Some(29721), None),
|
||||
|
||||
|
@ -358,6 +362,9 @@ declare_features! (
|
|||
// Allows specialization of implementations (RFC 1210).
|
||||
(active, specialization, "1.7.0", Some(31844), None),
|
||||
|
||||
// Allows using `#[naked]` on functions.
|
||||
(active, naked_functions, "1.9.0", Some(32408), None),
|
||||
|
||||
// Allows `cfg(target_has_atomic = "...")`.
|
||||
(active, cfg_target_has_atomic, "1.9.0", Some(32976), None),
|
||||
|
||||
|
@ -545,6 +552,10 @@ declare_features! (
|
|||
|
||||
// Allows using C-variadics.
|
||||
(active, c_variadic, "1.34.0", Some(44930), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
);
|
||||
|
||||
// Some features are known to be incomplete and using them is likely to have
|
||||
|
|
|
@ -8725,9 +8725,9 @@ impl<'a> Parser<'a> {
|
|||
// Check if this is a ident pattern, if so, we can optimize and avoid adding a
|
||||
// `let <pat> = __argN;` statement, instead just adding a `let <pat> = <pat>;`
|
||||
// statement.
|
||||
let (ident, is_simple_pattern) = match input.pat.node {
|
||||
PatKind::Ident(_, ident, _) => (ident, true),
|
||||
_ => (ident, false),
|
||||
let (binding_mode, ident, is_simple_pattern) = match input.pat.node {
|
||||
PatKind::Ident(binding_mode, ident, _) => (binding_mode, ident, true),
|
||||
_ => (BindingMode::ByValue(Mutability::Immutable), ident, false),
|
||||
};
|
||||
|
||||
// Construct an argument representing `__argN: <ty>` to replace the argument of the
|
||||
|
@ -8755,9 +8755,7 @@ impl<'a> Parser<'a> {
|
|||
let move_local = Local {
|
||||
pat: P(Pat {
|
||||
id,
|
||||
node: PatKind::Ident(
|
||||
BindingMode::ByValue(Mutability::Immutable), ident, None,
|
||||
),
|
||||
node: PatKind::Ident(binding_mode, ident, None),
|
||||
span,
|
||||
}),
|
||||
// We explicitly do not specify the type for this statement. When the user's
|
||||
|
|
|
@ -8,4 +8,4 @@ all:
|
|||
mkdir -p $(TMPDIR)/outdir
|
||||
$(RUSTC) foo.rs -o $(TMPDIR)/outdir/$(NAME)
|
||||
ln -nsf outdir/$(NAME) $(TMPDIR)
|
||||
RUST_LOG=rustc_metadata::loader $(RUSTC) bar.rs
|
||||
RUSTC_LOG=rustc_metadata::loader $(RUSTC) bar.rs
|
||||
|
|
|
@ -68,14 +68,14 @@ fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
|
|||
}
|
||||
|
||||
trait Trait {}
|
||||
existential type GenericBound<'a, T: Trait>: 'a;
|
||||
existential type GenericBound<'a, T: Trait>: Sized + 'a;
|
||||
|
||||
fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
|
||||
t
|
||||
}
|
||||
|
||||
mod pass_through {
|
||||
pub existential type Passthrough<T>: 'static;
|
||||
pub existential type Passthrough<T>: Sized + 'static;
|
||||
|
||||
fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
|
||||
t
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-pass
|
||||
// exec-env:RUST_LOG=rustc::middle=debug
|
||||
// exec-env:RUSTC_LOG=rustc::middle=debug
|
||||
|
||||
fn main() {
|
||||
let b = 1isize;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ignore-windows
|
||||
// ignore-emscripten no threads support
|
||||
// exec-env:RUST_LOG=debug
|
||||
// exec-env:RUSTC_LOG=debug
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// exec-env:RUST_LOG=std::ptr
|
||||
// exec-env:RUSTC_LOG=std::ptr
|
||||
|
||||
// In issue #9487, it was realized that std::ptr was invoking the logging
|
||||
// infrastructure, and when std::ptr was used during runtime initialization,
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
// dont-check-compiler-stderr
|
||||
// compile-flags: --error-format human
|
||||
|
||||
// rustc-env:RUST_LOG=debug
|
||||
// rustc-env:RUSTC_LOG=debug
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![allow(unused_must_use)]
|
||||
#![allow(unused_mut)]
|
||||
// ignore-windows
|
||||
// exec-env:RUST_LOG=debug
|
||||
// exec-env:RUSTC_LOG=debug
|
||||
// ignore-emscripten no threads support
|
||||
|
||||
// regression test for issue #10405, make sure we don't call println! too soon.
|
||||
|
|
|
@ -15,7 +15,7 @@ error[E0425]: cannot find value `no` in this scope
|
|||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:310:13
|
||||
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13
|
||||
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||
|
||||
---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
|
||||
|
@ -24,7 +24,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 11)' panicked at 'test
|
|||
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
|
||||
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||
|
||||
', src/librustdoc/test.rs:332:17
|
||||
', src/librustdoc/test.rs:341:17
|
||||
|
||||
|
||||
failures:
|
||||
|
|
10
src/test/rustdoc-ui/unparseable-doc-test.rs
Normal file
10
src/test/rustdoc-ui/unparseable-doc-test.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// compile-flags: --test
|
||||
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
|
||||
// failure-status: 101
|
||||
// rustc-env: RUST_BACKTRACE=0
|
||||
|
||||
/// ```rust
|
||||
/// let x = 7;
|
||||
/// "unterminated
|
||||
/// ```
|
||||
pub fn foo() {}
|
24
src/test/rustdoc-ui/unparseable-doc-test.stdout
Normal file
24
src/test/rustdoc-ui/unparseable-doc-test.stdout
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
running 1 test
|
||||
test $DIR/unparseable-doc-test.rs - foo (line 6) ... FAILED
|
||||
|
||||
failures:
|
||||
|
||||
---- $DIR/unparseable-doc-test.rs - foo (line 6) stdout ----
|
||||
error: unterminated double quote string
|
||||
--> $DIR/unparseable-doc-test.rs:8:1
|
||||
|
|
||||
2 | "unterminated
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
thread '$DIR/unparseable-doc-test.rs - foo (line 6)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13
|
||||
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
||||
|
||||
|
||||
failures:
|
||||
$DIR/unparseable-doc-test.rs - foo (line 6)
|
||||
|
||||
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
10
src/test/ui/async-await/mutable-arguments.rs
Normal file
10
src/test/ui/async-await/mutable-arguments.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// edition:2018
|
||||
// run-pass
|
||||
|
||||
#![feature(async_await)]
|
||||
|
||||
async fn foo(n: u32, mut vec: Vec<u32>) {
|
||||
vec.push(n);
|
||||
}
|
||||
|
||||
fn main() {}
|
16
src/test/ui/async-fn-path-elision.rs
Normal file
16
src/test/ui/async-fn-path-elision.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// edition:2018
|
||||
|
||||
#![feature(async_await, await_macro)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
struct HasLifetime<'a>(&'a bool);
|
||||
|
||||
async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here
|
||||
if *lt.0 {}
|
||||
}
|
||||
|
||||
fn no_error(lt: HasLifetime) {
|
||||
if *lt.0 {}
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/async-fn-path-elision.stderr
Normal file
8
src/test/ui/async-fn-path-elision.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/async-fn-path-elision.rs:8:20
|
||||
|
|
||||
LL | async fn error(lt: HasLifetime) {
|
||||
| ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -13,4 +13,5 @@ const FOO: u8 = [5u8][1];
|
|||
fn main() {
|
||||
black_box((FOO, FOO));
|
||||
//~^ ERROR erroneous constant used
|
||||
//~| ERROR erroneous constant
|
||||
}
|
||||
|
|
|
@ -13,11 +13,17 @@ LL | #![warn(const_err)]
|
|||
| ^^^^^^^^^
|
||||
|
||||
error[E0080]: erroneous constant used
|
||||
--> $DIR/const-err.rs:14:15
|
||||
--> $DIR/const-err.rs:14:16
|
||||
|
|
||||
LL | black_box((FOO, FOO));
|
||||
| ^^^^^^^^^^ referenced constant has errors
|
||||
| ^^^ referenced constant has errors
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0080]: erroneous constant used
|
||||
--> $DIR/const-err.rs:14:21
|
||||
|
|
||||
LL | black_box((FOO, FOO));
|
||||
| ^^^ referenced constant has errors
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
|
@ -20,21 +20,25 @@ error[E0308]: mismatched types
|
|||
--> $DIR/destructure-trait-ref.rs:31:10
|
||||
|
|
||||
LL | let &&x = &1isize as &T;
|
||||
| ^^ expected trait T, found reference
|
||||
| ^^
|
||||
| |
|
||||
| expected trait T, found reference
|
||||
| help: you can probably remove the explicit borrow: `x`
|
||||
|
|
||||
= note: expected type `dyn T`
|
||||
found type `&_`
|
||||
= help: did you mean `x: &dyn T`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/destructure-trait-ref.rs:36:11
|
||||
|
|
||||
LL | let &&&x = &(&1isize as &T);
|
||||
| ^^ expected trait T, found reference
|
||||
| ^^
|
||||
| |
|
||||
| expected trait T, found reference
|
||||
| help: you can probably remove the explicit borrow: `x`
|
||||
|
|
||||
= note: expected type `dyn T`
|
||||
found type `&_`
|
||||
= help: did you mean `x: &dyn T`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/destructure-trait-ref.rs:41:13
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#![feature(existential_type)]
|
||||
|
||||
existential type Foo: 'static;
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
fn foo() -> Foo {
|
||||
"foo"
|
||||
}
|
||||
|
||||
fn bar() -> impl 'static { //~ ERROR: at least one trait must be specified
|
||||
"foo"
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,14 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/existential-types-with-no-traits.rs:3:23
|
||||
|
|
||||
LL | existential type Foo: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: at least one trait must be specified
|
||||
--> $DIR/existential-types-with-no-traits.rs:10:13
|
||||
|
|
||||
LL | fn bar() -> impl 'static {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -4,6 +4,8 @@ fn main() {}
|
|||
|
||||
existential type Cmp<T>: 'static;
|
||||
//~^ ERROR could not find defining uses
|
||||
//~^^ ERROR: at least one trait must be specified
|
||||
|
||||
|
||||
// not a defining use, because it doesn't define *all* possible generics
|
||||
fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/generic_nondefining_use.rs:5:26
|
||||
|
|
||||
LL | existential type Cmp<T>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: defining existential type use does not fully define existential type
|
||||
--> $DIR/generic_nondefining_use.rs:9:1
|
||||
--> $DIR/generic_nondefining_use.rs:11:1
|
||||
|
|
||||
LL | / fn cmp() -> Cmp<u32> {
|
||||
LL | | 5u32
|
||||
|
@ -12,5 +18,5 @@ error: could not find defining uses
|
|||
LL | existential type Cmp<T>: 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
fn main() {}
|
||||
|
||||
existential type WrongGeneric<T: 'static>: 'static;
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
|
||||
//~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/generic_not_used.rs:5:44
|
||||
|
|
||||
LL | existential type WrongGeneric<T: 'static>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: type parameter `V` is part of concrete type but not used in parameter list for existential type
|
||||
--> $DIR/generic_not_used.rs:7:73
|
||||
--> $DIR/generic_not_used.rs:8:73
|
||||
|
|
||||
LL | fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
|
||||
| _________________________________________________________________________^
|
||||
|
@ -8,5 +14,5 @@ LL | | v
|
|||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ fn main() {
|
|||
|
||||
existential type WrongGeneric<T>: 'static;
|
||||
//~^ ERROR the parameter type `T` may not live long enough
|
||||
//~^^ ERROR: at least one trait must be specified
|
||||
|
||||
fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
|
||||
t
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:9:35
|
||||
|
|
||||
LL | existential type WrongGeneric<T>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/generic_type_does_not_live_long_enough.rs:6:18
|
||||
|
|
||||
|
@ -22,7 +28,7 @@ note: ...so that the type `T` will meet its required lifetime bounds
|
|||
LL | existential type WrongGeneric<T>: 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0310.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -4,6 +4,7 @@ fn main() {}
|
|||
|
||||
trait Trait {}
|
||||
existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
// no `Trait` bound
|
||||
fn underconstrain<T>(_: T) -> Underconstrained<T> {
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/generic_underconstrained.rs:6:46
|
||||
|
|
||||
LL | existential type Underconstrained<T: Trait>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `T: Trait` is not satisfied
|
||||
--> $DIR/generic_underconstrained.rs:6:1
|
||||
|
|
||||
|
@ -7,6 +13,6 @@ LL | existential type Underconstrained<T: Trait>: 'static;
|
|||
= help: consider adding a `where T: Trait` bound
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -4,6 +4,7 @@ fn main() {}
|
|||
|
||||
existential type Underconstrained<T: std::fmt::Debug>: 'static;
|
||||
//~^ ERROR `U` doesn't implement `std::fmt::Debug`
|
||||
//~^^ ERROR: at least one trait must be specified
|
||||
|
||||
// not a defining use, because it doesn't define *all* possible generics
|
||||
fn underconstrained<U>(_: U) -> Underconstrained<U> {
|
||||
|
@ -12,6 +13,7 @@ fn underconstrained<U>(_: U) -> Underconstrained<U> {
|
|||
|
||||
existential type Underconstrained2<T: std::fmt::Debug>: 'static;
|
||||
//~^ ERROR `V` doesn't implement `std::fmt::Debug`
|
||||
//~^^ ERROR: at least one trait must be specified
|
||||
|
||||
// not a defining use, because it doesn't define *all* possible generics
|
||||
fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/generic_underconstrained2.rs:5:56
|
||||
|
|
||||
LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: at least one trait must be specified
|
||||
--> $DIR/generic_underconstrained2.rs:14:57
|
||||
|
|
||||
LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: `U` doesn't implement `std::fmt::Debug`
|
||||
--> $DIR/generic_underconstrained2.rs:5:1
|
||||
|
|
||||
|
@ -9,7 +21,7 @@ LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
|
|||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: `V` doesn't implement `std::fmt::Debug`
|
||||
--> $DIR/generic_underconstrained2.rs:13:1
|
||||
--> $DIR/generic_underconstrained2.rs:14:1
|
||||
|
|
||||
LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
||||
|
@ -18,6 +30,6 @@ LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
|
|||
= help: consider adding a `where V: std::fmt::Debug` bound
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
// compile-pass
|
||||
#![feature(existential_type)]
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
existential type PartiallyDefined<T>: 'static;
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
|
||||
4u32
|
||||
}
|
||||
|
||||
// test that unused generic parameters are ok
|
||||
existential type PartiallyDefined2<T>: 'static;
|
||||
//~^ ERROR: at least one trait must be specified
|
||||
|
||||
fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
|
||||
4u32
|
||||
|
|
14
src/test/ui/existential_types/unused_generic_param.stderr
Normal file
14
src/test/ui/existential_types/unused_generic_param.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error: at least one trait must be specified
|
||||
--> $DIR/unused_generic_param.rs:6:39
|
||||
|
|
||||
LL | existential type PartiallyDefined<T>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: at least one trait must be specified
|
||||
--> $DIR/unused_generic_param.rs:13:40
|
||||
|
|
||||
LL | existential type PartiallyDefined2<T>: 'static;
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -5,7 +5,7 @@ trait MyTrait { }
|
|||
struct Foo<'a> { x: &'a u32 }
|
||||
|
||||
impl MyTrait for Foo {
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~^ ERROR implicit elided lifetime not allowed here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/path-elided.rs:7:18
|
||||
|
|
||||
LL | impl MyTrait for Foo {
|
||||
| ^^^ expected lifetime parameter
|
||||
| ^^^- help: indicate the anonymous lifetime: `<'_>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
trait MyTrait<'a> { }
|
||||
|
||||
impl MyTrait for u32 {
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~^ ERROR implicit elided lifetime not allowed here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/trait-elided.rs:5:6
|
||||
|
|
||||
LL | impl MyTrait for u32 {
|
||||
| ^^^^^^^ expected lifetime parameter
|
||||
| ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
|
|
|
@ -5,7 +5,8 @@ trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
|
|||
|
||||
impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
|
||||
//~^ ERROR lifetimes cannot use keyword names
|
||||
//~| ERROR missing lifetime specifier
|
||||
//~| ERROR implicit elided lifetime not allowed here
|
||||
//~| ERROR the size for values of type `str` cannot be known at compilation time
|
||||
fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
|
||||
vec![1]
|
||||
}
|
||||
|
|
|
@ -29,23 +29,32 @@ LL | impl<'self> Serializable<str> for &'self str {
|
|||
| ^^^^^
|
||||
|
||||
error: lifetimes cannot use keyword names
|
||||
--> $DIR/issue-10412.rs:9:25
|
||||
--> $DIR/issue-10412.rs:10:25
|
||||
|
|
||||
LL | fn serialize(val : &'self str) -> Vec<u8> {
|
||||
| ^^^^^
|
||||
|
||||
error: lifetimes cannot use keyword names
|
||||
--> $DIR/issue-10412.rs:12:37
|
||||
--> $DIR/issue-10412.rs:13:37
|
||||
|
|
||||
LL | fn deserialize(repr: &[u8]) -> &'self str {
|
||||
| ^^^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
error[E0726]: implicit elided lifetime not allowed here
|
||||
--> $DIR/issue-10412.rs:6:13
|
||||
|
|
||||
LL | impl<'self> Serializable<str> for &'self str {
|
||||
| ^^^^^^^^^^^^^^^^^ expected lifetime parameter
|
||||
| ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/issue-10412.rs:6:13
|
||||
|
|
||||
LL | impl<'self> Serializable<str> for &'self str {
|
||||
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `str`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -3,8 +3,7 @@ fn main() {
|
|||
let _ = test_func2(1);
|
||||
}
|
||||
|
||||
fn test_func1(n: i32) -> i32 {
|
||||
//~^ NOTE expected `i32` because of return type
|
||||
fn test_func1(n: i32) -> i32 { //~ NOTE expected `i32` because of return type
|
||||
match n {
|
||||
12 => 'b',
|
||||
//~^ ERROR mismatched types
|
||||
|
@ -14,10 +13,8 @@ fn test_func1(n: i32) -> i32 {
|
|||
}
|
||||
|
||||
fn test_func2(n: i32) -> i32 {
|
||||
let x = match n {
|
||||
//~^ NOTE `match` arms have incompatible types
|
||||
12 => 'b',
|
||||
//~^ NOTE this is found to be of type `char`
|
||||
let x = match n { //~ NOTE `match` arms have incompatible types
|
||||
12 => 'b', //~ NOTE this is found to be of type `char`
|
||||
_ => 42,
|
||||
//~^ ERROR match arms have incompatible types
|
||||
//~| NOTE expected char, found integer
|
||||
|
@ -27,8 +24,7 @@ fn test_func2(n: i32) -> i32 {
|
|||
}
|
||||
|
||||
fn test_func3(n: i32) -> i32 {
|
||||
let x = match n {
|
||||
//~^ NOTE `match` arms have incompatible types
|
||||
let x = match n { //~ NOTE `match` arms have incompatible types
|
||||
1 => 'b',
|
||||
2 => 'b',
|
||||
3 => 'b',
|
||||
|
@ -43,3 +39,15 @@ fn test_func3(n: i32) -> i32 {
|
|||
};
|
||||
x
|
||||
}
|
||||
|
||||
fn test_func4() {
|
||||
match Some(0u32) { //~ NOTE `match` arms have incompatible types
|
||||
Some(x) => {
|
||||
x //~ NOTE this is found to be of type `u32`
|
||||
},
|
||||
None => {}
|
||||
//~^ ERROR match arms have incompatible types
|
||||
//~| NOTE expected u32, found ()
|
||||
//~| NOTE expected type `u32`
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/match-type-err-first-arm.rs:9:15
|
||||
--> $DIR/match-type-err-first-arm.rs:8:15
|
||||
|
|
||||
LL | fn test_func1(n: i32) -> i32 {
|
||||
| --- expected `i32` because of return type
|
||||
...
|
||||
LL | match n {
|
||||
LL | 12 => 'b',
|
||||
| ^^^ expected i32, found char
|
||||
|
||||
error[E0308]: match arms have incompatible types
|
||||
--> $DIR/match-type-err-first-arm.rs:21:14
|
||||
--> $DIR/match-type-err-first-arm.rs:18:14
|
||||
|
|
||||
LL | let x = match n {
|
||||
| _____________-
|
||||
LL | |
|
||||
LL | | 12 => 'b',
|
||||
| | --- this is found to be of type `char`
|
||||
LL | |
|
||||
LL | | _ => 42,
|
||||
| | ^^ expected char, found integer
|
||||
... |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
@ -27,13 +26,13 @@ LL | | };
|
|||
found type `{integer}`
|
||||
|
||||
error[E0308]: match arms have incompatible types
|
||||
--> $DIR/match-type-err-first-arm.rs:39:14
|
||||
--> $DIR/match-type-err-first-arm.rs:35:14
|
||||
|
|
||||
LL | let x = match n {
|
||||
| _____________-
|
||||
LL | |
|
||||
LL | | 1 => 'b',
|
||||
LL | | 2 => 'b',
|
||||
LL | | 3 => 'b',
|
||||
... |
|
||||
LL | | 6 => 'b',
|
||||
| | --- this and all prior arms are found to be of type `char`
|
||||
|
@ -48,6 +47,24 @@ LL | | };
|
|||
= note: expected type `char`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0308]: match arms have incompatible types
|
||||
--> $DIR/match-type-err-first-arm.rs:48:17
|
||||
|
|
||||
LL | / match Some(0u32) {
|
||||
LL | | Some(x) => {
|
||||
LL | | x
|
||||
| | - this is found to be of type `u32`
|
||||
LL | | },
|
||||
LL | | None => {}
|
||||
| | ^^ expected u32, found ()
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -12,11 +12,13 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-38371.rs:18:9
|
||||
|
|
||||
LL | fn agh(&&bar: &u32) {
|
||||
| ^^^^ expected u32, found reference
|
||||
| ^^^^
|
||||
| |
|
||||
| expected u32, found reference
|
||||
| help: you can probably remove the explicit borrow: `bar`
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `&_`
|
||||
= help: did you mean `bar: &u32`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:21:8
|
||||
|
|
41
src/test/ui/suggestions/match-ergonomics.rs
Normal file
41
src/test/ui/suggestions/match-ergonomics.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
fn main() {
|
||||
let x = vec![1i32];
|
||||
match &x[..] {
|
||||
[&v] => {}, //~ ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
match x {
|
||||
[&v] => {}, //~ ERROR expected an array or slice
|
||||
_ => {},
|
||||
}
|
||||
match &x[..] {
|
||||
[v] => {},
|
||||
_ => {},
|
||||
}
|
||||
match &x[..] {
|
||||
&[v] => {},
|
||||
_ => {},
|
||||
}
|
||||
match x {
|
||||
[v] => {}, //~ ERROR expected an array or slice
|
||||
_ => {},
|
||||
}
|
||||
let y = 1i32;
|
||||
match &y {
|
||||
&v => {},
|
||||
_ => {},
|
||||
}
|
||||
match y {
|
||||
&v => {}, //~ ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
match &y {
|
||||
v => {},
|
||||
_ => {},
|
||||
}
|
||||
match y {
|
||||
v => {},
|
||||
_ => {},
|
||||
}
|
||||
if let [&v] = &x[..] {} //~ ERROR mismatched types
|
||||
}
|
52
src/test/ui/suggestions/match-ergonomics.stderr
Normal file
52
src/test/ui/suggestions/match-ergonomics.stderr
Normal file
|
@ -0,0 +1,52 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:4:10
|
||||
|
|
||||
LL | [&v] => {},
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
|
||||
--> $DIR/match-ergonomics.rs:8:9
|
||||
|
|
||||
LL | [&v] => {},
|
||||
| ^^^^ pattern cannot match with input type `std::vec::Vec<i32>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
|
||||
--> $DIR/match-ergonomics.rs:20:9
|
||||
|
|
||||
LL | [v] => {},
|
||||
| ^^^ pattern cannot match with input type `std::vec::Vec<i32>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:29:9
|
||||
|
|
||||
LL | &v => {},
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:40:13
|
||||
|
|
||||
LL | if let [&v] = &x[..] {}
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0529.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(type_alias_enum_variants)]
|
||||
#![deny(ambiguous_associated_items)]
|
||||
|
||||
enum E {
|
||||
V
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
error: ambiguous associated item
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:15:15
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:14:15
|
||||
|
|
||||
LL | fn f() -> Self::V { 0 }
|
||||
| ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:2:9
|
||||
|
|
||||
LL | #![deny(ambiguous_associated_items)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: #[deny(ambiguous_associated_items)] on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
|
||||
note: `V` could refer to variant defined here
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:5:5
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:4:5
|
||||
|
|
||||
LL | V
|
||||
| ^
|
||||
note: `V` could also refer to associated type defined here
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:9:5
|
||||
--> $DIR/type-alias-enum-variants-priority.rs:8:5
|
||||
|
|
||||
LL | type V;
|
||||
| ^^^^^^^
|
||||
|
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||
|
||||
[dependencies]
|
||||
regex = "1"
|
||||
serde = "1.0.8"
|
||||
serde_derive = "1.0.8"
|
||||
serde_json = "1.0.2"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//! * Library features have at most one stability level.
|
||||
//! * Library features have at most one `since` value.
|
||||
//! * All unstable lang features have tests to ensure they are actually unstable.
|
||||
//! * Language features in a group are sorted by `since` value.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
@ -14,6 +15,14 @@ use std::fs::{self, File};
|
|||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
use regex::{Regex, escape};
|
||||
|
||||
mod version;
|
||||
use self::version::Version;
|
||||
|
||||
const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start";
|
||||
const FEATURE_GROUP_END_PREFIX: &str = "// feature-group-end";
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Status {
|
||||
Stable,
|
||||
|
@ -35,7 +44,7 @@ impl fmt::Display for Status {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Feature {
|
||||
pub level: Status,
|
||||
pub since: String,
|
||||
pub since: Option<Version>,
|
||||
pub has_gate_test: bool,
|
||||
pub tracking_issue: Option<u32>,
|
||||
}
|
||||
|
@ -129,20 +138,8 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
|
|||
}
|
||||
|
||||
let mut lines = Vec::new();
|
||||
for (name, feature) in features.iter() {
|
||||
lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
|
||||
name,
|
||||
"lang",
|
||||
feature.level,
|
||||
feature.since));
|
||||
}
|
||||
for (name, feature) in lib_features {
|
||||
lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
|
||||
name,
|
||||
"lib",
|
||||
feature.level,
|
||||
feature.since));
|
||||
}
|
||||
lines.extend(format_features(&features, "lang"));
|
||||
lines.extend(format_features(&lib_features, "lib"));
|
||||
|
||||
lines.sort();
|
||||
for line in lines {
|
||||
|
@ -150,11 +147,31 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_features<'a>(features: &'a Features, family: &'a str) -> impl Iterator<Item = String> + 'a {
|
||||
features.iter().map(move |(name, feature)| {
|
||||
format!("{:<32} {:<8} {:<12} {:<8}",
|
||||
name,
|
||||
family,
|
||||
feature.level,
|
||||
feature.since.map_or("None".to_owned(),
|
||||
|since| since.to_string()))
|
||||
})
|
||||
}
|
||||
|
||||
fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
|
||||
line.find(attr)
|
||||
.and_then(|i| line[i..].find('"').map(|j| i + j + 1))
|
||||
.and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
|
||||
.map(|(i, j)| &line[i..j])
|
||||
let r = Regex::new(&format!(r#"{}\s*=\s*"([^"]*)""#, escape(attr)))
|
||||
.expect("malformed regex for find_attr_val");
|
||||
r.captures(line)
|
||||
.and_then(|c| c.get(1))
|
||||
.map(|m| m.as_str())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_attr_val() {
|
||||
let s = r#"#[unstable(feature = "checked_duration_since", issue = "58402")]"#;
|
||||
assert_eq!(find_attr_val(s, "feature"), Some("checked_duration_since"));
|
||||
assert_eq!(find_attr_val(s, "issue"), Some("58402"));
|
||||
assert_eq!(find_attr_val(s, "since"), None);
|
||||
}
|
||||
|
||||
fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
|
||||
|
@ -177,6 +194,9 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features {
|
|||
// without one inside `// no tracking issue START` and `// no tracking issue END`.
|
||||
let mut next_feature_omits_tracking_issue = false;
|
||||
|
||||
let mut in_feature_group = false;
|
||||
let mut prev_since = None;
|
||||
|
||||
contents.lines().zip(1..)
|
||||
.filter_map(|(line, line_number)| {
|
||||
let line = line.trim();
|
||||
|
@ -194,6 +214,25 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if line.starts_with(FEATURE_GROUP_START_PREFIX) {
|
||||
if in_feature_group {
|
||||
tidy_error!(
|
||||
bad,
|
||||
// ignore-tidy-linelength
|
||||
"libsyntax/feature_gate.rs:{}: new feature group is started without ending the previous one",
|
||||
line_number,
|
||||
);
|
||||
}
|
||||
|
||||
in_feature_group = true;
|
||||
prev_since = None;
|
||||
return None;
|
||||
} else if line.starts_with(FEATURE_GROUP_END_PREFIX) {
|
||||
in_feature_group = false;
|
||||
prev_since = None;
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut parts = line.split(',');
|
||||
let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
|
||||
Some("active") => Status::Unstable,
|
||||
|
@ -202,7 +241,33 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features {
|
|||
_ => return None,
|
||||
};
|
||||
let name = parts.next().unwrap().trim();
|
||||
let since = parts.next().unwrap().trim().trim_matches('"');
|
||||
|
||||
let since_str = parts.next().unwrap().trim().trim_matches('"');
|
||||
let since = match since_str.parse() {
|
||||
Ok(since) => Some(since),
|
||||
Err(err) => {
|
||||
tidy_error!(
|
||||
bad,
|
||||
"libsyntax/feature_gate.rs:{}: failed to parse since: {} ({:?})",
|
||||
line_number,
|
||||
since_str,
|
||||
err,
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
if in_feature_group {
|
||||
if prev_since > since {
|
||||
tidy_error!(
|
||||
bad,
|
||||
"libsyntax/feature_gate.rs:{}: feature {} is not sorted by since",
|
||||
line_number,
|
||||
name,
|
||||
);
|
||||
}
|
||||
prev_since = since;
|
||||
}
|
||||
|
||||
let issue_str = parts.next().unwrap().trim();
|
||||
let tracking_issue = if issue_str.starts_with("None") {
|
||||
if level == Status::Unstable && !next_feature_omits_tracking_issue {
|
||||
|
@ -222,7 +287,7 @@ pub fn collect_lang_features(base_src_path: &Path, bad: &mut bool) -> Features {
|
|||
Some((name.to_owned(),
|
||||
Feature {
|
||||
level,
|
||||
since: since.to_owned(),
|
||||
since,
|
||||
has_gate_test: false,
|
||||
tracking_issue,
|
||||
}))
|
||||
|
@ -239,7 +304,7 @@ pub fn collect_lib_features(base_src_path: &Path) -> Features {
|
|||
// add it to the set of known library features so we can still generate docs.
|
||||
lib_features.insert("compiler_builtins_lib".to_owned(), Feature {
|
||||
level: Status::Unstable,
|
||||
since: String::new(),
|
||||
since: None,
|
||||
has_gate_test: false,
|
||||
tracking_issue: None,
|
||||
});
|
||||
|
@ -336,11 +401,11 @@ fn map_lib_features(base_src_path: &Path,
|
|||
// `const fn` features are handled specially.
|
||||
let feature_name = match find_attr_val(line, "feature") {
|
||||
Some(name) => name,
|
||||
None => err!("malformed stability attribute"),
|
||||
None => err!("malformed stability attribute: missing `feature` key"),
|
||||
};
|
||||
let feature = Feature {
|
||||
level: Status::Unstable,
|
||||
since: "None".to_owned(),
|
||||
since: None,
|
||||
has_gate_test: false,
|
||||
// FIXME(#57563): #57563 is now used as a common tracking issue,
|
||||
// although we would like to have specific tracking issues for each
|
||||
|
@ -359,20 +424,23 @@ fn map_lib_features(base_src_path: &Path,
|
|||
};
|
||||
let feature_name = match find_attr_val(line, "feature") {
|
||||
Some(name) => name,
|
||||
None => err!("malformed stability attribute"),
|
||||
None => err!("malformed stability attribute: missing `feature` key"),
|
||||
};
|
||||
let since = match find_attr_val(line, "since") {
|
||||
Some(name) => name,
|
||||
let since = match find_attr_val(line, "since").map(|x| x.parse()) {
|
||||
Some(Ok(since)) => Some(since),
|
||||
Some(Err(_err)) => {
|
||||
err!("malformed stability attribute: can't parse `since` key");
|
||||
},
|
||||
None if level == Status::Stable => {
|
||||
err!("malformed stability attribute");
|
||||
err!("malformed stability attribute: missing the `since` key");
|
||||
}
|
||||
None => "None",
|
||||
None => None,
|
||||
};
|
||||
let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap());
|
||||
|
||||
let feature = Feature {
|
||||
level,
|
||||
since: since.to_owned(),
|
||||
since,
|
||||
has_gate_test: false,
|
||||
tracking_issue,
|
||||
};
|
||||
|
|
92
src/tools/tidy/src/features/version.rs
Normal file
92
src/tools/tidy/src/features/version.rs
Normal file
|
@ -0,0 +1,92 @@
|
|||
use std::str::FromStr;
|
||||
use std::num::ParseIntError;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Version {
|
||||
parts: [u32; 3],
|
||||
}
|
||||
|
||||
impl fmt::Display for Version {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad(&format!("{}.{}.{}", self.parts[0], self.parts[1], self.parts[2]))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseVersionError {
|
||||
ParseIntError(ParseIntError),
|
||||
WrongNumberOfParts,
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ParseVersionError {
|
||||
fn from(err: ParseIntError) -> Self {
|
||||
ParseVersionError::ParseIntError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Version {
|
||||
type Err = ParseVersionError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut iter = s.split('.').map(|part| Ok(part.parse()?));
|
||||
|
||||
let parts = {
|
||||
let mut part = || {
|
||||
iter.next()
|
||||
.unwrap_or(Err(ParseVersionError::WrongNumberOfParts))
|
||||
};
|
||||
|
||||
[part()?, part()?, part()?]
|
||||
};
|
||||
|
||||
if let Some(_) = iter.next() {
|
||||
// Ensure we don't have more than 3 parts.
|
||||
return Err(ParseVersionError::WrongNumberOfParts);
|
||||
}
|
||||
|
||||
Ok(Self { parts })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Version;
|
||||
|
||||
#[test]
|
||||
fn test_try_from_invalid_version() {
|
||||
assert!("".parse::<Version>().is_err());
|
||||
assert!("hello".parse::<Version>().is_err());
|
||||
assert!("1.32.hi".parse::<Version>().is_err());
|
||||
assert!("1.32..1".parse::<Version>().is_err());
|
||||
assert!("1.32".parse::<Version>().is_err());
|
||||
assert!("1.32.0.1".parse::<Version>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_single() {
|
||||
assert_eq!("1.32.0".parse(), Ok(Version { parts: [1, 32, 0] }));
|
||||
assert_eq!("1.0.0".parse(), Ok(Version { parts: [1, 0, 0] }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compare() {
|
||||
let v_1_0_0 = "1.0.0".parse::<Version>().unwrap();
|
||||
let v_1_32_0 = "1.32.0".parse::<Version>().unwrap();
|
||||
let v_1_32_1 = "1.32.1".parse::<Version>().unwrap();
|
||||
assert!(v_1_0_0 < v_1_32_1);
|
||||
assert!(v_1_0_0 < v_1_32_0);
|
||||
assert!(v_1_32_0 < v_1_32_1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_string() {
|
||||
let v_1_0_0 = "1.0.0".parse::<Version>().unwrap();
|
||||
let v_1_32_1 = "1.32.1".parse::<Version>().unwrap();
|
||||
|
||||
assert_eq!(v_1_0_0.to_string(), "1.0.0");
|
||||
assert_eq!(v_1_32_1.to_string(), "1.32.1");
|
||||
assert_eq!(format!("{:<8}", v_1_32_1), "1.32.1 ");
|
||||
assert_eq!(format!("{:>8}", v_1_32_1), " 1.32.1");
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#![deny(rust_2018_idioms)]
|
||||
|
||||
extern crate regex;
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue