1
Fork 0

Auto merge of #51448 - Mark-Simulacrum:rollup, r=Mark-Simulacrum

Rollup of 13 pull requests

Successful merges:

 - #50143 (Add deprecation lint for duplicated `macro_export`s)
 - #51099 (Fix Issue 38777)
 - #51276 (Dedup auto traits in trait objects.)
 - #51298 (Stabilize unit tests with non-`()` return type)
 - #51360 (Suggest parentheses when a struct literal needs them)
 - #51391 (Use spans pointing at the inside of a rustdoc attribute)
 - #51394 (Use scope tree depths to speed up `nearest_common_ancestor`.)
 - #51396 (Make the size of Option<NonZero*> a documented guarantee.)
 - #51401 (Warn on `repr` without hints)
 - #51412 (Avoid useless Vec clones in pending_obligations().)
 - #51427 (compiletest: autoremove duplicate .nll.* files (#51204))
 - #51436 (Do not require stage 2 compiler for rustdoc)
 - #51437 (rustbuild: generate full list of dependencies for metadata)

Failed merges:
This commit is contained in:
bors 2018-06-08 23:22:33 +00:00
commit cf91e9b9ba
54 changed files with 1108 additions and 457 deletions

View file

@ -800,10 +800,7 @@ impl<'a> Builder<'a> {
cargo.env("RUSTC_ERROR_FORMAT", error_format);
}
if cmd != "build" && cmd != "check" && want_rustdoc {
cargo.env(
"RUSTDOC_LIBDIR",
self.rustc_libdir(self.compiler(2, self.config.build)),
);
cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build));
}
if mode.is_tool() {

View file

@ -280,7 +280,8 @@ pub struct Build {
struct Crate {
name: Interned<String>,
version: String,
deps: Vec<Interned<String>>,
deps: HashSet<Interned<String>>,
id: String,
path: PathBuf,
doc_step: String,
build_step: String,

View file

@ -11,6 +11,7 @@
use std::collections::HashMap;
use std::process::Command;
use std::path::PathBuf;
use std::collections::HashSet;
use build_helper::output;
use serde_json;
@ -45,45 +46,17 @@ struct ResolveNode {
}
pub fn build(build: &mut Build) {
build_krate(build, "src/libstd");
build_krate(build, "src/libtest");
build_krate(build, "src/rustc");
}
let mut resolves = Vec::new();
build_krate(&build.std_features(), build, &mut resolves, "src/libstd");
build_krate("", build, &mut resolves, "src/libtest");
build_krate(&build.rustc_features(), build, &mut resolves, "src/rustc");
fn build_krate(build: &mut Build, krate: &str) {
// Run `cargo metadata` to figure out what crates we're testing.
//
// Down below we're going to call `cargo test`, but to test the right set
// of packages we're going to have to know what `-p` arguments to pass it
// to know what crates to test. Here we run `cargo metadata` to learn about
// the dependency graph and what `-p` arguments there are.
let mut cargo = Command::new(&build.initial_cargo);
cargo.arg("metadata")
.arg("--format-version").arg("1")
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
let output = output(&mut cargo);
let output: Output = serde_json::from_str(&output).unwrap();
let mut id2name = HashMap::new();
for package in output.packages {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
id2name.insert(package.id, name);
let mut path = PathBuf::from(package.manifest_path);
path.pop();
build.crates.insert(name, Crate {
build_step: format!("build-crate-{}", name),
doc_step: format!("doc-crate-{}", name),
test_step: format!("test-crate-{}", name),
bench_step: format!("bench-crate-{}", name),
name,
version: package.version,
deps: Vec::new(),
path,
});
}
for (name, krate) in build.crates.iter() {
id2name.insert(krate.id.clone(), name.clone());
}
for node in output.resolve.nodes {
for node in resolves {
let name = match id2name.get(&node.id) {
Some(name) => name,
None => continue,
@ -95,7 +68,42 @@ fn build_krate(build: &mut Build, krate: &str) {
Some(dep) => dep,
None => continue,
};
krate.deps.push(*dep);
krate.deps.insert(*dep);
}
}
}
fn build_krate(features: &str, build: &mut Build, resolves: &mut Vec<ResolveNode>, krate: &str) {
// Run `cargo metadata` to figure out what crates we're testing.
//
// Down below we're going to call `cargo test`, but to test the right set
// of packages we're going to have to know what `-p` arguments to pass it
// to know what crates to test. Here we run `cargo metadata` to learn about
// the dependency graph and what `-p` arguments there are.
let mut cargo = Command::new(&build.initial_cargo);
cargo.arg("metadata")
.arg("--format-version").arg("1")
.arg("--features").arg(features)
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
let output = output(&mut cargo);
let output: Output = serde_json::from_str(&output).unwrap();
for package in output.packages {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
let mut path = PathBuf::from(package.manifest_path);
path.pop();
build.crates.insert(name, Crate {
build_step: format!("build-crate-{}", name),
doc_step: format!("doc-crate-{}", name),
test_step: format!("test-crate-{}", name),
bench_step: format!("bench-crate-{}", name),
name,
version: package.version,
id: package.id,
deps: HashSet::new(),
path,
});
}
}
resolves.extend(output.resolve.nodes);
}

View file

@ -39,10 +39,10 @@ macro_rules! nonzero_integers {
$(
/// An integer that is known not to equal zero.
///
/// This may enable some memory layout optimization such as:
/// This enables some memory layout optimization.
/// For example, `Option<NonZeroU32>` is the same size as `u32`:
///
/// ```rust
/// # #![feature(nonzero)]
/// use std::mem::size_of;
/// assert_eq!(size_of::<Option<std::num::NonZeroU32>>(), size_of::<u32>());
/// ```

View file

@ -17,6 +17,7 @@
use errors::{Applicability, DiagnosticBuilder};
use lint::{LintPass, LateLintPass, LintArray};
use session::Session;
use syntax::ast;
use syntax::codemap::Span;
declare_lint! {
@ -206,6 +207,12 @@ declare_lint! {
"potentially-conflicting impls were erroneously allowed"
}
declare_lint! {
pub BAD_REPR,
Warn,
"detects incorrect use of `repr` attribute"
}
declare_lint! {
pub DEPRECATED,
Warn,
@ -285,6 +292,12 @@ declare_lint! {
"warns about duplicate associated type bindings in generics"
}
declare_lint! {
pub DUPLICATE_MACRO_EXPORTS,
Deny,
"detects duplicate macro exports"
}
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
@ -337,6 +350,7 @@ impl LintPass for HardwiredLints {
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
DUPLICATE_MACRO_EXPORTS,
)
}
}
@ -348,6 +362,7 @@ pub enum BuiltinLintDiagnostics {
Normal,
BareTraitObject(Span, /* is_global */ bool),
AbsPathWithModule(Span),
DuplicatedMacroExports(ast::Ident, Span, Span),
}
impl BuiltinLintDiagnostics {
@ -380,6 +395,10 @@ impl BuiltinLintDiagnostics {
};
db.span_suggestion_with_applicability(span, "use `crate`", sugg, app);
}
BuiltinLintDiagnostics::DuplicatedMacroExports(ident, earlier_span, later_span) => {
db.span_label(later_span, format!("`{}` already exported", ident));
db.span_note(earlier_span, "previous macro export is now shadowed");
}
}
}
}

View file

@ -22,7 +22,6 @@ use ty;
use std::fmt;
use std::mem;
use rustc_data_structures::small_vec::SmallVec;
use rustc_data_structures::sync::Lrc;
use syntax::codemap;
use syntax::ast;
@ -280,6 +279,8 @@ impl Scope {
}
}
pub type ScopeDepth = u32;
/// The region scope tree encodes information about region relationships.
#[derive(Default, Debug)]
pub struct ScopeTree {
@ -297,7 +298,7 @@ pub struct ScopeTree {
/// conditional expression or repeating block. (Note that the
/// enclosing scope id for the block associated with a closure is
/// the closure itself.)
parent_map: FxHashMap<Scope, Scope>,
parent_map: FxHashMap<Scope, (Scope, ScopeDepth)>,
/// `var_map` maps from a variable or binding id to the block in
/// which that variable is declared.
@ -415,11 +416,12 @@ pub struct Context {
/// details.
root_id: Option<hir::ItemLocalId>,
/// the scope that contains any new variables declared
var_parent: Option<Scope>,
/// The scope that contains any new variables declared, plus its depth in
/// the scope tree.
var_parent: Option<(Scope, ScopeDepth)>,
/// region parent of expressions etc
parent: Option<Scope>,
/// Region parent of expressions, etc., plus its depth in the scope tree.
parent: Option<(Scope, ScopeDepth)>,
}
struct RegionResolutionVisitor<'a, 'tcx: 'a> {
@ -499,7 +501,7 @@ impl<'tcx> Visitor<'tcx> for ExprLocatorVisitor {
}
impl<'tcx> ScopeTree {
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
debug!("{:?}.parent = {:?}", child, parent);
if let Some(p) = parent {
@ -515,7 +517,7 @@ impl<'tcx> ScopeTree {
pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(Scope, Scope) {
for (&child, &parent) in &self.parent_map {
e(child, parent)
e(child, parent.0)
}
}
@ -558,7 +560,7 @@ impl<'tcx> ScopeTree {
pub fn opt_encl_scope(&self, id: Scope) -> Option<Scope> {
//! Returns the narrowest scope that encloses `id`, if any.
self.parent_map.get(&id).cloned()
self.parent_map.get(&id).cloned().map(|(p, _)| p)
}
#[allow(dead_code)] // used in cfg
@ -590,7 +592,7 @@ impl<'tcx> ScopeTree {
// returned.
let mut id = Scope::Node(expr_id);
while let Some(&p) = self.parent_map.get(&id) {
while let Some(&(p, _)) = self.parent_map.get(&id) {
match p.data() {
ScopeData::Destruction(..) => {
debug!("temporary_scope({:?}) = {:?} [enclosing]",
@ -658,57 +660,61 @@ impl<'tcx> ScopeTree {
}
}
/// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest
/// scope which is greater than or equal to both `scope_a` and `scope_b`.
pub fn nearest_common_ancestor(&self,
scope_a: Scope,
scope_b: Scope)
-> Scope {
/// Finds the nearest common ancestor of two scopes. That is, finds the
/// smallest scope which is greater than or equal to both `scope_a` and
/// `scope_b`.
pub fn nearest_common_ancestor(&self, scope_a: Scope, scope_b: Scope) -> Scope {
if scope_a == scope_b { return scope_a; }
// Process the lists in tandem from the innermost scope, recording the
// scopes seen so far. The first scope that comes up for a second time
// is the nearest common ancestor.
//
// Note: another way to compute the nearest common ancestor is to get
// the full scope chain for both scopes and then compare the chains to
// find the first scope in a common tail. But getting a parent scope
// requires a hash table lookup, and we often have very long scope
// chains (10s or 100s of scopes) that only differ by a few elements at
// the start. So this algorithm is faster.
let mut a = scope_a;
let mut b = scope_b;
let mut ma = Some(&scope_a);
let mut mb = Some(&scope_b);
// Get the depth of each scope's parent. If either scope has no parent,
// it must be the root, which means we can stop immediately because the
// root must be the nearest common ancestor. (In practice, this is
// moderately common.)
let (parent_a, parent_a_depth) = match self.parent_map.get(&a) {
Some(pd) => *pd,
None => return a,
};
let (parent_b, parent_b_depth) = match self.parent_map.get(&b) {
Some(pd) => *pd,
None => return b,
};
// A HashSet<Scope> is a more obvious choice for these, but SmallVec is
// faster because the set size is normally small so linear search is
// as good or better than a hash table lookup, plus the size is usually
// small enough to avoid a heap allocation.
let mut seen_a: SmallVec<[&Scope; 32]> = SmallVec::new();
let mut seen_b: SmallVec<[&Scope; 32]> = SmallVec::new();
loop {
if let Some(a) = ma {
if seen_b.iter().any(|s| *s == a) {
return *a;
if parent_a_depth > parent_b_depth {
// `a` is lower than `b`. Move `a` up until it's at the same depth
// as `b`. The first move up is trivial because we already found
// `parent_a` above; the loop does the remaining N-1 moves.
a = parent_a;
for _ in 0..(parent_a_depth - parent_b_depth - 1) {
a = self.parent_map.get(&a).unwrap().0;
}
seen_a.push(a);
ma = self.parent_map.get(&a);
} else if parent_b_depth > parent_a_depth {
// `b` is lower than `a`.
b = parent_b;
for _ in 0..(parent_b_depth - parent_a_depth - 1) {
b = self.parent_map.get(&b).unwrap().0;
}
} else {
// Both scopes are at the same depth, and we know they're not equal
// because that case was tested for at the top of this function. So
// we can trivially move them both up one level now.
assert!(parent_a_depth != 0);
a = parent_a;
b = parent_b;
}
if let Some(b) = mb {
if seen_a.iter().any(|s| *s == b) {
return *b;
}
seen_b.push(b);
mb = self.parent_map.get(&b);
}
// Now both scopes are at the same level. We move upwards in lockstep
// until they match. In practice, this loop is almost always executed
// zero times because `a` is almost always a direct ancestor of `b` or
// vice versa.
while a != b {
a = self.parent_map.get(&a).unwrap().0;
b = self.parent_map.get(&b).unwrap().0;
};
if ma.is_none() && mb.is_none() {
// No nearest common ancestor found.
bug!();
}
}
a
}
/// Assuming that the provided region was defined within this `ScopeTree`,
@ -807,7 +813,7 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor,
//
// extern fn isalnum(c: c_int) -> c_int
}
Some(parent_scope) =>
Some((parent_scope, _)) =>
visitor.scope_tree.record_var_scope(var_id, parent_scope),
}
}
@ -1019,7 +1025,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
// Keep traversing up while we can.
match visitor.scope_tree.parent_map.get(&scope) {
// Don't cross from closure bodies to their parent.
Some(&superscope) => match superscope.data() {
Some(&(superscope, _)) => match superscope.data() {
ScopeData::CallSite(_) => break,
_ => scope = superscope
},
@ -1036,7 +1042,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
init: Option<&'tcx hir::Expr>) {
debug!("resolve_local(pat={:?}, init={:?})", pat, init);
let blk_scope = visitor.cx.var_parent;
let blk_scope = visitor.cx.var_parent.map(|(p, _)| p);
// As an exception to the normal rules governing temporary
// lifetimes, initializers in a let have a temporary lifetime
@ -1261,16 +1267,20 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
/// Records the current parent (if any) as the parent of `child_scope`.
fn record_child_scope(&mut self, child_scope: Scope) {
/// Returns the depth of `child_scope`.
fn record_child_scope(&mut self, child_scope: Scope) -> ScopeDepth {
let parent = self.cx.parent;
self.scope_tree.record_scope_parent(child_scope, parent);
// If `child_scope` has no parent, it must be the root node, and so has
// a depth of 1. Otherwise, its depth is one more than its parent's.
parent.map_or(1, |(_p, d)| d + 1)
}
/// Records the current parent (if any) as the parent of `child_scope`,
/// and sets `child_scope` as the new current parent.
fn enter_scope(&mut self, child_scope: Scope) {
self.record_child_scope(child_scope);
self.cx.parent = Some(child_scope);
let child_depth = self.record_child_scope(child_scope);
self.cx.parent = Some((child_scope, child_depth));
}
fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {

View file

@ -13,7 +13,7 @@ use ty::{self, Ty, TyCtxt};
use hir::def_id::DefId;
use super::{FulfillmentContext, FulfillmentError};
use super::{ObligationCause, PendingPredicateObligation, PredicateObligation};
use super::{ObligationCause, PredicateObligation};
pub trait TraitEngine<'tcx>: 'tcx {
fn normalize_projection_type<'a, 'gcx>(
@ -49,7 +49,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>>;
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
}
impl<'a, 'gcx, 'tcx> dyn TraitEngine<'tcx> {

View file

@ -241,8 +241,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.select(&mut selcx)
}
fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
self.predicates.pending_obligations()
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.predicates.map_pending_obligations(|o| o.obligation.clone())
}
}

View file

@ -229,13 +229,13 @@ impl<O: ForestObligation> ObligationForest<O> {
}
/// Returns the set of obligations that are in a pending state.
pub fn pending_obligations(&self) -> Vec<O>
where O: Clone
pub fn map_pending_obligations<P, F>(&self, f: F) -> Vec<P>
where F: Fn(&O) -> P
{
self.nodes
.iter()
.filter(|n| n.state.get() == NodeState::Pending)
.map(|n| n.obligation.clone())
.map(|n| f(&n.obligation))
.collect()
}

View file

@ -191,11 +191,12 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
self.infcx.tcx
}
pub fn create_region_hierarchy(&mut self, rh: &RH, parent: region::Scope) {
pub fn create_region_hierarchy(&mut self, rh: &RH,
parent: (region::Scope, region::ScopeDepth)) {
let me = region::Scope::Node(rh.id);
self.region_scope_tree.record_scope_parent(me, Some(parent));
for child_rh in rh.sub {
self.create_region_hierarchy(child_rh, me);
self.create_region_hierarchy(child_rh, (me, parent.1 + 1));
}
}
@ -215,7 +216,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
id: hir::ItemLocalId(11),
sub: &[],
}],
}, dscope);
}, (dscope, 1));
}
#[allow(dead_code)] // this seems like it could be useful, even if we don't use it now

View file

@ -673,6 +673,79 @@ impl EarlyLintPass for AnonymousParameters {
}
}
/// Checks for incorrect use use of `repr` attributes.
#[derive(Clone)]
pub struct BadRepr;
impl LintPass for BadRepr {
fn get_lints(&self) -> LintArray {
lint_array!()
}
}
impl EarlyLintPass for BadRepr {
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
if attr.name() == "repr" {
let list = attr.meta_item_list();
let repr_str = |lit: &str| { format!("#[repr({})]", lit) };
// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
// no hints (``#[repr]`)
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
if !has_hints {
let mut suggested = false;
let mut warn = if let Some(ref lit) = attr.value_str() {
// avoid warning about empty `repr` on `#[repr = "foo"]`
let mut warn = cx.struct_span_lint(
BAD_REPR,
attr.span,
"`repr` attribute isn't configurable with a literal",
);
match format!("{}", lit).as_ref() {
| "C" | "packed" | "rust" | "transparent"
| "u8" | "u16" | "u32" | "u64" | "u128" | "usize"
| "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => {
// if the literal could have been a valid `repr` arg,
// suggest the correct syntax
warn.span_suggestion(
attr.span,
"give `repr` a hint",
repr_str(&lit.as_str()),
);
suggested = true;
}
_ => { // the literal wasn't a valid `repr` arg
warn.span_label(attr.span, "needs a hint");
}
};
warn
} else {
let mut warn = cx.struct_span_lint(
BAD_REPR,
attr.span,
"`repr` attribute must have a hint",
);
warn.span_label(attr.span, "needs a hint");
warn
};
if !suggested {
warn.help(&format!(
"valid hints include `{}`, `{}`, `{}` and `{}`",
repr_str("C"),
repr_str("packed"),
repr_str("rust"),
repr_str("transparent"),
));
warn.note("for more information, visit \
<https://doc.rust-lang.org/reference/type-layout.html>");
}
warn.emit();
}
}
}
}
/// Checks for use of attributes which have been deprecated.
#[derive(Clone)]
pub struct DeprecatedAttr {

View file

@ -107,6 +107,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnusedImportBraces,
AnonymousParameters,
UnusedDocComment,
BadRepr,
);
add_early_builtin_with_new!(sess,
@ -211,6 +212,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
edition: None,
},
FutureIncompatibleInfo {
id: LintId::of(DUPLICATE_MACRO_EXPORTS),
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
edition: Some(Edition::Edition2018),
},
FutureIncompatibleInfo {
id: LintId::of(SAFE_EXTERN_STATICS),
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",

View file

@ -2934,8 +2934,38 @@ impl<'a> Resolver<'a> {
here due to private fields"));
}
} else {
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
path_str));
// HACK(estebank): find a better way to figure out that this was a
// parser issue where a struct literal is being used on an expression
// where a brace being opened means a block is being started. Look
// ahead for the next text to see if `span` is followed by a `{`.
let cm = this.session.codemap();
let mut sp = span;
loop {
sp = cm.next_point(sp);
match cm.span_to_snippet(sp) {
Ok(ref snippet) => {
if snippet.chars().any(|c| { !c.is_whitespace() }) {
break;
}
}
_ => break,
}
}
let followed_by_brace = match cm.span_to_snippet(sp) {
Ok(ref snippet) if snippet == "{" => true,
_ => false,
};
if let (PathSource::Expr(None), true) = (source, followed_by_brace) {
err.span_label(
span,
format!("did you mean `({} {{ /* fields */ }})`?", path_str),
);
} else {
err.span_label(
span,
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
);
}
}
return (err, candidates);
}

