Auto merge of #82281 - Dylan-DPC:rollup-raob2tu, r=Dylan-DPC

Rollup of 10 pull requests

Successful merges:

 - #79747 (Add explanations and suggestions to `irrefutable_let_patterns` lint)
 - #81496 (name async generators something more human friendly in type error diagnostic)
 - #81873 (Add Mutex::unlock)
 - #82093 (Add tests for Atomic*::fetch_{min,max})
 - #82238 (ast: Keep expansion status for out-of-line module items)
 - #82245 (Do not ICE when evaluating locals' types of invalid `yield`)
 - #82259 (Fix popping singleton paths in when generating E0433)
 - #82261 (rustdoc: Support argument files)
 - #82274 (libtest: Fix unwrap panic on duplicate TestDesc)
 - #82275 (Update cargo)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-02-19 08:24:01 +00:00
commit 8599bff5a3
63 changed files with 607 additions and 333 deletions

View File

@ -285,7 +285,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
[[package]]
name = "cargo"
version = "0.52.0"
version = "0.53.0"
dependencies = [
"anyhow",
"atty",

View File

@ -486,8 +486,8 @@ pub struct WhereEqPredicate {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate {
pub module: Mod,
pub attrs: Vec<Attribute>,
pub items: Vec<P<Item>>,
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<P<Item>>,
/// `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<P<Item>>, 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" {}`.

View File

@ -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<T: MutVisitor>(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<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
vis.visit_asyncness(asyncness);
}
pub fn noop_visit_mod<T: MutVisitor>(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<T: MutVisitor>(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<T: MutVisitor>(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 {

View File

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

View File

@ -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<Item>], 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);

View File

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

View File

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

View File

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

View File

@ -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<Comments<'a>>,
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) => {

View File

@ -91,7 +91,7 @@ pub fn inject(
}
let decls = mk_decls(&mut krate, &mut cx, &macros);
krate.module.items.push(decls);
krate.items.push(decls);
krate
}

View File

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

View File

@ -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<ast::Item>) -> SmallVec<[P<ast::Item>; 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)]
}

View File

@ -3,7 +3,7 @@ use std::fmt;
use std::fs;
use std::io;
pub fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
fn arg_expand(arg: String) -> Result<Vec<String>, 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<Vec<String>, Error> {
}
}
pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
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<String>),

View File

@ -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<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + 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,

View File

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

View File

@ -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);
*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();
}
return Default::default();
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);
}
};
dir
*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();
}
};
dir
}
};
// Set the module info before we flat map.

View File

@ -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<Attribute>,
pop_mod_stack: &mut bool,
) -> (Mod, Directory) {
) -> (Vec<P<Item>>, 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>(

View File

@ -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::<Vec<_>>().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()
);
})

View File

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

View File

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

View File

@ -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<Self::BreakTy> {
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,
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 <foo> { ... }` or `mod <foo>;` 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<Attribute>)> {
) -> PResult<'a, (Vec<Attribute>, Vec<P<Item>>, 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)))
}
}

View File

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

View File

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

View File

@ -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<Span>, 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<ast::Item>], 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);
}
}

View File

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

View File

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

View File

@ -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::<Vec<_>>()
.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"
));

View File

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

View File

@ -219,6 +219,26 @@ impl<T> Mutex<T> {
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<T: ?Sized> Mutex<T> {

View File

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

View File

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

View File

@ -432,13 +432,16 @@ fn usage(argv0: &str) {
(option.apply)(&mut options);
}
println!("{}", options.usage(&format!("{} [options] <input>", 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);

View File

@ -0,0 +1,2 @@
--cfg
unbroken€

View File

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

View File

@ -0,0 +1,2 @@
error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args

View File

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

View File

@ -0,0 +1,2 @@
error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)

View File

@ -0,0 +1,2 @@
--cfg
unbroken

View File

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

View File

@ -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":[]}

View File

@ -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":[]}

View File

@ -0,0 +1,16 @@
// edition:2018
#![feature(async_closure)]
use std::future::Future;
async fn one() {}
async fn two() {}
fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
fn main() {
fun(async {}, async {});
//~^ ERROR mismatched types
fun(one(), two());
//~^ ERROR mismatched types
fun((async || {})(), (async || {})());
//~^ ERROR mismatched types
}

View File

@ -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<T>(gen: T) -> impl Future<Output = T::Return>
| -------------------------------
| |
| 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`.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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: aborting due to 2 previous errors
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 3 previous errors

View File

@ -0,0 +1,3 @@
fn main() {
super(); //~ ERROR failed to resolve: there are too many leading `super` keywords
}

View File

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

View File

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

View File

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

@ -1 +1 @@
Subproject commit ab64d1393b5b77c66b6534ef5023a1b89ee7bf64
Subproject commit bf5a5d5e5d3ae842a63bfce6d070dfd438cf6070

View File

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