Auto merge of #56999 - petrochenkov:macrecov2, r=estebank

AST/HIR: Introduce `ExprKind::Err` for better error recovery in the front-end

This way we can avoid aborting compilation if expansion produces errors and generate `ExprKind::Err`s instead.
This commit is contained in:
bors 2018-12-27 22:27:27 +00:00
commit f8caa321c7
127 changed files with 713 additions and 368 deletions

View File

@ -392,7 +392,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprKind::Closure(..) |
hir::ExprKind::Lit(..) |
hir::ExprKind::Path(_) => {
hir::ExprKind::Path(_) |
hir::ExprKind::Err => {
self.straightline(expr, pred, None::<hir::Expr>.iter())
}
}

View File

@ -1099,6 +1099,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprKind::Yield(ref subexpression) => {
visitor.visit_expr(subexpression);
}
ExprKind::Err => {}
}
}

View File

@ -2709,7 +2709,6 @@ impl<'a> LoweringContext<'a> {
rules: self.lower_block_check_mode(&b.rules),
span: b.span,
targeted_by_break,
recovered: b.recovered,
})
}
@ -3781,7 +3780,6 @@ impl<'a> LoweringContext<'a> {
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
recovered: blk.recovered,
});
P(self.expr_block(blk, ThinVec::new()))
}
@ -4117,6 +4115,8 @@ impl<'a> LoweringContext<'a> {
hir::ExprKind::Yield(P(expr))
}
ExprKind::Err => hir::ExprKind::Err,
// Desugar `ExprIfLet`
// from: `if let <pat> = <sub_expr> <body> [<else_opt>]`
ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => {
@ -4821,7 +4821,6 @@ impl<'a> LoweringContext<'a> {
rules: hir::DefaultBlock,
span,
targeted_by_break: false,
recovered: false,
}
}

View File

@ -807,11 +807,6 @@ pub struct Block {
/// break out of this block early.
/// Used by `'label: {}` blocks and by `catch` statements.
pub targeted_by_break: bool,
/// If true, don't emit return value type errors as the parser had
/// to recover from a parse error so this block will not have an
/// appropriate type. A parse error will have been emitted so the
/// compilation will never succeed if this is true.
pub recovered: bool,
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
@ -1362,6 +1357,7 @@ impl Expr {
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Err => ExprPrecedence::Err,
}
}
@ -1412,7 +1408,8 @@ impl Expr {
ExprKind::AddrOf(..) |
ExprKind::Binary(..) |
ExprKind::Yield(..) |
ExprKind::Cast(..) => {
ExprKind::Cast(..) |
ExprKind::Err => {
false
}
}
@ -1525,6 +1522,9 @@ pub enum ExprKind {
/// A suspension point for generators. This is `yield <expr>` in Rust.
Yield(P<Expr>),
/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err,
}
/// Optionally `Self`-qualified value/type path or associated extension.

View File

@ -430,7 +430,9 @@ impl<'a> State<'a> {
self.s.word("_")?;
}
hir::TyKind::Err => {
self.s.word("?")?;
self.popen()?;
self.s.word("/*ERROR*/")?;
self.pclose()?;
}
}
self.end()
@ -1540,6 +1542,11 @@ impl<'a> State<'a> {
self.word_space("yield")?;
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
}
hir::ExprKind::Err => {
self.popen()?;
self.s.word("/*ERROR*/")?;
self.pclose()?;
}
}
self.ann.post(self, AnnNode::Expr(expr))?;
self.end()

View File

