diff --git a/Cargo.lock b/Cargo.lock index c1011c0f479cb..9f43f5a8b36b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,7 +285,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.52.0" +version = "0.53.0" dependencies = [ "anyhow", "atty", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cd0ad2b0150be..3550055ac10d3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -486,8 +486,8 @@ pub struct WhereEqPredicate { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Crate { - pub module: Mod, pub attrs: Vec, + pub items: Vec>, pub span: Span, /// The order of items in the HIR is unrelated to the order of /// items in the AST. However, we generate proc macro harnesses @@ -2299,21 +2299,22 @@ impl FnRetTy { } } -/// Module declaration. -/// -/// E.g., `mod foo;` or `mod foo { .. }`. +#[derive(Clone, PartialEq, Encodable, Decodable, Debug)] +pub enum Inline { + Yes, + No, +} + +/// Module item kind. #[derive(Clone, Encodable, Decodable, Debug)] -pub struct Mod { - /// A span from the first token past `{` to the last token until `}`. - /// For `mod foo;`, the inner span ranges from the first token - /// to the last token in the external file. - pub inner: Span, - /// `unsafe` keyword accepted syntactically for macro DSLs, but not - /// semantically by Rust. - pub unsafety: Unsafe, - pub items: Vec>, - /// `true` for `mod foo { .. }`; `false` for `mod foo;`. - pub inline: bool, +pub enum ModKind { + /// Module with inlined definition `mod foo { ... }`, + /// or with definition outlined to a separate file `mod foo;` and already loaded from it. + /// The inner span is from the first token past `{` to the last token until `}`, + /// or from the first to the last token in the loaded file. + Loaded(Vec>, Inline, Span), + /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it. + Unloaded, } /// Foreign module declaration. @@ -2710,7 +2711,9 @@ pub enum ItemKind { /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. - Mod(Mod), + /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not + /// semantically by Rust. + Mod(Unsafe, ModKind), /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 024d9687f3119..c286738811ca1 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -170,10 +170,6 @@ pub trait MutVisitor: Sized { noop_visit_ty_constraint(t, self); } - fn visit_mod(&mut self, m: &mut Mod) { - noop_visit_mod(m, self); - } - fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { noop_visit_foreign_mod(nm, self); } @@ -917,7 +913,13 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { vis.visit_generics(generics); visit_opt(body, |body| vis.visit_block(body)); } - ItemKind::Mod(m) => vis.visit_mod(m), + ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { + ModKind::Loaded(items, _inline, inner_span) => { + vis.visit_span(inner_span); + items.flat_map_in_place(|item| vis.flat_map_item(item)); + } + ModKind::Unloaded => {} + }, ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(_ga) => {} ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => { @@ -998,14 +1000,10 @@ pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { vis.visit_asyncness(asyncness); } -pub fn noop_visit_mod(module: &mut Mod, vis: &mut T) { - let Mod { inner, unsafety: _, items, inline: _ } = module; - vis.visit_span(inner); - items.flat_map_in_place(|item| vis.flat_map_item(item)); -} - +// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible, +// or make crate visiting first class if necessary. pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { - visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| { + visit_clobber(krate, |Crate { attrs, items, span, proc_macros }| { let item_vis = Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; let item = P(Item { @@ -1014,19 +1012,20 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { id: DUMMY_NODE_ID, vis: item_vis, span, - kind: ItemKind::Mod(module), + kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)), tokens: None, }); let items = vis.flat_map_item(item); let len = items.len(); if len == 0 { - let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true }; - Crate { module, attrs: vec![], span, proc_macros } + Crate { attrs: vec![], items: vec![], span, proc_macros } } else if len == 1 { let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); match kind { - ItemKind::Mod(module) => Crate { module, attrs, span, proc_macros }, + ItemKind::Mod(_, ModKind::Loaded(items, ..)) => { + Crate { attrs, items, span, proc_macros } + } _ => panic!("visitor converted a module to not a module"), } } else { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c37d4cd9f7936..32b9dd46baef4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -74,7 +74,7 @@ impl<'a> FnKind<'a> { /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -/// e.g., the `visit_mod` method by default calls `visit::walk_mod`. +/// e.g., the `visit_item` method by default calls `visit::walk_item`. /// /// If you want to ensure that your code handles every variant /// explicitly, you need to override each method. (And you also need @@ -87,9 +87,6 @@ pub trait Visitor<'ast>: Sized { fn visit_ident(&mut self, ident: Ident) { walk_ident(self, ident); } - fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) { - walk_mod(self, m); - } fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) } @@ -238,14 +235,10 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) { } pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { - visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID); + walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); } -pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) { - walk_list!(visitor, visit_item, &module.items); -} - pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) { for attr in local.attrs.iter() { visitor.visit_attribute(attr); @@ -297,7 +290,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id) } - ItemKind::Mod(ref module) => visitor.visit_mod(module, item.span, &item.attrs, item.id), + ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind { + ModKind::Loaded(items, _inline, _inner_span) => { + walk_list!(visitor, visit_item, items) + } + ModKind::Unloaded => {} + }, ItemKind::ForeignMod(ref foreign_module) => { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cad2a21d1a4a7..8b740b7774089 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -15,11 +15,11 @@ use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; - use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use tracing::debug; +use std::mem; + pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>, } @@ -34,25 +34,6 @@ impl ItemLowerer<'_, '_, '_> { } impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { - fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) { - let def_id = self.lctx.lower_node_id(n).expect_owner(); - - self.lctx.modules.insert( - def_id, - hir::ModuleItems { - items: BTreeSet::new(), - trait_items: BTreeSet::new(), - impl_items: BTreeSet::new(), - foreign_items: BTreeSet::new(), - }, - ); - - let old = self.lctx.current_module; - self.lctx.current_module = def_id; - visit::walk_mod(self, m); - self.lctx.current_module = old; - } - fn visit_item(&mut self, item: &'a Item) { let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { @@ -67,10 +48,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { if let Some(hir_id) = item_hir_id { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(box ImplKind { ref of_trait, .. }) = item.kind { - this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); - } else { - visit::walk_item(this, item); + match item.kind { + ItemKind::Mod(..) => { + let def_id = this.lctx.lower_node_id(item.id).expect_owner(); + let old_current_module = + mem::replace(&mut this.lctx.current_module, def_id); + visit::walk_item(this, item); + this.lctx.current_module = old_current_module; + } + ItemKind::Impl(box ImplKind { ref of_trait, .. }) => { + this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); + } + _ => visit::walk_item(this, item), } }); } @@ -94,13 +83,13 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { let hir_item = lctx.lower_trait_item(item); let id = hir_item.trait_item_id(); lctx.trait_items.insert(id, hir_item); - lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); + lctx.modules.entry(lctx.current_module).or_default().trait_items.insert(id); } AssocCtxt::Impl => { let hir_item = lctx.lower_impl_item(item); let id = hir_item.impl_item_id(); lctx.impl_items.insert(id, hir_item); - lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); + lctx.modules.entry(lctx.current_module).or_default().impl_items.insert(id); } }); @@ -113,7 +102,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { let hir_item = lctx.lower_foreign_item(item); let id = hir_item.foreign_item_id(); lctx.foreign_items.insert(id, hir_item); - lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id); + lctx.modules.entry(lctx.current_module).or_default().foreign_items.insert(id); }); visit::walk_foreign_item(self, item); @@ -157,7 +146,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T, ) -> T { - let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); + let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]); // this vector is only used when walking over impl headers, // input types, and the like, and should not be non-empty in @@ -172,12 +161,10 @@ impl<'hir> LoweringContext<'_, 'hir> { res } - pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod<'hir> { + pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { hir::Mod { - inner: m.inner, - item_ids: self - .arena - .alloc_from_iter(m.items.iter().flat_map(|x| self.lower_item_id(x))), + inner, + item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))), } } @@ -327,7 +314,12 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Fn(sig, generics, body_id) }) } - ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)), + ItemKind::Mod(_, ref mod_kind) => match mod_kind { + ModKind::Loaded(items, _, inner_span) => { + hir::ItemKind::Mod(self.lower_mod(items, *inner_span)) + } + ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), + }, ItemKind::ForeignMod(ref fm) => { if fm.abi.is_none() { self.maybe_lint_missing_abi(span, id, abi::Abi::C); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9d0b2cd5c675d..05b417effd491 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -560,7 +560,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); - let module = self.lower_mod(&c.module); + let module = self.lower_mod(&c.items, c.span); let attrs = self.lower_attrs(&c.attrs); let body_ids = body_ids(&self.bodies); let proc_macros = @@ -608,7 +608,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { let id = hir::ItemId { def_id: item.def_id }; self.items.insert(id, item); - self.modules.get_mut(&self.current_module).unwrap().items.insert(id); + self.modules.entry(self.current_module).or_default().items.insert(id); id } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8defd91c688d7..563bcda519065 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1054,12 +1054,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; } - ItemKind::Mod(Mod { inline, unsafety, .. }) => { + ItemKind::Mod(unsafety, ref mod_kind) => { if let Unsafe::Yes(span) = unsafety { self.err_handler().span_err(span, "module cannot be declared unsafe"); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). - if !inline && !self.session.contains_name(&item.attrs, sym::path) { + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) + && !self.session.contains_name(&item.attrs, sym::path) + { self.check_mod_file_item_asciionly(item.ident); } } diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 2971fa435c8dc..fb7e0d3450fde 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -20,10 +20,6 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_ident(self, ident); } - fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) { - self.count += 1; - walk_mod(self, m) - } fn visit_foreign_item(&mut self, i: &ForeignItem) { self.count += 1; walk_foreign_item(self, i) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7f712643d19ad..82f6e936b766e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -9,7 +9,7 @@ use rustc_ast::util::classify; use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; -use rustc_ast::{GenericArg, MacArgs}; +use rustc_ast::{GenericArg, MacArgs, ModKind}; use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; @@ -87,7 +87,6 @@ pub struct State<'a> { pub s: pp::Printer, comments: Option>, ann: &'a (dyn PpAnn + 'a), - is_expanded: bool, } crate const INDENT_UNIT: usize = 4; @@ -103,12 +102,8 @@ pub fn print_crate<'a>( is_expanded: bool, edition: Edition, ) -> String { - let mut s = State { - s: pp::mk_printer(), - comments: Some(Comments::new(sm, filename, input)), - ann, - is_expanded, - }; + let mut s = + State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }; if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) { // We need to print `#![no_std]` (and its feature gate) so that @@ -132,7 +127,10 @@ pub fn print_crate<'a>( } } - s.print_mod(&krate.module, &krate.attrs); + s.print_inner_attributes(&krate.attrs); + for item in &krate.items { + s.print_item(item); + } s.print_remaining_comments(); s.ann.post(&mut s, AnnNode::Crate(krate)); s.s.eof() @@ -853,7 +851,7 @@ impl<'a> PrintState<'a> for State<'a> { impl<'a> State<'a> { pub fn new() -> State<'a> { - State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false } + State { s: pp::mk_printer(), comments: None, ann: &NoAnn } } // Synthesizes a comment that was not textually present in the original source @@ -891,13 +889,6 @@ impl<'a> State<'a> { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span) } - pub fn print_mod(&mut self, _mod: &ast::Mod, attrs: &[ast::Attribute]) { - self.print_inner_attributes(attrs); - for item in &_mod.items { - self.print_item(item); - } - } - crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) { self.print_inner_attributes(attrs); for item in &nmod.items { @@ -1139,23 +1130,29 @@ impl<'a> State<'a> { let body = body.as_deref(); self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs); } - ast::ItemKind::Mod(ref _mod) => { + ast::ItemKind::Mod(unsafety, ref mod_kind) => { self.head(self.to_string(|s| { s.print_visibility(&item.vis); - s.print_unsafety(_mod.unsafety); + s.print_unsafety(unsafety); s.word("mod"); })); self.print_ident(item.ident); - if _mod.inline || self.is_expanded { - self.nbsp(); - self.bopen(); - self.print_mod(_mod, &item.attrs); - self.bclose(item.span); - } else { - self.s.word(";"); - self.end(); // end inner head-block - self.end(); // end outer head-block + match mod_kind { + ModKind::Loaded(items, ..) => { + self.nbsp(); + self.bopen(); + self.print_inner_attributes(&item.attrs); + for item in items { + self.print_item(item); + } + self.bclose(item.span); + } + ModKind::Unloaded => { + self.s.word(";"); + self.end(); // end inner head-block + self.end(); // end outer head-block + } } } ast::ItemKind::ForeignMod(ref nmod) => { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 7582d9805390e..71bbae1161b4b 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -91,7 +91,7 @@ pub fn inject( } let decls = mk_decls(&mut krate, &mut cx, ¯os); - krate.module.items.push(decls); + krate.items.push(decls); krate } diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 91566ec1ef245..3a81d076dc52f 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -44,7 +44,7 @@ pub fn inject( // .rev() to preserve ordering above in combination with insert(0, ...) for &name in names.iter().rev() { let ident = if rust_2018 { Ident::new(name, span) } else { Ident::new(name, call_site) }; - krate.module.items.insert( + krate.items.insert( 0, cx.item( span, @@ -79,7 +79,7 @@ pub fn inject( })), ); - krate.module.items.insert(0, use_item); + krate.items.insert(0, use_item); krate } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 4ac22be3c275d..28e8259784387 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -1,10 +1,10 @@ // Code that generates a test runner to run all the tests in a crate use rustc_ast as ast; -use rustc_ast::attr; use rustc_ast::entry::EntryPointType; use rustc_ast::mut_visit::{ExpectOne, *}; use rustc_ast::ptr::P; +use rustc_ast::{attr, ModKind}; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; @@ -89,7 +89,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { noop_visit_crate(c, self); // Create a main function to run our tests - c.module.items.push(mk_main(&mut self.cx)); + c.items.push(mk_main(&mut self.cx)); } fn flat_map_item(&mut self, i: P) -> SmallVec<[P; 1]> { @@ -103,9 +103,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(mut module) = item.kind { + if let ast::ItemKind::Mod(..) = item.kind { let tests = mem::take(&mut self.tests); - noop_visit_mod(&mut module, self); + noop_visit_item_kind(&mut item.kind, self); let mut tests = mem::replace(&mut self.tests, tests); if !tests.is_empty() { @@ -113,8 +113,12 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id }; // Create an identifier that will hygienically resolve the test // case name, even in another module. + let inner_span = match item.kind { + ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span, + _ => unreachable!(), + }; let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( - module.inner, + inner_span, AstPass::TestHarness, &[], Some(parent), @@ -126,7 +130,6 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { } self.cx.test_cases.extend(tests); } - item.kind = ast::ItemKind::Mod(module); } smallvec![P(item)] } diff --git a/compiler/rustc_driver/src/args.rs b/compiler/rustc_driver/src/args.rs index 4f2febf04b135..01338359f1af1 100644 --- a/compiler/rustc_driver/src/args.rs +++ b/compiler/rustc_driver/src/args.rs @@ -3,7 +3,7 @@ use std::fmt; use std::fs; use std::io; -pub fn arg_expand(arg: String) -> Result, Error> { +fn arg_expand(arg: String) -> Result, Error> { if let Some(path) = arg.strip_prefix('@') { let file = match fs::read_to_string(path) { Ok(file) => file, @@ -18,6 +18,20 @@ pub fn arg_expand(arg: String) -> Result, Error> { } } +pub fn arg_expand_all(at_args: &[String]) -> Vec { + let mut args = Vec::new(); + for arg in at_args { + match arg_expand(arg.clone()) { + Ok(arg) => args.extend(arg), + Err(err) => rustc_session::early_error( + rustc_session::config::ErrorOutputType::default(), + &format!("Failed to load argument file: {}", err), + ), + } + } + args +} + #[derive(Debug)] pub enum Error { Utf8Error(Option), diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 8295e88f75ac7..cad5a87bb1346 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -55,7 +55,7 @@ use std::process::{self, Command, Stdio}; use std::str; use std::time::Instant; -mod args; +pub mod args; pub mod pretty; /// Exit status code used for successful compilation and help output. @@ -188,16 +188,8 @@ fn run_compiler( Box Box + Send>, >, ) -> interface::Result<()> { - let mut args = Vec::new(); - for arg in at_args { - match args::arg_expand(arg.clone()) { - Ok(arg) => args.extend(arg), - Err(err) => early_error( - ErrorOutputType::default(), - &format!("Failed to load argument file: {}", err), - ), - } - } + let args = args::arg_expand_all(at_args); + let diagnostic_output = emitter.map_or(DiagnosticOutput::Default, DiagnosticOutput::Raw); let matches = match handle_options(&args) { Some(matches) => matches, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index b07bce94870c1..ad04fa9a95816 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -209,7 +209,7 @@ pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) None => { // The entire crate is unconfigured. krate.attrs = Vec::new(); - krate.module.items = Vec::new(); + krate.items = Vec::new(); Features::default() } Some(attrs) => { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f23e3b9f7471a..5a4737842f0af 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,8 +12,8 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AttrItem, AttrStyle, Block, ItemKind, LitKind, MacArgs}; -use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, NestedMetaItem}; +use rustc_ast::{AttrItem, AttrStyle, Block, Inline, ItemKind, LitKind, MacArgs}; +use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; @@ -350,6 +350,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { MacroExpander { cx, monotonic } } + // FIXME: Avoid visiting the crate as a `Mod` item, + // make crate a first class expansion target instead. pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { let mut module = ModuleData { mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], @@ -362,12 +364,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.root_path = module.directory.clone(); self.cx.current_expansion.module = Rc::new(module); - let orig_mod_span = krate.module.inner; - let krate_item = AstFragment::Items(smallvec![P(ast::Item { attrs: krate.attrs, span: krate.span, - kind: ast::ItemKind::Mod(krate.module), + kind: ast::ItemKind::Mod( + Unsafe::No, + ModKind::Loaded(krate.items, Inline::Yes, krate.span) + ), ident: Ident::invalid(), id: ast::DUMMY_NODE_ID, vis: ast::Visibility { @@ -379,28 +382,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> { })]); match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { - Some(ast::Item { attrs, kind: ast::ItemKind::Mod(module), .. }) => { + Some(ast::Item { + attrs, + kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)), + .. + }) => { krate.attrs = attrs; - krate.module = module; + krate.items = items; } None => { // Resolution failed so we return an empty expansion krate.attrs = vec![]; - krate.module = ast::Mod { - inner: orig_mod_span, - unsafety: Unsafe::No, - items: vec![], - inline: true, - }; + krate.items = vec![]; } Some(ast::Item { span, kind, .. }) => { krate.attrs = vec![]; - krate.module = ast::Mod { - inner: orig_mod_span, - unsafety: Unsafe::No, - items: vec![], - inline: true, - }; + krate.items = vec![]; self.cx.span_err( span, &format!( @@ -814,7 +811,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { - ast::ItemKind::Mod(module) if !module.inline => { + ast::ItemKind::Mod(_, mod_kind) + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) => + { feature_err( self.parse_sess, sym::proc_macro_hygiene, @@ -1271,52 +1270,47 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => { + ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { let sess = &self.cx.sess.parse_sess; let orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop. let dir = Directory { ownership: orig_ownership, path: module.directory }; - let Directory { ownership, path } = if old_mod.inline { - // Inline `mod foo { ... }`, but we still need to push directories. - item.attrs = attrs; - push_directory(&self.cx.sess, ident, &item.attrs, dir) - } else { - // We have an outline `mod foo;` so we need to parse the file. - let (new_mod, dir) = parse_external_mod( - &self.cx.sess, - ident, - span, - old_mod.unsafety, - dir, - &mut attrs, - pushed, - ); - - let krate = ast::Crate { - span: new_mod.inner, - module: new_mod, - attrs, - proc_macros: vec![], - }; - if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { - extern_mod_loaded(&krate, ident); + let Directory { ownership, path } = match mod_kind { + ModKind::Loaded(_, Inline::Yes, _) => { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(&self.cx.sess, ident, &item.attrs, dir) + } + ModKind::Loaded(_, Inline::No, _) => { + panic!("`mod` item is loaded from a file for the second time") } + ModKind::Unloaded => { + // We have an outline `mod foo;` so we need to parse the file. + let (items, inner_span, dir) = + parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed); + + let krate = + ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] }; + if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { + extern_mod_loaded(&krate, ident); + } - *old_mod = krate.module; - item.attrs = krate.attrs; - // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. - item = match self.configure(item) { - Some(node) => node, - None => { - if *pushed { - sess.included_mod_stack.borrow_mut().pop(); + *mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span); + item.attrs = krate.attrs; + // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. + item = match self.configure(item) { + Some(node) => node, + None => { + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } + return Default::default(); } - return Default::default(); - } - }; - dir + }; + dir + } }; // Set the module info before we flat map. diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 171cb3fa8e6e9..076d3b02be93f 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,4 +1,5 @@ -use rustc_ast::{token, Attribute, Mod, Unsafe}; +use rustc_ast::ptr::P; +use rustc_ast::{token, Attribute, Item}; use rustc_errors::{struct_span_err, PResult}; use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; @@ -42,11 +43,10 @@ crate fn parse_external_mod( sess: &Session, id: Ident, span: Span, // The span to blame on errors. - unsafety: Unsafe, Directory { mut ownership, path }: Directory, attrs: &mut Vec, pop_mod_stack: &mut bool, -) -> (Mod, Directory) { +) -> (Vec>, Span, Directory) { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. @@ -62,26 +62,22 @@ crate fn parse_external_mod( // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); - let mut module = parser.parse_mod(&token::Eof, unsafety)?; - module.0.inline = false; - module + let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?; + attrs.append(&mut inner_attrs); + (items, inner_span) }; // (1) ...instead, we return a dummy module. - let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_else(|_| { - let module = Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }; - (module, Vec::new()) - }); - attrs.append(&mut new_attrs); + let (items, inner_span) = result.map_err(|mut err| err.emit()).unwrap_or_default(); - // Extract the directory path for submodules of `module`. - let path = sess.source_map().span_to_unmapped_path(module.inner); + // Extract the directory path for submodules of the module. + let path = sess.source_map().span_to_unmapped_path(inner_span); let mut path = match path { FileName::Real(name) => name.into_local_path(), other => PathBuf::from(other.to_string()), }; path.pop(); - (module, Directory { ownership, path }) + (items, inner_span, Directory { ownership, path }) } fn error_on_circular_module<'a>( diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_expand/src/mut_visit/tests.rs index be0300bad98bd..7e7155ad27876 100644 --- a/compiler/rustc_expand/src/mut_visit/tests.rs +++ b/compiler/rustc_expand/src/mut_visit/tests.rs @@ -7,8 +7,8 @@ use rustc_span::symbol::Ident; use rustc_span::with_default_session_globals; // This version doesn't care about getting comments or doc-strings in. -fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) { - s.print_mod(&krate.module, &krate.attrs) +fn print_crate_items(krate: &ast::Crate) -> String { + krate.items.iter().map(|i| pprust::item_to_string(i)).collect::>().join(" ") } // Change every identifier to "zz". @@ -46,7 +46,7 @@ fn ident_transformation() { assert_pred!( matches_codepattern, "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &krate)), + print_crate_items(&krate), "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string() ); }) @@ -66,7 +66,7 @@ fn ident_transformation_in_defs() { assert_pred!( matches_codepattern, "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &krate)), + print_crate_items(&krate), "macro_rules! zz{(zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+))}".to_string() ); }) diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index f4fcaf5c0a452..56f25ffdb0187 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -309,8 +309,8 @@ fn out_of_line_mod() { .unwrap() .unwrap(); - if let ast::ItemKind::Mod(ref m) = item.kind { - assert!(m.items.len() == 2); + if let ast::ItemKind::Mod(_, ref mod_kind) = item.kind { + assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2)); } else { panic!(); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6ac1c570cfe1b..4df8c44e62b38 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use crate::def::{DefKind, Namespace, Res}; use crate::def_id::DefId; crate use crate::hir_id::HirId; @@ -615,7 +616,7 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Default, Encodable, Debug, HashStable_Generic)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate @@ -1280,7 +1281,7 @@ impl Body<'hir> { } /// The type of source expression that caused this generator to be created. -#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)] pub enum GeneratorKind { /// An explicit `async` block or the body of an async function. Async(AsyncGeneratorKind), @@ -1298,12 +1299,21 @@ impl fmt::Display for GeneratorKind { } } +impl GeneratorKind { + pub fn descr(&self) -> &'static str { + match self { + GeneratorKind::Async(ask) => ask.descr(), + GeneratorKind::Gen => "generator", + } + } +} + /// In the case of a generator created as part of an async construct, /// which kind of async construct caused it to be created? /// /// This helps error messages but is also used to drive coercions in /// type-checking (see #60424). -#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)] pub enum AsyncGeneratorKind { /// An explicit `async` block written by the user. Block, @@ -1325,6 +1335,16 @@ impl fmt::Display for AsyncGeneratorKind { } } +impl AsyncGeneratorKind { + pub fn descr(&self) -> &'static str { + match self { + AsyncGeneratorKind::Block => "`async` block", + AsyncGeneratorKind::Closure => "`async` closure body", + AsyncGeneratorKind::Fn => "`async fn` body", + } + } +} + #[derive(Copy, Clone, Debug)] pub enum BodyOwnerKind { /// Functions and methods. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 63f8a7293d899..9e55f7e558999 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1509,7 +1509,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - if let Some((kind, def_id)) = TyCategory::from_ty(t) { + if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); // Avoid cluttering the output when the "found" and error span overlap: // @@ -1582,11 +1582,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; if let Some((expected, found)) = expected_found { let expected_label = match exp_found { - Mismatch::Variable(ef) => ef.expected.prefix_string(), + Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx), Mismatch::Fixed(s) => s.into(), }; let found_label = match exp_found { - Mismatch::Variable(ef) => ef.found.prefix_string(), + Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx), Mismatch::Fixed(s) => s.into(), }; let exp_found = match exp_found { @@ -2489,7 +2489,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { pub enum TyCategory { Closure, Opaque, - Generator, + Generator(hir::GeneratorKind), Foreign, } @@ -2498,16 +2498,18 @@ impl TyCategory { match self { Self::Closure => "closure", Self::Opaque => "opaque type", - Self::Generator => "generator", + Self::Generator(gk) => gk.descr(), Self::Foreign => "foreign type", } } - pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> { + pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> { match *ty.kind() { ty::Closure(def_id, _) => Some((Self::Closure, def_id)), ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)), - ty::Generator(def_id, ..) => Some((Self::Generator, def_id)), + ty::Generator(def_id, ..) => { + Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id)) + } ty::Foreign(def_id) => Some((Self::Foreign, def_id)), _ => None, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index cb783847fd1cf..d533e267fd702 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -383,7 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { InferenceDiagnosticsData { name: s, span: None, - kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string() }, + kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) }, parent: None, } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 231edf442eb00..cc3bf4095fdef 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -188,13 +188,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_ident, ident); } - fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) { - run_early_pass!(self, check_mod, m, s, n); - self.check_id(n); - ast_visit::walk_mod(self, m); - run_early_pass!(self, check_mod_post, m, s, n); - } - fn visit_local(&mut self, l: &'a ast::Local) { self.with_lint_attrs(l.id, &l.attrs, |cx| { run_early_pass!(cx, check_local, l); diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 828f283d2a95a..ffbed3a0aff2d 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -160,8 +160,6 @@ macro_rules! early_lint_methods { fn check_ident(a: Ident); fn check_crate(a: &ast::Crate); fn check_crate_post(a: &ast::Crate); - fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId); - fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId); fn check_foreign_item(a: &ast::ForeignItem); fn check_foreign_item_post(a: &ast::ForeignItem); fn check_item(a: &ast::Item); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8eeee19cc298a..686d09dd7fcb4 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1814,14 +1814,12 @@ declare_lint! { } declare_lint! { - /// The `irrefutable_let_patterns` lint detects detects [irrefutable - /// patterns] in [`if let`] and [`while let`] statements. - /// - /// + /// The `irrefutable_let_patterns` lint detects [irrefutable patterns] + /// in [`if let`]s, [`while let`]s, and `if let` guards. /// /// ### Example /// - /// ```rust + /// ``` /// if let _ = 123 { /// println!("always runs!"); /// } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 7fe1e848d525a..bf315c81588a9 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -270,7 +270,7 @@ impl<'tcx> ty::TyS<'tcx> { } } ty::Closure(..) => "closure".into(), - ty::Generator(..) => "generator".into(), + ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), @@ -288,7 +288,7 @@ impl<'tcx> ty::TyS<'tcx> { } } - pub fn prefix_string(&self) -> Cow<'static, str> { + pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { match *self.kind() { ty::Infer(_) | ty::Error(_) @@ -314,7 +314,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), - ty::Generator(..) => "generator".into(), + ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e928f3c5d4d09..fdecbb9478808 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -366,14 +366,31 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option< } fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::MatchSource) { - tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| { - let msg = match source { - hir::MatchSource::IfLetDesugar { .. } => "irrefutable `if let` pattern", - hir::MatchSource::WhileLetDesugar => "irrefutable `while let` pattern", - hir::MatchSource::IfLetGuardDesugar => "irrefutable `if let` guard", - _ => bug!(), - }; - lint.build(msg).emit() + tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source { + hir::MatchSource::IfLetDesugar { .. } => { + let mut diag = lint.build("irrefutable `if let` pattern"); + diag.note("this pattern will always match, so the `if let` is useless"); + diag.help("consider replacing the `if let` with a `let`"); + diag.emit() + } + hir::MatchSource::WhileLetDesugar => { + let mut diag = lint.build("irrefutable `while let` pattern"); + diag.note("this pattern will always match, so the loop will never exit"); + diag.help("consider instead using a `loop { ... }` with a `let` inside it"); + diag.emit() + } + hir::MatchSource::IfLetGuardDesugar => { + let mut diag = lint.build("irrefutable `if let` guard pattern"); + diag.note("this pattern will always match, so the guard is useless"); + diag.help("consider removing the guard and adding a `let` inside the match arm"); + diag.emit() + } + _ => { + bug!( + "expected `if let`, `while let`, or `if let` guard HIR match source, found {:?}", + source, + ) + } }); } @@ -387,7 +404,7 @@ fn check_if_let_guard<'p, 'tcx>( report_arm_reachability(&cx, &report, hir::MatchSource::IfLetGuardDesugar); if report.non_exhaustiveness_witnesses.is_empty() { - // The match is exhaustive, i.e. the if let pattern is irrefutable. + // The match is exhaustive, i.e. the `if let` pattern is irrefutable. irrefutable_let_pattern(cx.tcx, pat.span, pat_id, hir::MatchSource::IfLetGuardDesugar) } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cdea82f50ede4..0f907859a19a6 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -25,11 +25,9 @@ use tracing::debug; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { - let lo = self.token.span; - let (module, attrs) = self.parse_mod(&token::Eof, Unsafe::No)?; - let span = lo.to(self.token.span); + let (attrs, items, span) = self.parse_mod(&token::Eof)?; let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. - Ok(ast::Crate { attrs, module, span, proc_macros }) + Ok(ast::Crate { attrs, items, span, proc_macros }) } /// Parses a `mod { ... }` or `mod ;` item. @@ -37,35 +35,26 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Mod)?; let id = self.parse_ident()?; - let (module, mut inner_attrs) = if self.eat(&token::Semi) { - (Mod { inner: Span::default(), unsafety, items: Vec::new(), inline: false }, Vec::new()) + let mod_kind = if self.eat(&token::Semi) { + ModKind::Unloaded } else { self.expect(&token::OpenDelim(token::Brace))?; - self.parse_mod(&token::CloseDelim(token::Brace), unsafety)? + let (mut inner_attrs, items, inner_span) = + self.parse_mod(&token::CloseDelim(token::Brace))?; + attrs.append(&mut inner_attrs); + ModKind::Loaded(items, Inline::Yes, inner_span) }; - attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module))) + Ok((id, ItemKind::Mod(unsafety, mod_kind))) } /// Parses the contents of a module (inner attributes followed by module items). pub fn parse_mod( &mut self, term: &TokenKind, - unsafety: Unsafe, - ) -> PResult<'a, (Mod, Vec)> { + ) -> PResult<'a, (Vec, Vec>, Span)> { let lo = self.token.span; let attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(term, lo, unsafety)?; - Ok((module, attrs)) - } - /// Given a termination token, parses all of the items in a module. - fn parse_mod_items( - &mut self, - term: &TokenKind, - inner_lo: Span, - unsafety: Unsafe, - ) -> PResult<'a, Mod> { let mut items = vec![]; while let Some(item) = self.parse_item(ForceCollect::No)? { items.push(item); @@ -82,9 +71,7 @@ impl<'a> Parser<'a> { } } - let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - - Ok(Mod { inner: inner_lo.to(hi), unsafety, items, inline: true }) + Ok((attrs, items, lo.to(self.prev_token.span))) } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 8d5a5bdf6b712..fac28281593c8 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -124,11 +124,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_item(self, i) } - fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: hir::HirId) { - self.record("Mod", Id::None, m); - hir_visit::walk_mod(self, m, n) - } - fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) { self.record("ForeignItem", Id::Node(i.hir_id()), i); hir_visit::walk_foreign_item(self, i) @@ -252,11 +247,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { - fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) { - self.record("Mod", Id::None, m); - ast_visit::walk_mod(self, m) - } - fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { self.record("ForeignItem", Id::None, i); ast_visit::walk_foreign_item(self, i) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index cca40a793dd00..701d48a982d36 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1023,7 +1023,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } - ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { + ItemKind::Mod(..) | ItemKind::ForeignMod(_) => { self.with_scope(item.id, |this| { visit::walk_item(this, item); }); @@ -1801,7 +1801,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { crate_lint: CrateLint, ) -> PartialRes { tracing::debug!( - "smart_resolve_path_fragment(id={:?},qself={:?},path={:?}", + "smart_resolve_path_fragment(id={:?}, qself={:?}, path={:?})", id, qself, path @@ -1841,11 +1841,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Before we start looking for candidates, we have to get our hands // on the type user is trying to perform invocation on; basically: - // we're transforming `HashMap::new` into just `HashMap` - let path = if let Some((_, path)) = path.split_last() { - path - } else { - return Some(parent_err); + // we're transforming `HashMap::new` into just `HashMap`. + let path = match path.split_last() { + Some((_, path)) if !path.is_empty() => path, + _ => return Some(parent_err), }; let (mut err, candidates) = diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index bca3c7b1b03d3..77fbbaa1532af 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -11,6 +11,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(bool_to_option)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(nll)] @@ -23,11 +24,12 @@ use Determinacy::*; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; +use rustc_ast::ptr::P; use rustc_ast::unwrap_or; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast::{Crate, CRATE_NODE_ID}; -use rustc_ast::{ItemKind, Path}; +use rustc_ast::{ItemKind, ModKind, Path}; use rustc_ast_lowering::ResolverAstLowering; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; @@ -59,6 +61,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; +use std::ops::ControlFlow; use std::{cmp, fmt, iter, ptr}; use tracing::debug; @@ -283,28 +286,21 @@ struct UsePlacementFinder { impl UsePlacementFinder { fn check(krate: &Crate, target_module: NodeId) -> (Option, bool) { let mut finder = UsePlacementFinder { target_module, span: None, found_use: false }; - visit::walk_crate(&mut finder, krate); + if let ControlFlow::Continue(..) = finder.check_mod(&krate.items, CRATE_NODE_ID) { + visit::walk_crate(&mut finder, krate); + } (finder.span, finder.found_use) } -} -impl<'tcx> Visitor<'tcx> for UsePlacementFinder { - fn visit_mod( - &mut self, - module: &'tcx ast::Mod, - _: Span, - _: &[ast::Attribute], - node_id: NodeId, - ) { + fn check_mod(&mut self, items: &[P], node_id: NodeId) -> ControlFlow<()> { if self.span.is_some() { - return; + return ControlFlow::Break(()); } if node_id != self.target_module { - visit::walk_mod(self, module); - return; + return ControlFlow::Continue(()); } // find a use statement - for item in &module.items { + for item in items { match item.kind { ItemKind::Use(..) => { // don't suggest placing a use before the prelude @@ -312,7 +308,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { if !item.span.from_expansion() { self.span = Some(item.span.shrink_to_lo()); self.found_use = true; - return; + return ControlFlow::Break(()); } } // don't place use before extern crate @@ -337,6 +333,18 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } } } + ControlFlow::Continue(()) + } +} + +impl<'tcx> Visitor<'tcx> for UsePlacementFinder { + fn visit_item(&mut self, item: &'tcx ast::Item) { + if let ItemKind::Mod(_, ModKind::Loaded(items, ..)) = &item.kind { + if let ControlFlow::Break(..) = self.check_mod(items, item.id) { + return; + } + } + visit::walk_item(self, item); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index e9aaa65256419..bfb5ebcea58b1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1368,8 +1368,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { Some(t) => Some(t), None => { let ty = parent_trait_ref.skip_binder().self_ty(); - let span = - TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); + let span = TyCategory::from_ty(self.tcx, ty) + .map(|(_, def_id)| self.tcx.def_span(def_id)); Some((ty.to_string(), span)) } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index fa09c26c800ae..32bf0ab7e8533 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2081,6 +2081,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => { self.tcx.sess.emit_err(YieldExprOutsideOfGenerator { span: expr.span }); + // Avoid expressions without types during writeback (#78653). + self.check_expr(value); self.tcx.mk_unit() } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 0134266fab56d..721e8ec54f05f 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "no {} named `{}` found for {} `{}` in the current scope", item_kind, item_name, - actual.prefix_string(), + actual.prefix_string(self.tcx), ty_str, ); if let Mode::MethodCall = mode { @@ -732,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|(_, path)| path) .collect::>() .join("\n"); - let actual_prefix = actual.prefix_string(); + let actual_prefix = actual.prefix_string(self.tcx); err.set_primary_message(&format!( "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" )); diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 2d1e4496aeef7..b735957666fc5 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -59,6 +59,26 @@ fn uint_xor() { assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); } +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn uint_min() { + let x = AtomicUsize::new(0xf731); + assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0x137f); + assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f); + assert_eq!(x.load(SeqCst), 0x137f); +} + +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn uint_max() { + let x = AtomicUsize::new(0x137f); + assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f); + assert_eq!(x.load(SeqCst), 0xf731); + assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731); +} + #[test] fn int_and() { let x = AtomicIsize::new(0xf731); @@ -87,6 +107,26 @@ fn int_xor() { assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); } +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn int_min() { + let x = AtomicIsize::new(0xf731); + assert_eq!(x.fetch_min(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0x137f); + assert_eq!(x.fetch_min(0xf731, SeqCst), 0x137f); + assert_eq!(x.load(SeqCst), 0x137f); +} + +#[test] +#[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins +fn int_max() { + let x = AtomicIsize::new(0x137f); + assert_eq!(x.fetch_max(0xf731, SeqCst), 0x137f); + assert_eq!(x.load(SeqCst), 0xf731); + assert_eq!(x.fetch_max(0x137f, SeqCst), 0xf731); + assert_eq!(x.load(SeqCst), 0xf731); +} + static S_FALSE: AtomicBool = AtomicBool::new(false); static S_TRUE: AtomicBool = AtomicBool::new(true); static S_INT: AtomicIsize = AtomicIsize::new(0); diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index a01ebb316e886..ab61618dc7d7b 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -219,6 +219,26 @@ impl Mutex { data: UnsafeCell::new(t), } } + + /// Immediately drops the guard, and consequently unlocks the mutex. + /// + /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. + /// Alternately, the guard will be automatically dropped when it goes out of scope. + /// + /// ``` + /// #![feature(mutex_unlock)] + /// + /// use std::sync::Mutex; + /// let mutex = Mutex::new(0); + /// + /// let mut guard = mutex.lock().unwrap(); + /// *guard += 20; + /// Mutex::unlock(guard); + /// ``` + #[unstable(feature = "mutex_unlock", issue = "81872")] + pub fn unlock(guard: MutexGuard<'_, T>) { + drop(guard); + } } impl Mutex { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index ae38030d49771..f9e65be9b0d40 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -353,12 +353,13 @@ where } let mut completed_test = res.unwrap(); - let running_test = running_tests.remove(&completed_test.desc).unwrap(); - if let Some(join_handle) = running_test.join_handle { - if let Err(_) = join_handle.join() { - if let TrOk = completed_test.result { - completed_test.result = - TrFailedMsg("panicked after reporting success".to_string()); + if let Some(running_test) = running_tests.remove(&completed_test.desc) { + if let Some(join_handle) = running_test.join_handle { + if let Err(_) = join_handle.join() { + if let TrOk = completed_test.result { + completed_test.result = + TrFailedMsg("panicked after reporting success".to_string()); + } } } } diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 80f7851debfbd..0302fbecb6ed0 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -422,3 +422,10 @@ $ rustdoc src/lib.rs --crate-version 1.3.37 When `rustdoc` receives this flag, it will print an extra "Version (version)" into the sidebar of the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation. + +## `@path`: load command-line flags from a path + +If you specify `@path` on the command-line, then it will open `path` and read +command line options from it. These options are one per line; a blank line indicates +an empty option. The file can use Unix or Windows style line endings, and must be +encoded as UTF-8. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 18bc275572ff0..d7978c4a0228d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -432,13 +432,16 @@ fn usage(argv0: &str) { (option.apply)(&mut options); } println!("{}", options.usage(&format!("{} [options] ", argv0))); + println!(" @path Read newline separated options from `path`\n"); println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html") } /// A result type used by several functions under `main()`. type MainResult = Result<(), ErrorReported>; -fn main_args(args: &[String]) -> MainResult { +fn main_args(at_args: &[String]) -> MainResult { + let args = rustc_driver::args::arg_expand_all(at_args); + let mut options = getopts::Options::new(); for option in opts() { (option.apply)(&mut options); diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.args b/src/test/rustdoc-ui/commandline-argfile-badutf8.args new file mode 100644 index 0000000000000..c070b0c2400d8 --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.args @@ -0,0 +1,2 @@ +--cfg +unbroken€ \ No newline at end of file diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.rs b/src/test/rustdoc-ui/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000000..e2984e3ca97ac --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.rs @@ -0,0 +1,12 @@ +// Check to see if we can get parameters from an @argsfile file +// +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr b/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000000..9af6fc0a518df --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.rs b/src/test/rustdoc-ui/commandline-argfile-missing.rs new file mode 100644 index 0000000000000..020c3ff3c7e63 --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile-missing.rs @@ -0,0 +1,15 @@ +// Check to see if we can get parameters from an @argsfile file +// +// ignore-tidy-linelength +// normalize-stderr-test: "os error \d+" -> "os error $$ERR" +// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/rustdoc-ui/commandline-argfile-missing.stderr b/src/test/rustdoc-ui/commandline-argfile-missing.stderr new file mode 100644 index 0000000000000..179ad83100419 --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/src/test/rustdoc-ui/commandline-argfile.args b/src/test/rustdoc-ui/commandline-argfile.args new file mode 100644 index 0000000000000..972938bf6c8dd --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile.args @@ -0,0 +1,2 @@ +--cfg +unbroken \ No newline at end of file diff --git a/src/test/rustdoc-ui/commandline-argfile.rs b/src/test/rustdoc-ui/commandline-argfile.rs new file mode 100644 index 0000000000000..cc8c8722c1c35 --- /dev/null +++ b/src/test/rustdoc-ui/commandline-argfile.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// check-pass +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index 02342af8dc53e..0307875c154b8 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 235f39c567b8e..d26530efe3ecd 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/async-await/generator-desc.rs b/src/test/ui/async-await/generator-desc.rs new file mode 100644 index 0000000000000..5008120166711 --- /dev/null +++ b/src/test/ui/async-await/generator-desc.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +async fn one() {} +async fn two() {} + +fn fun>(f1: F, f2: F) {} +fn main() { + fun(async {}, async {}); + //~^ ERROR mismatched types + fun(one(), two()); + //~^ ERROR mismatched types + fun((async || {})(), (async || {})()); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr new file mode 100644 index 0000000000000..b85926c7a03c0 --- /dev/null +++ b/src/test/ui/async-await/generator-desc.stderr @@ -0,0 +1,49 @@ +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:10:25 + | +LL | fun(async {}, async {}); + | -- ^^ expected `async` block, found a different `async` block + | | + | the expected `async` block + | + = note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]` + found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]` + +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:12:16 + | +LL | async fn one() {} + | - the `Output` of this `async fn`'s expected opaque type +LL | async fn two() {} + | - the `Output` of this `async fn`'s found opaque type +... +LL | fun(one(), two()); + | ^^^^^ expected opaque type, found a different opaque type + | + = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) + found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) + = help: consider `await`ing on both `Future`s + = note: distinct uses of `impl Trait` result in different opaque types + +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:14:26 + | +LL | fun((async || {})(), (async || {})()); + | -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body + | | + | the expected `async` closure body + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- + | | + | the expected opaque type + | the found opaque type + | + = note: expected opaque type `impl Future` (`async` closure body) + found opaque type `impl Future` (`async` closure body) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr index 5c7a56c7ceda4..8586dfd91863c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -17,6 +17,8 @@ LL | | } | |_________^ | = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` error[E0382]: use of moved value: `c` --> $DIR/closure-origin-single-variant-diagnostics.rs:25:13 diff --git a/src/test/ui/expr/if/if-let.stderr b/src/test/ui/expr/if/if-let.stderr index 468e913a773c0..c64c9093ee54a 100644 --- a/src/test/ui/expr/if/if-let.stderr +++ b/src/test/ui/expr/if/if-let.stderr @@ -10,6 +10,8 @@ LL | | }); | |_______- in this macro invocation | = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `if let` pattern @@ -23,6 +25,8 @@ LL | | println!("irrefutable pattern"); LL | | }); | |_______- in this macro invocation | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `if let` pattern @@ -32,6 +36,9 @@ LL | / if let a = 1 { LL | | println!("irrefutable pattern"); LL | | } | |_____^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` warning: irrefutable `if let` pattern --> $DIR/if-let.rs:30:5 @@ -44,6 +51,9 @@ LL | | } else { LL | | println!("else in irrefutable `if let`"); LL | | } | |_____^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` warning: irrefutable `if let` pattern --> $DIR/if-let.rs:40:12 @@ -53,6 +63,9 @@ LL | } else if let a = 1 { LL | | println!("irrefutable pattern"); LL | | } | |_____^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` warning: irrefutable `if let` pattern --> $DIR/if-let.rs:46:12 @@ -62,6 +75,9 @@ LL | } else if let a = 1 { LL | | println!("irrefutable pattern"); LL | | } | |_____^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` warning: 6 warnings emitted diff --git a/src/test/ui/generator/yield-outside-generator-issue-78653.rs b/src/test/ui/generator/yield-outside-generator-issue-78653.rs new file mode 100644 index 0000000000000..4e8050c81b0d3 --- /dev/null +++ b/src/test/ui/generator/yield-outside-generator-issue-78653.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +fn main() { + yield || for i in 0 { } + //~^ ERROR yield expression outside of generator literal + //~| ERROR `{integer}` is not an iterator +} diff --git a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr new file mode 100644 index 0000000000000..f0c7cb0e5d50c --- /dev/null +++ b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr @@ -0,0 +1,21 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/yield-outside-generator-issue-78653.rs:4:5 + | +LL | yield || for i in 0 { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `{integer}` is not an iterator + --> $DIR/yield-outside-generator-issue-78653.rs:4:23 + | +LL | yield || for i in 0 { } + | ^ `{integer}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{integer}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` + = note: required by `into_iter` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0627. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr index 4134d6aa54468..56befe3a0a75d 100644 --- a/src/test/ui/issues/issue-49040.stderr +++ b/src/test/ui/issues/issue-49040.stderr @@ -7,10 +7,8 @@ LL | #![allow(unused_variables)]; error[E0601]: `main` function not found in crate `issue_49040` --> $DIR/issue-49040.rs:1:1 | -LL | / #![allow(unused_variables)]; -LL | | -LL | | fn foo() {} - | |__^ consider adding a `main` function to `$DIR/issue-49040.rs` +LL | #![allow(unused_variables)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs` error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs index c1cfa4695c9ee..7549eae7016b5 100644 --- a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs +++ b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs @@ -1,3 +1,6 @@ +#![feature(if_let_guard)] +#![allow(incomplete_features)] + #![deny(irrefutable_let_patterns)] fn main() { @@ -6,4 +9,9 @@ fn main() { while let _ = 5 { //~ ERROR irrefutable `while let` pattern break; } + + match 5 { + _ if let _ = 2 => {} //~ ERROR irrefutable `if let` guard pattern + _ => {} + } } diff --git a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr index 1de30f7db0698..d6926ee12eeaa 100644 --- a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr +++ b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr @@ -1,22 +1,36 @@ error: irrefutable `if let` pattern - --> $DIR/deny-irrefutable-let-patterns.rs:4:5 + --> $DIR/deny-irrefutable-let-patterns.rs:7:5 | LL | if let _ = 5 {} | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deny-irrefutable-let-patterns.rs:1:9 + --> $DIR/deny-irrefutable-let-patterns.rs:4:9 | LL | #![deny(irrefutable_let_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` error: irrefutable `while let` pattern - --> $DIR/deny-irrefutable-let-patterns.rs:6:5 + --> $DIR/deny-irrefutable-let-patterns.rs:9:5 | LL | / while let _ = 5 { LL | | break; LL | | } | |_____^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +error: irrefutable `if let` guard pattern + --> $DIR/deny-irrefutable-let-patterns.rs:14:18 + | +LL | _ if let _ = 2 => {} + | ^ + | + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-82156.rs b/src/test/ui/resolve/issue-82156.rs new file mode 100644 index 0000000000000..6215259e48657 --- /dev/null +++ b/src/test/ui/resolve/issue-82156.rs @@ -0,0 +1,3 @@ +fn main() { + super(); //~ ERROR failed to resolve: there are too many leading `super` keywords +} diff --git a/src/test/ui/resolve/issue-82156.stderr b/src/test/ui/resolve/issue-82156.stderr new file mode 100644 index 0000000000000..d53599dcce61b --- /dev/null +++ b/src/test/ui/resolve/issue-82156.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/issue-82156.rs:2:5 + | +LL | super(); + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/rfc-2294-if-let-guard/warns.stderr b/src/test/ui/rfc-2294-if-let-guard/warns.stderr index 33fa25d32fb1b..c7627f1c3c50c 100644 --- a/src/test/ui/rfc-2294-if-let-guard/warns.stderr +++ b/src/test/ui/rfc-2294-if-let-guard/warns.stderr @@ -1,4 +1,4 @@ -error: irrefutable `if let` guard +error: irrefutable `if let` guard pattern --> $DIR/warns.rs:7:24 | LL | Some(x) if let () = x => {} @@ -9,6 +9,8 @@ note: the lint level is defined here | LL | #[deny(irrefutable_let_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm error: unreachable pattern --> $DIR/warns.rs:16:25 diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr index 6538b9fbe6f28..04e77bf9470a2 100644 --- a/src/test/ui/while-let.stderr +++ b/src/test/ui/while-let.stderr @@ -10,6 +10,8 @@ LL | | }); | |_______- in this macro invocation | = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern @@ -23,6 +25,8 @@ LL | | println!("irrefutable pattern"); LL | | }); | |_______- in this macro invocation | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern @@ -33,6 +37,9 @@ LL | | println!("irrefutable pattern"); LL | | break; LL | | } | |_____^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it warning: 3 warnings emitted diff --git a/src/tools/cargo b/src/tools/cargo index ab64d1393b5b7..bf5a5d5e5d3ae 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ab64d1393b5b77c66b6534ef5023a1b89ee7bf64 +Subproject commit bf5a5d5e5d3ae842a63bfce6d070dfd438cf6070 diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs index 642326469725f..9ff7ef7cc3b55 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs @@ -241,9 +241,12 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) } - (Mod(l), Mod(r)) => { - l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind)) - } + (Mod(lu, lmk), Mod(ru, rmk)) => lu == ru && match (lmk, rmk) { + (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => + linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)), + (ModKind::Unloaded, ModKind::Unloaded) => true, + _ => false, + }, (ForeignMod(l), ForeignMod(r)) => { both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r)) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))