1
Fork 0

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:
bors 2019-05-03 15:10:16 +00:00
commit 3af1bdc4bc
66 changed files with 891 additions and 297 deletions

View file

@ -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)",

View file

@ -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");
}
}

View file

@ -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
}

View file

@ -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),

View file

@ -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,

View file

@ -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() {

View file

@ -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

View file

@ -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) => {

View file

@ -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>,

View file

@ -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;

View file

@ -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>>,

View file

@ -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() {

View file

@ -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,

View file

@ -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");
}
}
_ => {}
}

View file

@ -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) {

View file

@ -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,

View file

@ -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>;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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() {}

View file

@ -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.

View file

@ -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:

View 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() {}

View 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

View 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() {}

View 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() {}

View 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

View file

@ -13,4 +13,5 @@ const FOO: u8 = [5u8][1];
fn main() {
black_box((FOO, FOO));
//~^ ERROR erroneous constant used
//~| ERROR erroneous constant
}

View file

@ -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`.

View file

@ -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

View file

@ -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() {}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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`.

View file

@ -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> {

View file

@ -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`.

View file

@ -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> {

View file

@ -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`.

View file

@ -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

View 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

View file

@ -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() {}

View file

@ -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`.

View file

@ -3,7 +3,7 @@
trait MyTrait<'a> { }
impl MyTrait for u32 {
//~^ ERROR missing lifetime specifier
//~^ ERROR implicit elided lifetime not allowed here
}
fn main() {}

View file

@ -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`.

View file

@ -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]
}

View file

@ -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`.

View file

@ -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`
};
}

View file

@ -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`.

View file

@ -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

View 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
}

View 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`.

View file

@ -1,5 +1,4 @@
#![feature(type_alias_enum_variants)]
#![deny(ambiguous_associated_items)]
enum E {
V

View file

@ -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;
| ^^^^^^^

View file

@ -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"

View file

@ -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,
};

View 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");
}
}

View file

@ -5,6 +5,7 @@
#![deny(rust_2018_idioms)]
extern crate regex;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;