@ -410,7 +410,6 @@ impl_stable_hash_for!(struct hir::Block {
rules,
span,
targeted_by_break,
recovered,
});
impl_stable_hash_for!(struct hir::Pat {
@ -592,7 +591,8 @@ impl_stable_hash_for!(enum hir::ExprKind {
InlineAsm(asm, inputs, outputs),
Struct(path, fields, base),
Repeat(val, times),
Yield(val)
Yield(val),
Err
});
impl_stable_hash_for!(enum hir::LocalSource {

View File

@ -222,14 +222,13 @@ impl<'a> LintLevelsBuilder<'a> {
match item.node {
ast::MetaItemKind::Word => {} // actual lint names handled later
ast::MetaItemKind::NameValue(ref name_value) => {
let gate_reasons = !self.sess.features_untracked().lint_reasons;
if item.ident == "reason" {
// found reason, reslice meta list to exclude it
metas = &metas[0..metas.len()-1];
// FIXME (#55112): issue unused-attributes lint if we thereby
// don't have any lint names (`#[level(reason = "foo")]`)
if let ast::LitKind::Str(rationale, _) = name_value.node {
if gate_reasons {
if !self.sess.features_untracked().lint_reasons {
feature_gate::emit_feature_err(
&self.sess.parse_sess,
"lint_reasons",
@ -237,9 +236,8 @@ impl<'a> LintLevelsBuilder<'a> {
feature_gate::GateIssue::Language,
"lint reasons are experimental"
);
} else {
reason = Some(rationale);
}
reason = Some(rationale);
} else {
let mut err = bad_attr(name_value.span);
err.help("reason must be a string literal");

View File

@ -479,7 +479,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
}
hir::ExprKind::Continue(..) |
hir::ExprKind::Lit(..) => {}
hir::ExprKind::Lit(..) |
hir::ExprKind::Err => {}
hir::ExprKind::Loop(ref blk, _, _) => {
self.walk_block(&blk);

View File

@ -515,6 +515,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
hir::ExprKind::Box(..) |
hir::ExprKind::Yield(..) |
hir::ExprKind::Type(..) |
hir::ExprKind::Err |
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
intravisit::walk_expr(ir, expr);
}
@ -1254,7 +1255,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_exprs(inputs, succ)
}
hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
hir::ExprKind::Lit(..) | hir::ExprKind::Err |
hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
succ
}
@ -1521,7 +1523,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => {
hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {
intravisit::walk_expr(this, expr);
}
}

View File

@ -687,7 +687,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) |
hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => {
hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) | hir::ExprKind::Err => {
Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty))
}
}

View File

@ -987,7 +987,6 @@ where
};
let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
let err_count = ecx.parse_sess.span_diagnostic.err_count();
// Expand macros now!
let krate = time(sess, "expand crate", || {
@ -1013,9 +1012,6 @@ where
let msg = "missing fragment specifier";
sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
}
if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
ecx.parse_sess.span_diagnostic.abort_if_errors();
}
if cfg!(windows) {
env::set_var("PATH", &old_path);
}
@ -1119,12 +1115,6 @@ where
})
})?;
// Unresolved macros might be due to mistyped `#[macro_use]`,
// so abort after checking for unknown attributes. (#49074)
if resolver.found_unresolved_macro {
sess.diagnostic().abort_if_errors();
}
// Lower ast -> hir.
// First, we need to collect the dep_graph.
let dep_graph = match future_dep_graph {

View File

@ -741,7 +741,6 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
fn stmt_to_block(rules: ast::BlockCheckMode,
recovered: bool,
s: Option<ast::Stmt>,
sess: &Session) -> ast::Block {
ast::Block {
@ -749,7 +748,6 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
rules,
id: sess.next_node_id(),
span: syntax_pos::DUMMY_SP,
recovered,
}
}
@ -768,7 +766,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
}
}
let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess);
let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess);
let loop_expr = P(ast::Expr {
node: ast::ExprKind::Loop(P(empty_block), None),
id: self.sess.next_node_id(),
@ -809,7 +807,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
old_blocks.push(new_block);
}
stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess)
stmt_to_block(b.rules, Some(loop_stmt), self.sess)
} else {
//push `loop {}` onto the end of our fresh block and yield that
new_block.stmts.push(loop_stmt);

View File

@ -780,6 +780,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() },
hir::ExprKind::Err => unreachable!(),
};
Expr {

View File

@ -278,25 +278,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_ty(self, ty)
}
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
// Check if the path in this `use` is not generic, such as `use foo::bar<T>;` While this
// can't happen normally thanks to the parser, a generic might sneak in if the `use` is
// built using a macro.
//
// macro_use foo {
// ($p:path) => { use $p; }
// }
// foo!(bar::baz<T>);
use_tree.prefix.segments.iter().find(|segment| {
segment.args.is_some()
}).map(|segment| {
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
"generic arguments in import path");
});
visit::walk_use_tree(self, use_tree, id);
}
fn visit_label(&mut self, label: &'a Label) {
self.check_label(label.ident);
visit::walk_label(self, label);
@ -433,17 +414,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_foreign_item(self, fi)
}
fn visit_vis(&mut self, vis: &'a Visibility) {
if let VisibilityKind::Restricted { ref path, .. } = vis.node {
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
"generic arguments in visibility path");
});
}
visit::walk_vis(self, vis)
}
fn visit_generics(&mut self, generics: &'a Generics) {
let mut seen_non_lifetime_param = false;
let mut seen_default = None;

View File

@ -449,7 +449,8 @@ fn check_expr_kind<'a, 'tcx>(
struct_result
}
hir::ExprKind::Lit(_) => Promotable,
hir::ExprKind::Lit(_) |
hir::ExprKind::Err => Promotable,
hir::ExprKind::AddrOf(_, ref expr) |
hir::ExprKind::Repeat(ref expr, _) => {

View File

@ -1576,7 +1576,6 @@ pub struct Resolver<'a> {
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
pub found_unresolved_macro: bool,
/// List of crate local macros that we need to warn about as being unused.
/// Right now this only includes macro_rules! macros, and macros 2.0.
@ -1911,7 +1910,6 @@ impl<'a> Resolver<'a> {
name_already_seen: FxHashMap::default(),
potentially_unused_imports: Vec::new(),
struct_constructors: Default::default(),
found_unresolved_macro: false,
unused_macros: FxHashSet::default(),
current_type_ascription: Vec::new(),
injected_crate: None,
@ -2024,8 +2022,10 @@ impl<'a> Resolver<'a> {
record_used_id: Option<NodeId>,
path_span: Span)
-> Option<LexicalScopeBinding<'a>> {
let record_used = record_used_id.is_some();
assert!(ns == TypeNS || ns == ValueNS);
if ident.name == keywords::Invalid.name() {
return Some(LexicalScopeBinding::Def(Def::Err));
}
if ns == TypeNS {
ident.span = if ident.name == keywords::SelfUpper.name() {
// FIXME(jseyfried) improve `Self` hygiene
@ -2038,6 +2038,7 @@ impl<'a> Resolver<'a> {
}
// Walk backwards up the ribs in scope.
let record_used = record_used_id.is_some();
let mut module = self.graph_root;
for i in (0 .. self.ribs[ns].len()).rev() {
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {

View File

@ -182,7 +182,14 @@ impl<'a> base::Resolver for Resolver<'a> {
};
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, true, force)?;
let (def, ext) = match self.resolve_macro_to_def(path, kind, &parent_scope, true, force) {
Ok((def, ext)) => (def, ext),
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
// Replace unresolved attributes with used inert attributes for better recovery.
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true })));
}
Err(determinacy) => return Err(determinacy),
};
if let Def::Macro(def_id, _) = def {
if after_derive {
@ -337,7 +344,6 @@ impl<'a> Resolver<'a> {
}
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
self.found_unresolved_macro = true;
Err(Determinacy::Determined)
}
PathResult::Module(..) => unreachable!(),
@ -353,10 +359,8 @@ impl<'a> Resolver<'a> {
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
);
match binding {
Ok(..) => {}
Err(Determinacy::Determined) => self.found_unresolved_macro = true,
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
if let Err(Determinacy::Undetermined) = binding {
return Err(Determinacy::Undetermined);
}
if trace {
@ -858,14 +862,23 @@ impl<'a> Resolver<'a> {
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
let check_consistency = |this: &mut Self, path: &[Segment], span,
kind: MacroKind, initial_def, def| {
let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
initial_def: Option<Def>, def: Def| {
if let Some(initial_def) = initial_def {
if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as ambiguity errors, so this is a bug.
span_bug!(span, "inconsistent resolution for a macro");
if initial_def == Def::NonMacroAttr(NonMacroAttrKind::Custom) {
// Yeah, legacy custom attributes are implemented using forced resolution
// (which is a best effort error recovery tool, basically), so we can't
// promise their resolution won't change later.
let msg = format!("inconsistent resolution for a macro: first {}, then {}",
initial_def.kind_name(), def.kind_name());
this.session.span_err(span, &msg);
} else {
span_bug!(span, "inconsistent resolution for a macro");
}
}
} else {
// It's possible that the macro was unresolved (indeterminate) and silently

View File

@ -4513,6 +4513,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
tcx.mk_unit()
}
hir::ExprKind::Err => {
tcx.types.err
}
}
}
@ -4769,12 +4772,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
//
// #41425 -- label the implicit `()` as being the
// "found type" here, rather than the "expected type".
//
// #44579 -- if the block was recovered during parsing,
// the type would be nonsensical and it is not worth it
// to perform the type check, so we avoid generating the
// diagnostic output.
if !self.diverges.get().always() && !blk.recovered {
if !self.diverges.get().always() {
coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
if let Some(expected_ty) = expected.only_has_type(self) {
self.consider_hint_about_removing_semicolon(blk,

View File

@ -2210,7 +2210,6 @@ fn from_target_feature(
feature_gate::GateIssue::Language,
&format!("the target feature `{}` is currently unstable", feature),
);
return None;
}
Some(Symbol::intern(feature))
}));

View File

@ -444,7 +444,6 @@ pub struct Block {
/// Distinguishes between `unsafe { ... }` and `{ ... }`
pub rules: BlockCheckMode,
pub span: Span,
pub recovered: bool,
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
@ -1001,6 +1000,7 @@ impl Expr {
ExprKind::Paren(..) => ExprPrecedence::Paren,
ExprKind::Try(..) => ExprPrecedence::Try,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Err => ExprPrecedence::Err,
}
}
}
@ -1160,6 +1160,9 @@ pub enum ExprKind {
/// A `yield`, with an optional value to be yielded.
Yield(Option<P<Expr>>),
/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err,
}
/// The explicit `Self` type in a "qualified path". The actual

View File

@ -2,7 +2,7 @@ pub use self::SyntaxExtension::*;
use ast::{self, Attribute, Name, PatKind, MetaItem};
use attr::HasAttrs;
use source_map::{self, SourceMap, Spanned, respan};
use source_map::{SourceMap, Spanned, respan};
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use edition::Edition;
use errors::{DiagnosticBuilder, DiagnosticId};
@ -456,7 +456,8 @@ impl MacResult for MacEager {
#[derive(Copy, Clone)]
pub struct DummyResult {
expr_only: bool,
span: Span
is_error: bool,
span: Span,
}
impl DummyResult {
@ -464,8 +465,13 @@ impl DummyResult {
///
/// Use this as a return value after hitting any errors and
/// calling `span_err`.
pub fn any(sp: Span) -> Box<dyn MacResult+'static> {
Box::new(DummyResult { expr_only: false, span: sp })
pub fn any(span: Span) -> Box<dyn MacResult+'static> {
Box::new(DummyResult { expr_only: false, is_error: true, span })
}
/// Same as `any`, but must be a valid fragment, not error.
pub fn any_valid(span: Span) -> Box<dyn MacResult+'static> {
Box::new(DummyResult { expr_only: false, is_error: false, span })
}
/// Create a default MacResult that can only be an expression.
@ -473,15 +479,15 @@ impl DummyResult {
/// Use this for macros that must expand to an expression, so even
/// if an error is encountered internally, the user will receive
/// an error that they also used it in the wrong place.
pub fn expr(sp: Span) -> Box<dyn MacResult+'static> {
Box::new(DummyResult { expr_only: true, span: sp })
pub fn expr(span: Span) -> Box<dyn MacResult+'static> {
Box::new(DummyResult { expr_only: true, is_error: true, span })
}
/// A plain dummy expression.
pub fn raw_expr(sp: Span) -> P<ast::Expr> {
pub fn raw_expr(sp: Span, is_error: bool) -> P<ast::Expr> {
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))),
node: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) },
span: sp,
attrs: ThinVec::new(),
})
@ -496,10 +502,11 @@ impl DummyResult {
}
}
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
/// A plain dummy type.
pub fn raw_ty(sp: Span, is_error: bool) -> P<ast::Ty> {
P(ast::Ty {
id: ast::DUMMY_NODE_ID,
node: ast::TyKind::Infer,
node: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(Vec::new()) },
span: sp
})
}
@ -507,7 +514,7 @@ impl DummyResult {
impl MacResult for DummyResult {
fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
Some(DummyResult::raw_expr(self.span))
Some(DummyResult::raw_expr(self.span, self.is_error))
}
fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
@ -550,13 +557,13 @@ impl MacResult for DummyResult {
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> {
Some(smallvec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.is_error)),
span: self.span,
}])
}
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
Some(DummyResult::raw_ty(self.span))
Some(DummyResult::raw_ty(self.span, self.is_error))
}
}
@ -796,7 +803,6 @@ pub struct ExtCtxt<'a> {
pub ecfg: expand::ExpansionConfig<'a>,
pub root_path: PathBuf,
pub resolver: &'a mut dyn Resolver,
pub resolve_err_count: usize,
pub current_expansion: ExpansionData,
pub expansions: FxHashMap<Span, Vec<String>>,
}
@ -811,7 +817,6 @@ impl<'a> ExtCtxt<'a> {
ecfg,
root_path: PathBuf::new(),
resolver,
resolve_err_count: 0,
current_expansion: ExpansionData {
mark: Mark::root(),
depth: 0,

View File

@ -587,7 +587,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
id: ast::DUMMY_NODE_ID,
rules: BlockCheckMode::Default,
span,
recovered: false,
})
}