View file

@ -18,13 +18,14 @@ use {names_to_string, module_to_string};
use {resolve_error, ResolutionError};
use rustc::ty;
use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE;
use rustc::lint::builtin::BuiltinLintDiagnostics;
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::def::*;
use rustc::session::DiagnosticMessageId;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use syntax::ast::{Ident, Name, NodeId};
use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::symbol::keywords;
@ -974,7 +975,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
if module as *const _ == self.graph_root as *const _ {
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
for export in macro_exports.into_iter().rev() {
if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),
export.span) {
self.session.buffer_lint_with_diagnostic(
DUPLICATE_MACRO_EXPORTS,
CRATE_NODE_ID,
later_span,
&format!("a macro named `{}` has already been exported", export.ident),
BuiltinLintDiagnostics::DuplicatedMacroExports(
export.ident, export.span, later_span));
} else {
reexports.push(export);
}
}

View file

@ -30,6 +30,7 @@ use util::common::ErrorReported;
use util::nodemap::{FxHashSet, FxHashMap};
use errors::FatalError;
// use std::cmp::Ordering;
use std::iter;
use syntax::ast;
use syntax::feature_gate::{GateIssue, emit_feature_err};
@ -646,7 +647,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
&mut vec![]);
}
let (auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
let (mut auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
if !trait_bounds.is_empty() {
let b = &trait_bounds[0];
@ -707,6 +708,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
.emit();
}
// Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
auto_traits.sort();
auto_traits.dedup();
// skip_binder is okay, because the predicates are re-bound.
let mut v =
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
@ -1319,7 +1324,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
}
/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the
/// Divides a list of general trait bounds into two groups: auto traits (e.g. Sync and Send) and the
/// remaining general trait bounds.
fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_bounds: &'b [hir::PolyTraitRef])

View file

@ -225,7 +225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_sig = fulfillment_cx
.pending_obligations()
.iter()
.map(|obligation| &obligation.obligation)
.filter_map(|obligation| {
debug!(
"deduce_expectations_from_obligations: obligation.predicate={:?}",
@ -257,7 +256,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let expected_kind = fulfillment_cx
.pending_obligations()
.iter()
.map(|obligation| &obligation.obligation)
.filter_map(|obligation| {
let opt_trait_ref = match obligation.predicate {
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),

View file

@ -1251,30 +1251,60 @@ fn resolution_failure(
link_range: Option<Range<usize>>,
) {
let sp = span_of_attrs(attrs);
let mut diag = cx.sess()
.struct_span_warn(sp, &format!("[{}] cannot be resolved, ignoring it...", path_str));
let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
if let Some(link_range) = link_range {
let code_dox = sp.to_src(cx);
let doc_comment_padding = 3;
let mut diag = if let Some(link_range) = link_range {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~~~
// | link_range
// last_new_line_offset
let mut diag;
if dox.lines().count() == code_dox.lines().count() {
let line_offset = dox[..link_range.start].lines().count();
// The span starts in the `///`, so we don't have to account for the leading whitespace
let code_dox_len = if line_offset <= 1 {
doc_comment_padding
} else {
// The first `///`
doc_comment_padding +
// Each subsequent leading whitespace and `///`
code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
sum + doc_comment_padding + line.len() - line.trim().len()
})
};
// Extract the specific span
let sp = sp.from_inner_byte_pos(
link_range.start + code_dox_len,
link_range.end + code_dox_len,
);
diag = cx.sess().struct_span_warn(sp, &msg);
diag.span_label(sp, "cannot be resolved, ignoring");
} else {
diag = cx.sess().struct_span_warn(sp, &msg);
let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
// Print the line containing the `link_range` and manually mark it with '^'s
diag.note(&format!(
"the link appears in this line:\n\n{line}\n{indicator: <before$}{indicator:^<found$}",
"the link appears in this line:\n\n{line}\n\
{indicator: <before$}{indicator:^<found$}",
line=line,
indicator="",
before=link_range.start - last_new_line_offset,
found=link_range.len(),
));
} else {
}
diag
} else {
cx.sess().struct_span_warn(sp, &msg)
};
diag.emit();
}

View file

@ -398,9 +398,6 @@ declare_features! (
// `foo.rs` as an alternative to `foo/mod.rs`
(active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
// Termination trait in tests (RFC 1937)
(active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)),
// `extern` in paths
(active, extern_in_paths, "1.23.0", Some(44660), None),
@ -616,6 +613,8 @@ declare_features! (
(accepted, fn_must_use, "1.27.0", Some(43302), None),
// Allows use of the :lifetime macro fragment specifier
(accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
// Termination trait in tests (RFC 1937)
(accepted, termination_trait_test, "1.27.0", Some(48854), None),
);
// If you change this, please modify src/doc/unstable-book as well. You must

View file

@ -652,7 +652,7 @@ impl<'a> Parser<'a> {
Err(err)
}
} else {
self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[])
self.expect_one_of(slice::from_ref(t), &[])
}
}
@ -1108,7 +1108,12 @@ impl<'a> Parser<'a> {
{
let mut first: bool = true;
let mut v = vec![];
while !kets.contains(&&self.token) {
while !kets.iter().any(|k| {
match expect {
TokenExpectType::Expect => self.check(k),
TokenExpectType::NoExpect => self.token == **k,
}
}) {
match self.token {
token::CloseDelim(..) | token::Eof => break,
_ => {}

View file

@ -335,7 +335,7 @@ enum BadTestSignature {
fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
let has_test_attr = attr::contains_name(&i.attrs, "test");
fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
fn has_test_signature(_cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
match i.node {
ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
@ -351,15 +351,14 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
return No(BadTestSignature::NoArgumentsAllowed);
}
match (has_output, cx.features.termination_trait_test, has_should_panic_attr) {
(true, true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
(true, true, false) => if generics.is_parameterized() {
match (has_output, has_should_panic_attr) {
(true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
(true, false) => if generics.is_parameterized() {
No(BadTestSignature::WrongTypeSignature)
} else {
Yes
},
(true, false, _) => No(BadTestSignature::WrongTypeSignature),
(false, _, _) => Yes
(false, _) => Yes
}
}
_ => No(BadTestSignature::NotEvenAFunction),
@ -395,31 +394,12 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
let has_bench_attr = attr::contains_name(&i.attrs, "bench");
fn has_bench_signature(cx: &TestCtxt, i: &ast::Item) -> bool {
fn has_bench_signature(_cx: &TestCtxt, i: &ast::Item) -> bool {
match i.node {
ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
let input_cnt = decl.inputs.len();
// If the termination trait is active, the compiler will check that the output
// type implements the `Termination` trait as `libtest` enforces that.
let output_matches = if cx.features.termination_trait_test {
true
} else {
let no_output = match decl.output {
ast::FunctionRetTy::Default(..) => true,
ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
_ => false
};
let tparm_cnt = generics.params.iter()
.filter(|param| param.is_type_param())
.count();
no_output && tparm_cnt == 0
};
ast::ItemKind::Fn(ref decl, _, _, _, _, _) => {
// NB: inadequate check, but we're running
// well before resolve, can't get too deep.
input_cnt == 1 && output_matches
decl.inputs.len() == 1
}
_ => false
}
@ -430,13 +410,8 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
if has_bench_attr && !has_bench_signature {
let diag = cx.span_diagnostic;
if cx.features.termination_trait_test {
diag.span_err(i.span, "functions used as benches must have signature \
`fn(&mut Bencher) -> impl Termination`");
} else {
diag.span_err(i.span, "functions used as benches must have signature \
`fn(&mut Bencher) -> ()`");
}
}
has_bench_attr && has_bench_signature

View file

@ -9,7 +9,7 @@
// except according to those terms.
fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
//~| ERROR expected one of `->`, `where`, or `{`, found `]`
//~| ERROR expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
// FIXME(jseyfried): avoid emitting the second error (preexisting)
fn main() {}

View file

@ -34,6 +34,7 @@ fn main() {
#[repr]
let _y = "123";
//~^^ ERROR attribute should not be applied to a statement
//~| WARN `repr` attribute must have a hint
fn foo() {}
@ -44,5 +45,5 @@ fn main() {
let _z = #[repr] 1;
//~^ ERROR attribute should not be applied to an expression
//~| WARN `repr` attribute must have a hint
}

View file

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(duplicate_macro_exports)]
#[macro_export]
macro_rules! foo { ($i:ident) => {} }

View file

@ -1,4 +1,4 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,15 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --test
macro_rules! macro_one { ($($t:tt)*) => ($($t)*) }
fn main() {}
#[cfg(test)]
mod tests {
#[test]
fn it_works() -> Result<(), ()> {
//~^ ERROR functions used as tests must have signature fn() -> ()
Ok(())
}
}
macro_rules! macro_two { ($($t:tt)*) => ($($t)*) }

View file

@ -20,12 +20,12 @@ pub fn main() {
#[path = "auxiliary"]
mod foo {
mod two_macros;
mod two_macros_2;
}
#[path = "auxiliary"]
mod bar {
macro_rules! m { () => { mod two_macros; } }
macro_rules! m { () => { mod two_macros_2; } }
m!();
}
}

View file

@ -0,0 +1,53 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that duplicate auto trait bounds in trait objects don't create new types.
#[allow(unused_assignments)]
use std::marker::Send as SendAlias;
// A dummy trait for the non-auto trait.
trait Trait {}
// A dummy struct to implement Trait, Send, and .
struct Struct;
impl Trait for Struct {}
// These three functions should be equivalent.
fn takes_dyn_trait_send(_: Box<dyn Trait + Send>) {}
fn takes_dyn_trait_send_send(_: Box<dyn Trait + Send + Send>) {}
fn takes_dyn_trait_send_sendalias(_: Box<dyn Trait + Send + SendAlias>) {}
impl dyn Trait + Send + Send {
fn do_nothing(&self) {}
}
fn main() {
// 1. Moving into a variable with more Sends and back.
let mut dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
let dyn_trait_send_send: Box<dyn Trait + Send + Send> = dyn_trait_send;
dyn_trait_send = dyn_trait_send_send;
// 2. Calling methods with different number of Sends.
let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
takes_dyn_trait_send_send(dyn_trait_send);
let dyn_trait_send_send = Box::new(Struct) as Box<dyn Trait + Send + Send>;
takes_dyn_trait_send(dyn_trait_send_send);
// 3. Aliases to the trait are transparent.
let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
takes_dyn_trait_send_sendalias(dyn_trait_send);
// 4. Calling an impl that duplicates an auto trait.
let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
dyn_trait_send.do_nothing();
}

View file

@ -10,10 +10,48 @@
// compile-pass
//! Test with [Foo::baz], [Bar::foo], ...
//!
//! and [Uniooon::X].
//! Test with [Foo::baz], [Bar::foo], ...
//! , [Uniooon::X] and [Qux::Z].
//!
//! , [Uniooon::X] and [Qux::Z].
/// [Qux:Y]
pub struct Foo {
pub bar: usize,
}
/// Foo
/// bar [BarA] bar
/// baz
pub fn a() {}
/**
* Foo
* bar [BarB] bar
* baz
*/
pub fn b() {}
/** Foo
bar [BarC] bar
baz
let bar_c_1 = 0;
let bar_c_2 = 0;
let g = [bar_c_1];
let h = g[bar_c_2];
*/
pub fn c() {}
#[doc = "Foo\nbar [BarD] bar\nbaz"]
pub fn d() {}
macro_rules! f {
($f:expr) => {
#[doc = $f]
pub fn f() {}
}
}
f!("Foo\nbar [BarF] bar\nbaz");

View file

@ -1,39 +1,105 @@
warning: [Foo::baz] cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:13:1
warning: `[Foo::baz]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:13:23
|
13 | / //! Test with [Foo::baz], [Bar::foo], ...
14 | | //!
15 | | //! and [Uniooon::X].
| |_____________________^
13 | //! Test with [Foo::baz], [Bar::foo], ...
| ^^^^^^^^ cannot be resolved, ignoring
warning: `[Bar::foo]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:13:35
|
13 | //! Test with [Foo::baz], [Bar::foo], ...
| ^^^^^^^^ cannot be resolved, ignoring
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:14:13
|
14 | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ cannot be resolved, ignoring
warning: `[Qux::Z]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:14:30
|
14 | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ cannot be resolved, ignoring
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:16:14
|
16 | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ cannot be resolved, ignoring
warning: `[Qux::Z]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:16:31
|
16 | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ cannot be resolved, ignoring
warning: `[Qux:Y]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:18:13
|
18 | /// [Qux:Y]
| ^^^^^ cannot be resolved, ignoring
warning: `[BarA]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:24:10
|
24 | /// bar [BarA] bar
| ^^^^ cannot be resolved, ignoring
warning: `[BarB]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:28:1
|
28 | / /**
29 | | * Foo
30 | | * bar [BarB] bar
31 | | * baz
32 | | */
| |___^
|
= note: the link appears in this line:
Test with [Foo::baz], [Bar::foo], ...
^^^^^^^^
bar [BarB] bar
^^^^
warning: [Bar::foo] cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:13:1
warning: `[BarC]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:35:1
|
13 | / //! Test with [Foo::baz], [Bar::foo], ...
14 | | //!
15 | | //! and [Uniooon::X].
| |_____________________^
35 | / /** Foo
36 | |
37 | | bar [BarC] bar
38 | | baz
... |
44 | |
45 | | */
| |__^
|
= note: the link appears in this line:
Test with [Foo::baz], [Bar::foo], ...
^^^^^^^^
bar [BarC] bar
^^^^
warning: [Uniooon::X] cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:13:1
warning: `[BarD]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:48:1
|
13 | / //! Test with [Foo::baz], [Bar::foo], ...
14 | | //!
15 | | //! and [Uniooon::X].
| |_____________________^
48 | #[doc = "Foo/nbar [BarD] bar/nbaz"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the link appears in this line:
and [Uniooon::X].
^^^^^^^^^^
bar [BarD] bar
^^^^
warning: `[BarF]` cannot be resolved, ignoring it...
--> $DIR/intra-links-warning.rs:53:9
|
53 | #[doc = $f]
| ^^^^^^^^^^^
...
57 | f!("Foo/nbar [BarF] bar/nbaz");
| ------------------------------- in this macro invocation
|
= note: the link appears in this line:
bar [BarF] bar
^^^^

View file

@ -13,3 +13,22 @@ fn main () {
let f = Foo(); //~ ERROR E0423
}
fn bar() {
struct S { x: i32, y: i32 }
#[derive(PartialEq)]
struct T {}
if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
//~^ ERROR E0423
//~| expected type, found `1`
if T {} == T {} { println!("Ok"); }
//~^ ERROR E0423
//~| ERROR expected expression, found `==`
}
fn foo() {
for _ in std::ops::Range { start: 0, end: 10 } {}
//~^ ERROR E0423
//~| ERROR expected type, found `0`
}

View file

@ -1,9 +1,48 @@
error: expected type, found `1`
--> $DIR/E0423.rs:22:39
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
| ^ expecting a type here because of type ascription
error: expected expression, found `==`
--> $DIR/E0423.rs:25:13
|
LL | if T {} == T {} { println!("Ok"); }
| ^^ expected expression
error: expected type, found `0`
--> $DIR/E0423.rs:31:39
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
| ^ expecting a type here because of type ascription
error[E0423]: expected function, found struct `Foo`
--> $DIR/E0423.rs:14:13
|
LL | let f = Foo(); //~ ERROR E0423
| ^^^ did you mean `Foo { /* fields */ }`?
| ^^^
| |
| did you mean `foo`?
| did you mean `Foo { /* fields */ }`?
error: aborting due to previous error
error[E0423]: expected value, found struct `S`
--> $DIR/E0423.rs:22:32
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
| ^ did you mean `(S { /* fields */ })`?
error[E0423]: expected value, found struct `T`
--> $DIR/E0423.rs:25:8
|
LL | if T {} == T {} { println!("Ok"); }
| ^ did you mean `(T { /* fields */ })`?
error[E0423]: expected value, found struct `std::ops::Range`
--> $DIR/E0423.rs:31:14
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
| ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0423`.

View file

@ -59,7 +59,9 @@
#![start = "x4300"] //~ WARN unused attribute
// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
#![repr = "3900"] //~ WARN unused attribute
#![repr = "3900"]
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
#![path = "3800"] //~ WARN unused attribute
#![abi = "3700"] //~ WARN unused attribute
#![automatically_derived = "3600"] //~ WARN unused attribute
@ -309,20 +311,25 @@ mod bench {
#[repr = "3900"]
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
mod repr {
mod inner { #![repr="3900"] }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
#[repr = "3900"] fn f() { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
struct S;
#[repr = "3900"] type T = S;
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
#[repr = "3900"] impl S { }
//~^ WARN unused attribute
//~| WARN `repr` attribute isn't configurable with a literal
}
#[path = "3800"]

View file

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_export]
macro_rules! foo { ($i:ident) => {} }
#[macro_export]
macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
//~| WARN this was previously accepted

View file

@ -0,0 +1,22 @@
error: a macro named `foo` has already been exported
--> $DIR/issue-38715.rs:15:1
|
LL | macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported
|
= note: #[deny(duplicate_macro_exports)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
= note: for more information, see issue #35896 <https://github.com/rust-lang/rust/issues/35896>
note: previous macro export is now shadowed
--> $DIR/issue-38715.rs:12:1
|
LL | macro_rules! foo { ($i:ident) => {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0601]: `main` function not found in crate `issue_38715`
|
= note: consider adding a `main` function to `$DIR/issue-38715.rs`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0601`.

View file

@ -10,11 +10,11 @@ note: unclosed delimiter
LL | callback(path.as_ref(); //~ ERROR expected one of
| ^
error: expected one of `,`, `.`, `?`, or an operator, found `;`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
--> $DIR/token-error-correct-3.rs:24:35
|
LL | callback(path.as_ref(); //~ ERROR expected one of
| ^ expected one of `,`, `.`, `?`, or an operator here
| ^ expected one of `)`, `,`, `.`, `?`, or an operator here
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
--> $DIR/token-error-correct-3.rs:30:9

View file

@ -10,7 +10,6 @@
// compile-flags: --test
#![feature(termination_trait_test)]
#![feature(test)]
extern crate test;

View file

@ -1,5 +1,5 @@
error: functions using `#[should_panic]` must return `()`
--> $DIR/termination-trait-in-test-should-panic.rs:22:1
--> $DIR/termination-trait-in-test-should-panic.rs:21:1
|
LL | / fn not_a_num() -> Result<(), ParseIntError> {
LL | | //~^ ERROR functions using `#[should_panic]` must return `()`

View file

@ -11,7 +11,6 @@
// compile-flags: --test
// run-pass
#![feature(termination_trait_test)]
#![feature(test)]
extern crate test;

View file

@ -10,8 +10,6 @@
// compile-flags: --test
#![feature(termination_trait_test)]
use std::num::ParseIntError;
#[test]

View file

@ -1,5 +1,5 @@
error[E0277]: `main` has invalid return type `std::result::Result<f32, std::num::ParseIntError>`
--> $DIR/termination-trait-test-wrong-type.rs:18:1
--> $DIR/termination-trait-test-wrong-type.rs:16:1
|
LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> { //~ ERROR
LL | | "0".parse()

View file

@ -14,6 +14,6 @@ mod x {
}
// `.` is similar to `,` so list parsing should continue to closing `}`
use x::{A. B}; //~ ERROR expected one of `,`, `::`, or `as`, found `.`
use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.`
fn main() {}

View file

@ -1,8 +1,8 @@
error: expected one of `,`, `::`, or `as`, found `.`
error: expected one of `,`, `::`, `as`, or `}`, found `.`
--> $DIR/similar-tokens.rs:17:10
|
LL | use x::{A. B}; //~ ERROR expected one of `,`, `::`, or `as`, found `.`
| ^ expected one of `,`, `::`, or `as` here
LL | use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.`
| ^ expected one of `,`, `::`, `as`, or `}` here
error: aborting due to previous error

View file

@ -0,0 +1,28 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-pass
#[repr]
//^ WARN `repr` attribute must have a hint
struct _A {}
#[repr = "B"]
//^ WARN `repr` attribute isn't configurable with a literal
struct _B {}
#[repr = "C"]
//^ WARN `repr` attribute isn't configurable with a literal
struct _C {}
#[repr(C)]
struct _D {}
fn main() {}

View file

@ -0,0 +1,25 @@
warning: `repr` attribute must have a hint
--> $DIR/repr.rs:13:1
|
LL | #[repr]
| ^^^^^^^ needs a hint
|
= note: #[warn(bad_repr)] on by default
= help: valid hints include `#[repr(C)]`, `#[repr(packed)]`, `#[repr(rust)]` and `#[repr(transparent)]`
= note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html>
warning: `repr` attribute isn't configurable with a literal
--> $DIR/repr.rs:17:1
|
LL | #[repr = "B"]
| ^^^^^^^^^^^^^ needs a hint
|
= help: valid hints include `#[repr(C)]`, `#[repr(packed)]`, `#[repr(rust)]` and `#[repr(transparent)]`
= note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html>
warning: `repr` attribute isn't configurable with a literal
--> $DIR/repr.rs:21:1
|
LL | #[repr = "C"]
| ^^^^^^^^^^^^^ help: give `repr` a hint: `#[repr(C)]`

View file

@ -10,11 +10,11 @@ note: unclosed delimiter
LL | option.map(|some| 42;
| ^
error: expected one of `,`, `.`, `?`, or an operator, found `;`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
--> $DIR/issue-10636-2.rs:15:25
|
LL | option.map(|some| 42;
| ^ expected one of `,`, `.`, `?`, or an operator here
| ^ expected one of `)`, `,`, `.`, `?`, or an operator here
error: expected expression, found `)`
--> $DIR/issue-10636-2.rs:18:1

View file

@ -0,0 +1,29 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type.
// Issue: #47010
struct Struct;
impl Trait for Struct {}
trait Trait {}
type Send1 = Trait + Send;
type Send2 = Trait + Send + Send;
fn main () {}
impl Trait + Send {
fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
}
impl Trait + Send + Send {
fn test(&self) { println!("two"); }
}

View file

@ -0,0 +1,12 @@
error[E0592]: duplicate definitions with name `test`
--> $DIR/trait-object-auto-dedup-in-impl.rs:24:5
|
LL | fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`
...
LL | fn test(&self) { println!("two"); }
| ----------------------------------- other definition for `test`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0592`.

View file

@ -12,6 +12,6 @@ mod foo {
type T = ();
struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
struct S2(pub((foo)) ());
//~^ ERROR expected `,`, found `(`
//~^ ERROR expected one of `)` or `,`, found `(`
//~| ERROR cannot find type `foo` in this scope
}

View file

@ -0,0 +1,20 @@
error: expected one of `)` or `,`, found `(`
--> $DIR/test.rs:14:26
|
LL | struct S2(pub((foo)) ());
| ^ expected one of `)` or `,` here
error[E0412]: cannot find type `foo` in this scope
--> $DIR/test.rs:14:20
|
LL | struct S2(pub((foo)) ());
| ^^^ not found in this scope
error[E0601]: `main` function not found in crate `test`
|
= note: consider adding a `main` function to `$DIR/test.rs`
error: aborting due to 3 previous errors
Some errors occurred: E0412, E0601.
For more information about an error, try `rustc --explain E0412`.

View file

@ -13,7 +13,7 @@ macro_rules! define_struct {
struct S1(pub $t);
struct S2(pub (in foo) ());
struct S3(pub $t ());
//~^ ERROR expected `,`, found `(`
//~^ ERROR expected one of `)` or `,`, found `(`
}
}

View file

@ -0,0 +1,11 @@
error: expected one of `)` or `,`, found `(`
--> $DIR/test2.rs:15:26
|
LL | struct S3(pub $t ());
| ^ expected one of `)` or `,` here
...
LL | define_struct! { (foo) }
| ------------------------ in this macro invocation
error: aborting due to previous error

View file

@ -13,7 +13,7 @@ macro_rules! define_struct {
struct S1(pub($t));
struct S2(pub (in foo) ());
struct S3(pub($t) ());
//~^ ERROR expected `,`, found `(`
//~^ ERROR expected one of `)` or `,`, found `(`
}
}

View file

@ -0,0 +1,11 @@
error: expected one of `)` or `,`, found `(`
--> $DIR/test3.rs:15:27
|
LL | struct S3(pub($t) ());
| ^ expected one of `)` or `,` here
...
LL | define_struct! { foo }
| ---------------------- in this macro invocation
error: aborting due to previous error

View file

@ -9,7 +9,7 @@
// except according to those terms.
use common::CompareMode;
use common::{expected_output_path, UI_FIXED, UI_STDERR, UI_STDOUT};
use common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
use common::{output_base_dir, output_base_name, output_testname_unique};
use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
@ -2609,6 +2609,9 @@ impl<'test> TestCx<'test> {
errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
let modes_to_prune = vec![CompareMode::Nll];
self.prune_duplicate_outputs(&modes_to_prune);
if self.config.compare_mode.is_some() {
// don't test rustfix with nll right now
} else if self.props.run_rustfix {
@ -2971,6 +2974,16 @@ impl<'test> TestCx<'test> {
}
}
fn delete_file(&self, file: &PathBuf) {
if let Err(e) = ::std::fs::remove_file(file) {
self.fatal(&format!(
"failed to delete `{}`: {}",
file.display(),
e,
));
}
}
fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
if actual == expected {
return 0;
@ -3023,13 +3036,7 @@ impl<'test> TestCx<'test> {
for output_file in &files {
if actual.is_empty() {
if let Err(e) = ::std::fs::remove_file(output_file) {
self.fatal(&format!(
"failed to delete `{}`: {}",
output_file.display(),
e,
));
}
self.delete_file(output_file);
} else {
match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
Ok(()) => {}
@ -3054,6 +3061,42 @@ impl<'test> TestCx<'test> {
}
}
fn prune_duplicate_output(&self, mode: CompareMode, kind: &str, canon_content: &str) {
let examined_path = expected_output_path(
&self.testpaths,
self.revision,
&Some(mode),
kind,
);
let examined_content = self
.load_expected_output_from_path(&examined_path)
.unwrap_or_else(|_| String::new());
if examined_path.exists() && canon_content == &examined_content {
self.delete_file(&examined_path);
}
}
fn prune_duplicate_outputs(&self, modes: &[CompareMode]) {
if self.config.bless {
for kind in UI_EXTENSIONS {
let canon_comparison_path = expected_output_path(
&self.testpaths,
self.revision,
&None,
kind,
);
if let Ok(canon) = self.load_expected_output_from_path(&canon_comparison_path) {
for mode in modes {
self.prune_duplicate_output(mode.clone(), kind, &canon);
}
}
}
}
}
fn create_stamp(&self) {
let mut f = File::create(::stamp(&self.config, self.testpaths, self.revision)).unwrap();
f.write_all(compute_stamp_hash(&self.config).as_bytes())