View File

@ -344,8 +344,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
// FIXME(jseyfried): Refactor out the following logic
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
if let Some(ext) = ext {
let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
invoc_fragment_kind.dummy(invoc_span).unwrap()
});
self.collect_invocations(fragment, &[])
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
if !item.derive_allowed() {
@ -431,9 +433,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn resolve_imports(&mut self) {
if self.monotonic {
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
self.cx.resolver.resolve_imports();
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
}
}
@ -457,11 +457,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
};
if self.monotonic {
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
let mark = self.cx.current_expansion.mark;
self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
derives);
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
self.cx.resolver.visit_ast_fragment_with_placeholders(
self.cx.current_expansion.mark, &fragment_with_placeholders, derives
);
}
(fragment_with_placeholders, invocations)
@ -724,7 +722,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span,
GateIssue::Library(Some(issue)), &explain);
this.cx.trace_macros_diag();
return Err(kind.dummy(span));
}
}

View File

@ -1272,16 +1272,15 @@ impl<'a> Context<'a> {
return;
}
}
if name.starts_with("rustc_") {
gate_feature!(self, rustc_attrs, attr.span,
"unless otherwise specified, attributes \
with the prefix `rustc_` \
are reserved for internal compiler diagnostics");
} else if !attr::is_known(attr) {
// Only run the custom attribute lint during regular feature gate
// checking. Macro gating runs before the plugin attributes are
// registered, so we skip this in that case.
if !is_macro {
if !attr::is_known(attr) {
if name.starts_with("rustc_") {
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
are reserved for internal compiler diagnostics";
gate_feature!(self, rustc_attrs, attr.span, msg);
} else if !is_macro {
// Only run the custom attribute lint during regular feature gate
// checking. Macro gating runs before the plugin attributes are
// registered, so we skip this in that case.
let msg = format!("The attribute `{}` is currently unknown to the compiler and \
may have meaning added to it in the future", attr.path);
gate_feature!(self, custom_attribute, attr.span, &msg);

View File

@ -892,12 +892,11 @@ fn noop_fold_bounds<T: Folder>(bounds: GenericBounds, folder: &mut T)
}
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
b.map(|Block {id, stmts, rules, span, recovered}| Block {
b.map(|Block {id, stmts, rules, span}| Block {
id: folder.new_id(id),
stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
rules,
span: folder.new_span(span),
recovered,
})
}
@ -1367,6 +1366,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprKind::Yield(ex) => ExprKind::Yield(ex.map(|x| folder.fold_expr(x))),
ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
ExprKind::TryBlock(body) => ExprKind::TryBlock(folder.fold_block(body)),
ExprKind::Err => ExprKind::Err,
},
id: folder.new_id(id),
span: folder.new_span(span),

View File

@ -32,6 +32,7 @@ use ast::{UseTree, UseTreeKind};
use ast::{BinOpKind, UnOp};
use ast::{RangeEnd, RangeSyntax};
use {ast, attr};
use ext::base::DummyResult;
use source_map::{self, SourceMap, Spanned, respan};
use syntax_pos::{self, Span, MultiSpan, BytePos, FileName};
use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId};
@ -2870,6 +2871,7 @@ impl<'a> Parser<'a> {
let mut err = self.fatal(&format!("unknown macro variable `{}`", name));
err.span_label(self.span, "unknown macro variable");
err.emit();
self.bump();
return
}
token::Interpolated(ref nt) => {
@ -4966,16 +4968,16 @@ impl<'a> Parser<'a> {
/// Precondition: already parsed the '{'.
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
let mut stmts = vec![];
let mut recovered = false;
while !self.eat(&token::CloseDelim(token::Brace)) {
let stmt = match self.parse_full_stmt(false) {
Err(mut err) => {
err.emit();
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
self.eat(&token::CloseDelim(token::Brace));
recovered = true;
break;
Some(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Expr(DummyResult::raw_expr(self.span, true)),
span: self.span,
})
}
Ok(stmt) => stmt,
};
@ -4993,7 +4995,6 @@ impl<'a> Parser<'a> {
id: ast::DUMMY_NODE_ID,
rules: s,
span: lo.to(self.prev_span),
recovered,
}))
}

View File

@ -1093,7 +1093,9 @@ impl<'a> State<'a> {
self.s.word("_")?;
}
ast::TyKind::Err => {
self.s.word("?")?;
self.popen()?;
self.s.word("/*ERROR*/")?;
self.pclose()?;
}
ast::TyKind::ImplicitSelf => {
self.s.word("Self")?;
@ -2391,6 +2393,11 @@ impl<'a> State<'a> {
self.s.space()?;
self.print_block_with_attrs(blk, attrs)?
}
ast::ExprKind::Err => {
self.popen()?;
self.s.word("/*ERROR*/")?;
self.pclose()?
}
}
self.ann.post(self, AnnNode::Expr(expr))?;
self.end()

View File

@ -267,6 +267,7 @@ pub enum ExprPrecedence {
TryBlock,
Struct,
Async,
Err,
}
impl ExprPrecedence {
@ -325,7 +326,8 @@ impl ExprPrecedence {
ExprPrecedence::Block |
ExprPrecedence::TryBlock |
ExprPrecedence::Async |
ExprPrecedence::Struct => PREC_PAREN,
ExprPrecedence::Struct |
ExprPrecedence::Err => PREC_PAREN,
}
}
}

View File

@ -802,6 +802,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::TryBlock(ref body) => {
visitor.visit_block(body)
}
ExprKind::Err => {}
}
visitor.visit_expr_post(expression)

View File

@ -49,7 +49,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_ASM);
return DummyResult::expr(sp);
}
// Split the tts before the first colon, to avoid `asm!("x": y)` being

View File

@ -20,7 +20,6 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_CONCAT_IDENTS);
return base::DummyResult::expr(sp);
}
if tts.is_empty() {

View File

@ -3,7 +3,7 @@ use deriving::generic::*;
use deriving::generic::ty::*;
use syntax::ast::{Expr, MetaItem};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::symbol::Symbol;
@ -69,7 +69,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
span_err!(cx, trait_span, E0665,
"`Default` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_usize(trait_span, 0)
DummyResult::raw_expr(trait_span, true)
}
_ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"),
};

View File

@ -153,6 +153,5 @@ fn call_intrinsic(cx: &ExtCtxt,
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
span,
recovered: false,
}))
}

View File

@ -666,7 +666,7 @@ impl<'a, 'b> Context<'a, 'b> {
"X" => "UpperHex",
_ => {
ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname));
"Dummy"
return DummyResult::raw_expr(sp, true);
}
}
}
@ -713,7 +713,6 @@ pub fn expand_format_args_nl<'cx>(
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_FORMAT_ARGS_NL);
return base::DummyResult::expr(sp);
}
sp = sp.apply_mark(ecx.current_expansion.mark);
match parse_args(ecx, sp, tts) {
@ -761,7 +760,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
Applicability::MaybeIncorrect,
);
err.emit();
return DummyResult::raw_expr(sp);
return DummyResult::raw_expr(sp, true);
}
};
@ -857,7 +856,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
e.span_label(sp, label);
}
e.emit();
return DummyResult::raw_expr(sp);
return DummyResult::raw_expr(sp, true);
}
let arg_spans = parser.arg_places.iter()

View File

@ -29,7 +29,6 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_GLOBAL_ASM);
return DummyResult::any(sp);
}
let mut p = cx.new_parser_from_tts(tts);

View File

@ -14,11 +14,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_LOG_SYNTAX);
return base::DummyResult::any(sp);
}
println!("{}", print::pprust::tts_to_string(tts));
// any so that `log_syntax` can be invoked as an expression and item.
base::DummyResult::any(sp)
base::DummyResult::any_valid(sp)
}

View File

@ -31,8 +31,6 @@ pub fn expand(
attr_sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_CUSTOM_TEST_FRAMEWORKS);
return vec![anno_item];
}
if !ecx.ecfg.should_test { return vec![]; }

View File

@ -15,7 +15,6 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_TRACE_MACROS);
return base::DummyResult::any(sp);
}
match (tt.len(), tt.first()) {
@ -28,5 +27,5 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
}
base::DummyResult::any(sp)
base::DummyResult::any_valid(sp)
}

View File

@ -3,3 +3,5 @@
// error-pattern:cannot depend on a crate that needs a panic runtime
extern crate depends;
fn main() {}

View File

@ -0,0 +1,4 @@
error: the crate `depends` cannot depend on a crate that needs a panic runtime, but it depends on `needs_panic_runtime`
error: aborting due to previous error

View File

@ -105,7 +105,6 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
id: DUMMY_NODE_ID,
rules: BlockCheckMode::Default,
span: DUMMY_SP,
recovered: false,
});
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
},

View File

@ -1,2 +1,4 @@
#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
fn check() {}
fn main() {}

View File

@ -33,3 +33,5 @@ macro_rules! generate_s10 {
}
generate_s10!(concat!("nonexistent"));
fn main() {}

View File

@ -4,7 +4,7 @@ pub fn print(_args: std::fmt::Arguments) {}
#[macro_export]
macro_rules! myprint {
($($arg:tt)*) => (print(format_args!($($arg)*)));
($($arg:tt)*) => ($crate::print(format_args!($($arg)*)));
}
#[macro_export]

View File

@ -4,6 +4,8 @@ trait Foo {
type Bar;
}
struct Bar;
impl Bar {
#[derive(Clone)]
//~^ ERROR `derive` may only be applied to structs, enums and unions

View File

@ -5,7 +5,7 @@ LL | #[derive(Clone)]
| ^^^^^^^^^^^^^^^^
error: `derive` may only be applied to structs, enums and unions
--> $DIR/derive-on-trait-item-or-impl-item.rs:8:5
--> $DIR/derive-on-trait-item-or-impl-item.rs:10:5
|
LL | #[derive(Clone)]
| ^^^^^^^^^^^^^^^^

View File

@ -1,14 +1,27 @@
fn foo() {
println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
(0..13).collect<Vec<i32>>();
//~^ ERROR chained comparison
//~| ERROR expected value, found struct `Vec`
//~| ERROR expected value, found builtin type `i32`
//~| ERROR attempted to take value of method `collect`
}
fn bar() {
println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
Vec<i32>::new();
//~^ ERROR chained comparison
//~| ERROR expected value, found struct `Vec`
//~| ERROR expected value, found builtin type `i32`
//~| ERROR cannot find function `new` in the crate root
}
fn qux() {
println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
(0..13).collect<Vec<i32>();
//~^ ERROR chained comparison
//~| ERROR chained comparison
//~| ERROR expected value, found struct `Vec`
//~| ERROR expected value, found builtin type `i32`
//~| ERROR attempted to take value of method `collect`
//~| ERROR mismatched types
}
fn main() {}

View File

@ -1,38 +1,107 @@
error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:2:37
--> $DIR/issue-40396.rs:2:20
|
LL | println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
| ^^^^^^^^
LL | (0..13).collect<Vec<i32>>();
| ^^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:6:25
--> $DIR/issue-40396.rs:10:8
|
LL | println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
| ^^^^^^^
LL | Vec<i32>::new();
| ^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:10:37
--> $DIR/issue-40396.rs:18:20
|
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
| ^^^^^^^^
LL | (0..13).collect<Vec<i32>();
| ^^^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:10:41
--> $DIR/issue-40396.rs:18:24
|
LL | println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
| ^^^^^^
LL | (0..13).collect<Vec<i32>();
| ^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
error: aborting due to 4 previous errors
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:2:21
|
LL | (0..13).collect<Vec<i32>>();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:2:25
|
LL | (0..13).collect<Vec<i32>>();
| ^^^ not a value
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:10:5
|
LL | Vec<i32>::new();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:10:9
|
LL | Vec<i32>::new();
| ^^^ not a value
error[E0425]: cannot find function `new` in the crate root
--> $DIR/issue-40396.rs:10:15
|
LL | Vec<i32>::new();
| ^^^ not found in the crate root
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:18:21
|
LL | (0..13).collect<Vec<i32>();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:18:25
|
LL | (0..13).collect<Vec<i32>();
| ^^^ not a value
error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
--> $DIR/issue-40396.rs:2:13
|
LL | (0..13).collect<Vec<i32>>();
| ^^^^^^^
|
= help: maybe a `()` to call it is missing?
error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>`
--> $DIR/issue-40396.rs:18:13
|
LL | (0..13).collect<Vec<i32>();
| ^^^^^^^
|
= help: maybe a `()` to call it is missing?
error[E0308]: mismatched types
--> $DIR/issue-40396.rs:18:29
|
LL | (0..13).collect<Vec<i32>();
| ^^ expected bool, found ()
|
= note: expected type `bool`
found type `()`
error: aborting due to 14 previous errors
Some errors occurred: E0308, E0423, E0425, E0615.
For more information about an error, try `rustc --explain E0308`.

View File

@ -4,6 +4,10 @@
#[macro_use]
extern crate edition_kw_macro_2015;
mod module {
pub fn async() {}
}
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
@ -18,3 +22,5 @@ pub fn check_async() {
module::async(); // OK
module::r#async(); // OK
}
fn main() {}

View File

@ -1,11 +1,11 @@
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2015-2015-parsing.rs:12:31
--> $DIR/edition-keywords-2015-2015-parsing.rs:16:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^ no rules expected this token in macro call
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2015-parsing.rs:13:35
--> $DIR/edition-keywords-2015-2015-parsing.rs:17:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^ no rules expected this token in macro call

View File

@ -10,3 +10,5 @@ mod one_async {
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View File

@ -4,6 +4,10 @@
#[macro_use]
extern crate edition_kw_macro_2018;
mod module {
pub fn async() {}
}
pub fn check_async() {
let mut async = 1; // OK
let mut r#async = 1; // OK
@ -18,3 +22,5 @@ pub fn check_async() {
module::async(); // OK
module::r#async(); // OK
}
fn main() {}

View File

@ -1,11 +1,11 @@
error: no rules expected the token `r#async`
--> $DIR/edition-keywords-2015-2018-parsing.rs:12:31
--> $DIR/edition-keywords-2015-2018-parsing.rs:16:31
|
LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async`
| ^^^^^^^ no rules expected this token in macro call
error: no rules expected the token `async`
--> $DIR/edition-keywords-2015-2018-parsing.rs:13:35
--> $DIR/edition-keywords-2015-2018-parsing.rs:17:35
|
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^ no rules expected this token in macro call

View File

@ -10,3 +10,5 @@ mod one_async {
mod two_async {
produces_async_raw! {} // OK
}
fn main() {}

View File

@ -13,3 +13,5 @@ mod derive {
//~^ ERROR cannot find derive macro `x3300` in this scope
struct S;
}
fn main() {}

View File

@ -31,3 +31,5 @@ mod derive {
//~^ ERROR `derive` may only be applied to structs, enums and unions
impl S { }
}
fn main() {}

View File

@ -2,6 +2,6 @@
fn main() {
unsafe {
println!("{}", asm!("")); //~ ERROR inline assembly is not stable
println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable
}
}

View File

@ -1,8 +1,8 @@
error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722)
--> $DIR/feature-gate-asm2.rs:5:24
--> $DIR/feature-gate-asm2.rs:5:26
|
LL | println!("{}", asm!("")); //~ ERROR inline assembly is not stable
| ^^^^^^^^
LL | println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable
| ^^^^^^^^
|
= help: add #![feature(asm)] to the crate attributes to enable

View File

@ -1,3 +1,5 @@
#![feature(intrinsics, lang_items, no_core)]
#![crate_type="rlib"]
#![no_core]

View File

@ -1,5 +1,5 @@
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:13:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:15:7
|
LL | #[cfg(target_has_atomic = "8")]
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -7,7 +7,7 @@ LL | #[cfg(target_has_atomic = "8")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:19:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:21:7
|
LL | #[cfg(target_has_atomic = "8")]
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | #[cfg(target_has_atomic = "8")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:24:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:26:7
|
LL | #[cfg(target_has_atomic = "16")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -23,7 +23,7 @@ LL | #[cfg(target_has_atomic = "16")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:31:7
|
LL | #[cfg(target_has_atomic = "16")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -31,7 +31,7 @@ LL | #[cfg(target_has_atomic = "16")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:36:7
|
LL | #[cfg(target_has_atomic = "32")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -39,7 +39,7 @@ LL | #[cfg(target_has_atomic = "32")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:41:7
|
LL | #[cfg(target_has_atomic = "32")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -47,7 +47,7 @@ LL | #[cfg(target_has_atomic = "32")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:46:7
|
LL | #[cfg(target_has_atomic = "64")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -55,7 +55,7 @@ LL | #[cfg(target_has_atomic = "64")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:51:7
|
LL | #[cfg(target_has_atomic = "64")]
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -63,7 +63,7 @@ LL | #[cfg(target_has_atomic = "64")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:56:7
|
LL | #[cfg(target_has_atomic = "128")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -71,7 +71,7 @@ LL | #[cfg(target_has_atomic = "128")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:61:7
|
LL | #[cfg(target_has_atomic = "128")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -79,7 +79,7 @@ LL | #[cfg(target_has_atomic = "128")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:66:7
|
LL | #[cfg(target_has_atomic = "ptr")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -87,7 +87,7 @@ LL | #[cfg(target_has_atomic = "ptr")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7
--> $DIR/feature-gate-cfg-target-has-atomic.rs:71:7
|
LL | #[cfg(target_has_atomic = "ptr")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -95,7 +95,7 @@ LL | #[cfg(target_has_atomic = "ptr")]
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:76:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
|
LL | cfg!(target_has_atomic = "8");
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -103,7 +103,7 @@ LL | cfg!(target_has_atomic = "8");
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
|
LL | cfg!(target_has_atomic = "16");
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -111,7 +111,7 @@ LL | cfg!(target_has_atomic = "16");
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
|
LL | cfg!(target_has_atomic = "32");
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -119,7 +119,7 @@ LL | cfg!(target_has_atomic = "32");
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
|
LL | cfg!(target_has_atomic = "64");
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -127,7 +127,7 @@ LL | cfg!(target_has_atomic = "64");
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:86:10
|
LL | cfg!(target_has_atomic = "128");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -135,7 +135,7 @@ LL | cfg!(target_has_atomic = "128");
= help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
--> $DIR/feature-gate-cfg-target-has-atomic.rs:86:10
--> $DIR/feature-gate-cfg-target-has-atomic.rs:88:10
|
LL | cfg!(target_has_atomic = "ptr");
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2,4 +2,5 @@
fn main() {
concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
//~| ERROR cannot find value `ab` in this scope
}

View File

@ -6,6 +6,13 @@ LL | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
|
= help: add #![feature(concat_idents)] to the crate attributes to enable
error: aborting due to previous error
error[E0425]: cannot find value `ab` in this scope
--> $DIR/feature-gate-concat_idents2.rs:4:5
|
LL | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
| ^^^^^^^^^^^^^^^^^^^^^ not found in this scope
For more information about this error, try `rustc --explain E0658`.
error: aborting due to 2 previous errors
Some errors occurred: E0425, E0658.
For more information about an error, try `rustc --explain E0425`.

View File

@ -0,0 +1 @@

View File

@ -1,5 +1,5 @@
// gate-test-log_syntax
fn main() {
println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
}

View File

@ -1,8 +1,8 @@
error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
--> $DIR/feature-gate-log_syntax2.rs:4:20
--> $DIR/feature-gate-log_syntax2.rs:4:22
|
LL | println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
| ^^^^^^^^^^^^^
LL | println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
| ^^^^^^^^^^^^^
|
= help: add #![feature(log_syntax)] to the crate attributes to enable

View File

@ -0,0 +1 @@

View File

@ -23,3 +23,5 @@ extern {
emits_nothing!();
//~^ ERROR macro invocations in `extern {}` blocks are experimental
}
fn main() {}

View File

@ -1,8 +1,6 @@
// ignore-tidy-linelength
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
#[rustc_foo]
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
fn main() {}

View File

@ -1,5 +1,5 @@
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
--> $DIR/feature-gate-rustc-attrs.rs:5:3
--> $DIR/feature-gate-rustc-attrs.rs:3:3
|
LL | #[rustc_foo]
| ^^^^^^^^^

View File

@ -1,8 +1,6 @@
// We only want to assert that this doesn't ICE, we don't particularly care
// about whether it nor it fails to compile.
// error-pattern:
macro_rules! foo{
() => {{
macro_rules! bar{() => (())}
@ -15,9 +13,11 @@ pub fn main() {
assert!({one! two()});
//~^ ERROR macros that expand to items must either be surrounded with braces or followed by a
//~| ERROR cannot find macro `one!` in this scope
//~| ERROR mismatched types
// regardless of whether nested macro_rules works, the following should at
// least throw a conventional error.
assert!({one! two});
//~^ ERROR expected
//~^ ERROR expected `(` or `{`, found `}`
}

View File

@ -1,5 +1,5 @@
error: macros that expand to items must either be surrounded with braces or followed by a semicolon
--> $DIR/issue-10536.rs:16:22
--> $DIR/issue-10536.rs:14:22
|
LL | assert!({one! two()});
| ^^
@ -10,5 +10,21 @@ error: expected `(` or `{`, found `}`
LL | assert!({one! two});
| ^ expected `(` or `{`
error: aborting due to 2 previous errors
error: cannot find macro `one!` in this scope
--> $DIR/issue-10536.rs:14:14
|
LL | assert!({one! two()});
| ^^^
error[E0308]: mismatched types
--> $DIR/issue-10536.rs:14:13
|
LL | assert!({one! two()});
| ^^^^^^^^^^^^ expected bool, found ()
|
= note: expected type `bool`
found type `()`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,4 +1,5 @@
fn main() {
print!(testo!());
//~^ ERROR: format argument must be a string literal
//~| ERROR: cannot find macro `testo!` in this scope
}

View File

@ -8,5 +8,11 @@ help: you might be missing a string literal to format with
LL | print!("{}", testo!());
| ^^^^^
error: aborting due to previous error
error: cannot find macro `testo!` in this scope
--> $DIR/issue-11692-1.rs:2:12
|
LL | print!(testo!());
| ^^^^^
error: aborting due to 2 previous errors

View File

@ -1,3 +1,4 @@
fn main() {
concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
//~| ERROR expected a literal
}

View File

@ -1,8 +1,16 @@
error: expected a literal
--> $DIR/issue-11692-2.rs:2:13
|
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
| ^^^^^^^
|
= note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()`
error: cannot find macro `test!` in this scope
--> $DIR/issue-11692-2.rs:2:13
|
LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
| ^^^^
error: aborting due to previous error
error: aborting due to 2 previous errors

View File

@ -3,6 +3,7 @@
#[derive(Debug)]
struct Baz<T>(
concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
//~^ ERROR cannot find type `FooBar` in this scope
);
fn main() {}

View File

@ -4,5 +4,12 @@ error: `derive` cannot be used on items with type macros
LL | concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0412]: cannot find type `FooBar` in this scope
--> $DIR/issue-32950.rs:5:5
|
LL | concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
| ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0412`.

View File

@ -2,3 +2,5 @@
Sync, //~ ERROR this unsafe trait should be implemented explicitly
Copy)]
enum Foo {}
fn main() {}

View File

@ -3,3 +3,5 @@ fn intersect_map<K, V>(this: &mut HashMap<K, V>, other: HashMap<K, V>) -> bool {
this.drain()
//~^ ERROR no method named
}
fn main() {}

View File

@ -1,7 +1,3 @@
error[E0601]: `main` function not found in crate `issue_35677`
|
= note: consider adding a `main` function to `$DIR/issue-35677.rs`
error[E0599]: no method named `drain` found for type `&mut std::collections::HashMap<K, V>` in the current scope
--> $DIR/issue-35677.rs:3:10
|
@ -12,7 +8,6 @@ LL | this.drain()
`K : std::cmp::Eq`
`K : std::hash::Hash`
error: aborting due to 2 previous errors
error: aborting due to previous error
Some errors occurred: E0599, E0601.
For more information about an error, try `rustc --explain E0599`.
For more information about this error, try `rustc --explain E0599`.

View File

@ -1 +1,3 @@
#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
fn main() {}

View File

@ -16,3 +16,5 @@ trait Tr2 {
#[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
type F;
}
fn main() {}

View File

@ -4,7 +4,7 @@ macro_rules! m {
}
}
trait Trait {}
trait Tr {}
m!(Tr);

View File

@ -9,5 +9,5 @@ mod foo {
}
fn main() {
bar!();
bar!(); //~ ERROR cannot find macro `bar!` in this scope
}

View File

@ -6,6 +6,14 @@ LL | #[marco_use] // typo
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
error: aborting due to previous error
error: cannot find macro `bar!` in this scope
--> $DIR/issue-49074.rs:12:4
|
LL | bar!(); //~ ERROR cannot find macro `bar!` in this scope
| ^^^
|
= help: have you added the `#[macro_use]` on the module/import?
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -22,3 +22,4 @@ unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
//~^ ERROR #[cfg] cannot be applied on a generic parameter
//~| ERROR attribute `ignored` is currently unknown to the compiler

View File

@ -46,5 +46,14 @@ error: #[cfg] cannot be applied on a generic parameter
LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
| ^^^^^^^^^^^^
error: aborting due to 8 previous errors
error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/issue-51279.rs:23:8
|
LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
| ^^^^^^^^^^
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -22,3 +22,5 @@ pub trait Graph<'a> {
//~^ ERROR cannot infer
}
}
fn main() {}

View File

@ -1,7 +1,3 @@
error[E0601]: `main` function not found in crate `issue_55796`
|
= note: consider adding a `main` function to `$DIR/issue-55796.rs`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/issue-55796.rs:16:9
|
@ -44,7 +40,6 @@ LL | Box::new(self.in_edges(u).map(|e| e.target()))
expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)>
found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>>
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
Some errors occurred: E0495, E0601.
For more information about an error, try `rustc --explain E0495`.
For more information about this error, try `rustc --explain E0495`.

View File

@ -4,10 +4,10 @@ macro_rules! g {
($inp:ident) => (
{ $inp $nonexistent }
//~^ ERROR unknown macro variable `nonexistent`
//~| ERROR expected one of
);
}
fn main() {
let foo = 0;
g!(foo);
}

View File

@ -7,14 +7,5 @@ LL | { $inp $nonexistent }
LL | g!(foo);
| -------- in this macro invocation
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `nonexistent`
--> $DIR/issue-6596-2.rs:5:16
|
LL | { $inp $nonexistent }
| ^^^^^^^^^^^^ expected one of 8 possible tokens here
...
LL | g!(foo);
| -------- in this macro invocation
error: aborting due to 2 previous errors
error: aborting due to previous error

View File

@ -12,6 +12,9 @@ macro_rules! pong {
//~| ERROR expected one of
//~| ERROR expected one of
#[allow(non_camel_case_types)]
struct syntax;
fn main() {
pong!();
ping!();

View File

@ -1,41 +1,41 @@
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:17:23
--> $DIR/macro-comma-behavior.rs:21:23
|
LL | assert_eq!(1, 1, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:20:23
--> $DIR/macro-comma-behavior.rs:24:23
|
LL | assert_ne!(1, 2, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:26:29
--> $DIR/macro-comma-behavior.rs:30:29
|
LL | debug_assert_eq!(1, 1, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:29:29
--> $DIR/macro-comma-behavior.rs:33:29
|
LL | debug_assert_ne!(1, 2, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:50:19
--> $DIR/macro-comma-behavior.rs:54:19
|
LL | format_args!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:68:21
--> $DIR/macro-comma-behavior.rs:72:21
|
LL | unimplemented!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:77:24
--> $DIR/macro-comma-behavior.rs:81:24
|
LL | write!(f, "{}",)?;
| ^^

View File

@ -3,10 +3,14 @@
// compile-flags: -C debug_assertions=yes
// revisions: std core
#![feature(lang_items)]
#![cfg_attr(core, no_std)]
#[cfg(std)] use std::fmt;
#[cfg(core)] use core::fmt;
#[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {}
#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {}
#[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} }
// (see documentation of the similarly-named test in run-pass)
fn to_format_or_not_to_format() {

View File

@ -1,59 +1,59 @@
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:17:23
--> $DIR/macro-comma-behavior.rs:21:23
|
LL | assert_eq!(1, 1, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:20:23
--> $DIR/macro-comma-behavior.rs:24:23
|
LL | assert_ne!(1, 2, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:26:29
--> $DIR/macro-comma-behavior.rs:30:29
|
LL | debug_assert_eq!(1, 1, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:29:29
--> $DIR/macro-comma-behavior.rs:33:29
|
LL | debug_assert_ne!(1, 2, "{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:34:18
--> $DIR/macro-comma-behavior.rs:38:18
|
LL | eprint!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:46:18
--> $DIR/macro-comma-behavior.rs:50:18
|
LL | format!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:50:19
--> $DIR/macro-comma-behavior.rs:54:19
|
LL | format_args!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:57:17
--> $DIR/macro-comma-behavior.rs:61:17
|
LL | print!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:68:21
--> $DIR/macro-comma-behavior.rs:72:21
|
LL | unimplemented!("{}",);
| ^^
error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-comma-behavior.rs:77:24
--> $DIR/macro-comma-behavior.rs:81:24
|
LL | write!(f, "{}",)?;
| ^^

View File

@ -13,3 +13,5 @@ struct Test3;
#[derive]
//~^ WARNING empty trait list
struct Test4;
fn main() {}

View File

@ -1,9 +0,0 @@
error: the crate `depends` cannot depend on a crate that needs a panic runtime, but it depends on `needs_panic_runtime`
error[E0601]: `main` function not found in crate `runtime_depend_on_needs_runtime`
|
= note: consider adding a `main` function to `$DIR/runtime-depend-on-needs-runtime.rs`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0601`.

View File

@ -14,5 +14,5 @@ mod foo {
}
fn main() {
let y: u32 = foo::x;
let y: u32 = foo::x; //~ ERROR static `x` is private
}

Some files were not shown because too many files have changed in this diff Show More