Auto merge of #2715 - RalfJung:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2022-12-05 12:55:36 +00:00
commit 552b63c161
261 changed files with 3312 additions and 2594 deletions

View File

@ -309,7 +309,7 @@ jobs:
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
os: macos-latest
os: macos-12-xl
- name: dist-apple-various
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
@ -320,7 +320,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: dist-x86_64-apple-alt
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths"
@ -331,7 +331,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: x86_64-apple-1
env:
SCRIPT: "./x.py --stage 2 test --exclude src/test/ui --exclude src/test/rustdoc --exclude src/test/run-make-fulldeps"
@ -342,7 +342,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: x86_64-apple-2
env:
SCRIPT: "./x.py --stage 2 test src/test/ui src/test/rustdoc src/test/run-make-fulldeps"
@ -353,7 +353,7 @@ jobs:
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
os: macos-latest
os: macos-12-xl
- name: dist-aarch64-apple
env:
SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
@ -368,7 +368,7 @@ jobs:
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
JEMALLOC_SYS_WITH_LG_PAGE: 14
os: macos-latest
os: macos-12-xl
- name: x86_64-msvc-1
env:
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"

View File

@ -92,6 +92,15 @@ version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
[[package]]
name = "ar_archive_writer"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "276881980556fdadeb88aa1ffc667e4d2e8fe72531dfabcb7a82bb3c9ea9ba31"
dependencies = [
"object",
]
[[package]]
name = "array_tool"
version = "1.0.3"
@ -906,9 +915,9 @@ version = "0.0.0"
[[package]]
name = "cpufeatures"
version = "0.2.1"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
"libc",
]
@ -1085,12 +1094,6 @@ version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
[[package]]
name = "digest"
version = "0.10.2"
@ -1162,6 +1165,12 @@ dependencies = [
"syn",
]
[[package]]
name = "dissimilar"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
[[package]]
name = "dlmalloc"
version = "0.2.3"
@ -1283,11 +1292,11 @@ dependencies = [
[[package]]
name = "expect-test"
version = "1.0.1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceb96f3eaa0d4e8769c52dacfd4eb60183b817ed2f176171b3c691d5022b0f2e"
checksum = "1d4661aca38d826eb7c72fe128e4238220616de4c0cc00db7bfc38e2e1364dd3"
dependencies = [
"difference",
"dissimilar",
"once_cell",
]
@ -3495,6 +3504,7 @@ dependencies = [
name = "rustc_codegen_ssa"
version = "0.0.0"
dependencies = [
"ar_archive_writer",
"bitflags",
"cc",
"itertools",

View File

@ -0,0 +1,15 @@
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.

View File

@ -354,7 +354,7 @@ pub trait LayoutCalculator {
if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
};
let mut st = self.univariant(dl, &variants[v], &repr, kind)?;
let mut st = self.univariant(dl, &variants[v], repr, kind)?;
st.variants = Variants::Single { index: v };
if is_unsafe_cell {
@ -457,7 +457,7 @@ pub trait LayoutCalculator {
let mut variant_layouts = variants
.iter_enumerated()
.map(|(j, v)| {
let mut st = self.univariant(dl, v, &repr, StructKind::AlwaysSized)?;
let mut st = self.univariant(dl, v, repr, StructKind::AlwaysSized)?;
st.variants = Variants::Single { index: j };
align = align.max(st.align);
@ -647,8 +647,8 @@ pub trait LayoutCalculator {
.map(|(i, field_layouts)| {
let mut st = self.univariant(
dl,
&field_layouts,
&repr,
field_layouts,
repr,
StructKind::Prefixed(min_ity.size(), prefix_align),
)?;
st.variants = Variants::Single { index: i };
@ -755,7 +755,7 @@ pub trait LayoutCalculator {
// Try to use a ScalarPair for all tagged enums.
let mut common_prim = None;
let mut common_prim_initialized_in_all_variants = true;
for (field_layouts, layout_variant) in iter::zip(&*variants, &layout_variants) {
for (field_layouts, layout_variant) in iter::zip(variants, &layout_variants) {
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
panic!();
};

View File

@ -1179,7 +1179,7 @@ impl Expr {
pub fn peel_parens(&self) -> &Expr {
let mut expr = self;
while let ExprKind::Paren(inner) = &expr.kind {
expr = &inner;
expr = inner;
}
expr
}
@ -1312,8 +1312,10 @@ pub struct Closure {
pub movability: Movability,
pub fn_decl: P<FnDecl>,
pub body: P<Expr>,
/// The span of the argument block `|...|`.
/// The span of the declaration block: 'move |...| -> ...'
pub fn_decl_span: Span,
/// The span of the argument block `|...|`
pub fn_arg_span: Span,
}
/// Limit types of a range (inclusive or exclusive)
@ -2027,7 +2029,7 @@ impl Ty {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = &ty;
final_ty = ty;
}
final_ty
}

View File

@ -736,8 +736,7 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
return; // Avoid visiting the span for the second time.
}
token::Interpolated(nt) => {
let mut nt = Lrc::make_mut(nt);
visit_nonterminal(&mut nt, vis);
visit_nonterminal(Lrc::make_mut(nt), vis);
}
_ => {}
}
@ -1368,6 +1367,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
fn_decl,
body,
fn_decl_span,
fn_arg_span: _,
}) => {
vis.visit_closure_binder(binder);
vis.visit_asyncness(asyncness);

View File

@ -64,7 +64,7 @@ impl TokenTree {
match (self, other) {
(TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
(TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
delim == delim2 && tts.eq_unspanned(&tts2)
delim == delim2 && tts.eq_unspanned(tts2)
}
_ => false,
}
@ -402,7 +402,7 @@ impl TokenStream {
let mut t1 = self.trees();
let mut t2 = other.trees();
for (t1, t2) in iter::zip(&mut t1, &mut t2) {
if !t1.eq_unspanned(&t2) {
if !t1.eq_unspanned(t2) {
return false;
}
}
@ -475,7 +475,7 @@ impl TokenStream {
token::Interpolated(nt) => TokenTree::Delimited(
DelimSpan::from_single(token.span),
Delimiter::Invisible,
TokenStream::from_nonterminal_ast(&nt).flattened(),
TokenStream::from_nonterminal_ast(nt).flattened(),
),
_ => TokenTree::Token(token.clone(), spacing),
}
@ -511,7 +511,7 @@ impl TokenStream {
fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last()
&& let TokenTree::Token(tok, spacing) = tt
&& let Some(glued_tok) = last_tok.glue(&tok)
&& let Some(glued_tok) = last_tok.glue(tok)
{
// ...then overwrite the last token tree in `vec` with the
// glued token, and skip the first token tree from `stream`.

View File

@ -21,6 +21,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
| ast::ExprKind::Loop(..)
| ast::ExprKind::ForLoop(..)
| ast::ExprKind::TryBlock(..)
| ast::ExprKind::ConstBlock(..)
)
}

View File

@ -110,7 +110,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
} else {
&mut lines
};
if let Some(horizontal) = get_horizontal_trim(&lines, kind) {
if let Some(horizontal) = get_horizontal_trim(lines, kind) {
changes = true;
// remove a "[ \t]*\*" block from each line, if possible
for line in lines.iter_mut() {
@ -147,7 +147,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<usize> {
fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str {
let len = s.len();
match all_whitespace(&s, col) {
match all_whitespace(s, col) {
Some(col) => {
if col < len {
&s[col..]

View File

@ -52,14 +52,14 @@ impl LitKind {
// new symbol because the string in the LitKind is different to the
// string in the token.
let s = symbol.as_str();
let symbol = if s.contains(&['\\', '\r']) {
let symbol = if s.contains(['\\', '\r']) {
let mut buf = String::with_capacity(s.len());
let mut error = Ok(());
// Force-inlining here is aggressive but the closure is
// called on every char in the string, so it can be
// hot in programs with many long strings.
unescape_literal(
&s,
s,
Mode::Str,
&mut #[inline(always)]
|_, unescaped_char| match unescaped_char {
@ -85,7 +85,7 @@ impl LitKind {
if s.contains('\r') {
let mut buf = String::with_capacity(s.len());
let mut error = Ok(());
unescape_literal(&s, Mode::RawStr, &mut |_, unescaped_char| {
unescape_literal(s, Mode::RawStr, &mut |_, unescaped_char| {
match unescaped_char {
Ok(c) => buf.push(c),
Err(err) => {
@ -106,7 +106,7 @@ impl LitKind {
let s = symbol.as_str();
let mut buf = Vec::with_capacity(s.len());
let mut error = Ok(());
unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c {
unescape_literal(s, Mode::ByteStr, &mut |_, c| match c {
Ok(c) => buf.push(byte_from_char(c)),
Err(err) => {
if err.is_fatal() {
@ -122,7 +122,7 @@ impl LitKind {
let bytes = if s.contains('\r') {
let mut buf = Vec::with_capacity(s.len());
let mut error = Ok(());
unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c {
unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c {
Ok(c) => buf.push(byte_from_char(c)),
Err(err) => {
if err.is_fatal() {

View File

@ -384,7 +384,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
| ast::ExprKind::AssignOp(_, lhs, rhs)
| ast::ExprKind::Binary(_, lhs, rhs) => {
// X { y: 1 } + X { y: 2 }
contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs)
}
ast::ExprKind::Await(x)
| ast::ExprKind::Unary(_, x)
@ -393,12 +393,12 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
| ast::ExprKind::Field(x, _)
| ast::ExprKind::Index(x, _) => {
// &X { y: 1 }, X { y: 1 }.y
contains_exterior_struct_lit(&x)
contains_exterior_struct_lit(x)
}
ast::ExprKind::MethodCall(box ast::MethodCall { receiver, .. }) => {
// X { y: 1 }.bar(...)
contains_exterior_struct_lit(&receiver)
contains_exterior_struct_lit(receiver)
}
_ => false,

View File

@ -17,7 +17,7 @@ pub fn contains_text_flow_control_chars(s: &str) -> bool {
// U+2069 - E2 81 A9
let mut bytes = s.as_bytes();
loop {
match core::slice::memchr::memchr(0xE2, &bytes) {
match core::slice::memchr::memchr(0xE2, bytes) {
Some(idx) => {
// bytes are valid UTF-8 -> E2 must be followed by two bytes
let ch = &bytes[idx..idx + 3];

View File

@ -840,6 +840,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
fn_decl,
body,
fn_decl_span: _,
fn_arg_span: _,
}) => {
visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id)
}

View File

@ -222,7 +222,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Wrap the expression in an AnonConst.
let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id();
self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
self.create_def(
parent_def_id.def_id,
node_id,
DefPathData::AnonConst,
*op_sp,
);
let anon_const = AnonConst { id: node_id, value: P(expr) };
hir::InlineAsmOperand::SymFn {
anon_const: self.lower_anon_const(&anon_const),

View File

@ -176,6 +176,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body,
fn_decl_span,
fn_arg_span,
}) => {
if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure(
@ -186,6 +187,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
)
} else {
self.lower_expr_closure(
@ -196,6 +198,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
)
}
}
@ -365,7 +368,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id();
// Add a definition for the in-band const def.
self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst, f.span);
let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@ -642,6 +645,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body,
fn_decl_span: self.lower_span(span),
fn_arg_span: None,
movability: Some(hir::Movability::Static),
});
@ -898,6 +902,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
decl: &FnDecl,
body: &Expr,
fn_decl_span: Span,
fn_arg_span: Span,
) -> hir::ExprKind<'hir> {
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
@ -928,6 +933,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body: body_id,
fn_decl_span: self.lower_span(fn_decl_span),
fn_arg_span: Some(self.lower_span(fn_arg_span)),
movability: generator_option,
});
@ -984,6 +990,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
decl: &FnDecl,
body: &Expr,
fn_decl_span: Span,
fn_arg_span: Span,
) -> hir::ExprKind<'hir> {
if let &ClosureBinder::For { span, .. } = binder {
self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
@ -1038,6 +1045,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl,
body,
fn_decl_span: self.lower_span(fn_decl_span),
fn_arg_span: Some(self.lower_span(fn_arg_span)),
movability: None,
});
hir::ExprKind::Closure(c)

View File

@ -487,6 +487,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
parent: LocalDefId,
node_id: ast::NodeId,
data: DefPathData,
span: Span,
) -> LocalDefId {
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
assert!(
@ -497,7 +498,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.tcx.hir().def_key(self.local_def_id(node_id)),
);
let def_id = self.tcx.create_def(parent, data).def_id();
let def_id = self.tcx.at(span).create_def(parent, data).def_id();
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.resolver.node_id_to_def_id.insert(node_id, def_id);
@ -823,6 +824,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.current_hir_id_owner.def_id,
param,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
ident.span,
);
debug!(?_def_id);
@ -1151,15 +1153,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id();
let span = self.lower_span(ty.span);
// Add a definition for the in-band const def.
let def_id = self.create_def(
parent_def_id.def_id,
node_id,
DefPathData::AnonConst,
span,
);
let span = self.lower_span(ty.span);
let path_expr = Expr {
id: ty.id,
kind: ExprKind::Path(qself.clone(), path.clone()),
@ -1353,12 +1356,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx,
),
ImplTraitContext::Universal => {
let span = t.span;
self.create_def(
self.current_hir_id_owner.def_id,
*def_node_id,
DefPathData::ImplTrait,
span,
);
let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
@ -1455,6 +1459,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.current_hir_id_owner.def_id,
opaque_ty_node_id,
DefPathData::ImplTrait,
opaque_ty_span,
);
debug!(?opaque_ty_def_id);
@ -1608,6 +1613,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
parent_def_id,
node_id,
DefPathData::LifetimeNs(lifetime.ident.name),
lifetime.ident.span,
);
remapping.insert(old_def_id, new_def_id);
@ -1624,6 +1630,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
parent_def_id,
node_id,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
lifetime.ident.span,
);
remapping.insert(old_def_id, new_def_id);
@ -1806,7 +1813,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let fn_def_id = self.local_def_id(fn_node_id);
let opaque_ty_def_id =
self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait);
self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait, opaque_ty_span);
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
@ -1866,6 +1873,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
opaque_ty_def_id,
inner_node_id,
DefPathData::LifetimeNs(ident.name),
ident.span,
);
new_remapping.insert(outer_def_id, inner_def_id);

View File

@ -519,7 +519,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
ast::MetaItemKind::List(items) => {
self.print_path(&item.path, false, 0);
self.popen();
self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i));
self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i));
self.pclose();
}
}
@ -536,7 +536,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) {
match tt {
TokenTree::Token(token, _) => {
let token_str = self.token_to_string_ext(&token, convert_dollar_crate);
let token_str = self.token_to_string_ext(token, convert_dollar_crate);
self.word(token_str);
if let token::DocComment(..) = token.kind {
self.hardbreak()
@ -998,7 +998,7 @@ impl<'a> State<'a> {
ast::AssocConstraintKind::Bound { bounds } => {
if !bounds.is_empty() {
self.word_nbsp(":");
self.print_type_bounds(&bounds);
self.print_type_bounds(bounds);
}
}
}
@ -1035,7 +1035,7 @@ impl<'a> State<'a> {
}
ast::TyKind::Tup(elts) => {
self.popen();
self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty));
self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty));
if elts.len() == 1 {
self.word(",");
}
@ -1254,7 +1254,7 @@ impl<'a> State<'a> {
self.popen();
self.commasep(Consistent, &args, |s, arg| match arg {
AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
AsmArg::Template(template) => s.print_string(template, ast::StrStyle::Cooked),
AsmArg::Operand(op) => {
let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r {
InlineAsmRegOrRegClass::Reg(r) => s.print_symbol(*r, ast::StrStyle::Cooked),
@ -1424,11 +1424,11 @@ impl<'a> State<'a> {
self.print_path(path, true, 0);
}
self.popen();
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
self.pclose();
}
PatKind::Or(pats) => {
self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p));
self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p));
}
PatKind::Path(None, path) => {
self.print_path(path, true, 0);
@ -1450,7 +1450,7 @@ impl<'a> State<'a> {
}
self.commasep_cmnt(
Consistent,
&fields,
fields,
|s, f| {
s.cbox(INDENT_UNIT);
if !f.is_shorthand {
@ -1475,7 +1475,7 @@ impl<'a> State<'a> {
}
PatKind::Tuple(elts) => {
self.popen();
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
if elts.len() == 1 {
self.word(",");
}
@ -1498,7 +1498,7 @@ impl<'a> State<'a> {
self.print_pat(inner);
}
}
PatKind::Lit(e) => self.print_expr(&**e),
PatKind::Lit(e) => self.print_expr(e),
PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => {
if let Some(e) = begin {
self.print_expr(e);
@ -1514,7 +1514,7 @@ impl<'a> State<'a> {
}
PatKind::Slice(elts) => {
self.word("[");
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
self.word("]");
}
PatKind::Rest => self.word(".."),
@ -1600,7 +1600,7 @@ impl<'a> State<'a> {
self.word("<");
self.commasep(Inconsistent, &generic_params, |s, param| {
self.commasep(Inconsistent, generic_params, |s, param| {
s.print_outer_attributes_inline(&param.attrs);
match &param.kind {

View File

@ -305,10 +305,10 @@ impl<'a> State<'a> {
self.print_expr_tup(exprs);
}
ast::ExprKind::Call(func, args) => {
self.print_expr_call(func, &args);
self.print_expr_call(func, args);
}
ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
self.print_expr_method_call(seg, &receiver, &args);
self.print_expr_method_call(seg, receiver, args);
}
ast::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(*op, lhs, rhs);
@ -402,6 +402,7 @@ impl<'a> State<'a> {
fn_decl,
body,
fn_decl_span: _,
fn_arg_span: _,
}) => {
self.print_closure_binder(binder);
self.print_movability(*movability);
@ -605,7 +606,7 @@ impl<'a> State<'a> {
match binder {
ast::ClosureBinder::NotPresent => {}
ast::ClosureBinder::For { generic_params, .. } => {
self.print_formal_generic_params(&generic_params)
self.print_formal_generic_params(generic_params)
}
}
}

View File

@ -73,7 +73,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
// Replace all remaining regions with fresh inference variables.
renumber::renumber_mir(infcx, body, promoted);
dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
dump_mir(infcx.tcx, false, "renumber", &0, body, |_, _| Ok(()));
universal_regions
}
@ -331,7 +331,7 @@ pub(super) fn dump_mir_results<'tcx>(
return;
}
dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
dump_mir(infcx.tcx, false, "nll", &0, body, |pass_where, out| {
match pass_where {
// Before the CFG, dump out the values for each region variable.
PassWhere::BeforeCFG => {
@ -358,15 +358,13 @@ pub(super) fn dump_mir_results<'tcx>(
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
let mut file =
create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
let mut file = create_dump_file(infcx.tcx, "regioncx.all.dot", false, "nll", &0, body)?;
regioncx.dump_graphviz_raw_constraints(&mut file)?;
};
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
let mut file =
create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
let mut file = create_dump_file(infcx.tcx, "regioncx.scc.dot", false, "nll", &0, body)?;
regioncx.dump_graphviz_scc_constraints(&mut file)?;
};
}

View File

@ -19,11 +19,6 @@ version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
[[package]]
name = "ar"
version = "0.8.0"
source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648"
[[package]]
name = "arrayvec"
version = "0.7.2"
@ -324,7 +319,6 @@ dependencies = [
name = "rustc_codegen_cranelift"
version = "0.1.0"
dependencies = [
"ar",
"cranelift-codegen",
"cranelift-frontend",
"cranelift-jit",

View File

@ -18,7 +18,6 @@ target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.9.1"
libloading = { version = "0.7.3", optional = true }
once_cell = "1.10.0"

View File

@ -1,35 +1,15 @@
//! Creation of ar archives like for the lib and staticlib crate type
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{self, Read, Seek};
use std::path::{Path, PathBuf};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use rustc_codegen_ssa::back::archive::{
get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
};
use rustc_session::Session;
use object::read::archive::ArchiveFile;
use object::{Object, ObjectSymbol, ReadCache};
#[derive(Debug)]
enum ArchiveEntry {
FromArchive { archive_index: usize, file_range: (u64, u64) },
File(PathBuf),
}
pub(crate) struct ArArchiveBuilderBuilder;
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
Box::new(ArArchiveBuilder {
sess,
use_gnu_style_archive: sess.target.archive_format == "gnu",
// FIXME fix builtin ranlib on macOS
no_builtin_ranlib: sess.target.is_like_osx,
src_archives: vec![],
entries: vec![],
})
Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols))
}
fn create_dll_import_lib(
@ -40,200 +20,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
bug!("creating dll imports is not supported");
}
}
pub(crate) struct ArArchiveBuilder<'a> {
sess: &'a Session,
use_gnu_style_archive: bool,
no_builtin_ranlib: bool,
src_archives: Vec<File>,
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
// the end of an archive for linkers to not get confused.
entries: Vec<(Vec<u8>, ArchiveEntry)>,
}
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
ArchiveEntry::File(file.to_owned()),
));
}
fn add_archive(
&mut self,
archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> std::io::Result<()> {
let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
let archive = ArchiveFile::parse(&read_cache).unwrap();
let archive_index = self.src_archives.len();
for entry in archive.members() {
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
}
}
self.src_archives.push(read_cache.into_inner());
Ok(())
}
fn build(mut self: Box<Self>, output: &Path) -> bool {
enum BuilderKind {
Bsd(ar::Builder<File>),
Gnu(ar::GnuBuilder<File>),
}
let sess = self.sess;
let mut symbol_table = BTreeMap::new();
let mut entries = Vec::new();
for (mut entry_name, entry) in self.entries {
// FIXME only read the symbol table of the object files to avoid having to keep all
// object files in memory at once, or read them twice.
let data = match entry {
ArchiveEntry::FromArchive { archive_index, file_range } => {
// FIXME read symbols from symtab
let src_read_cache = &mut self.src_archives[archive_index];
src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap();
let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap());
src_read_cache.read_exact(&mut data).unwrap();
data
}
ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| {
sess.fatal(&format!(
"error while reading object file during archive building: {}",
err
));
}),
};
if !self.no_builtin_ranlib {
if symbol_table.contains_key(&entry_name) {
// The ar crate can't handle creating a symbol table in case of multiple archive
// members with the same name. Work around this by prepending a number until we
// get a unique name.
for i in 1.. {
let new_name = format!("{}_", i)
.into_bytes()
.into_iter()
.chain(entry_name.iter().copied())
.collect::<Vec<_>>();
if !symbol_table.contains_key(&new_name) {
entry_name = new_name;
break;
}
}
}
match object::File::parse(&*data) {
Ok(object) => {
symbol_table.insert(
entry_name.to_vec(),
object
.symbols()
.filter_map(|symbol| {
if symbol.is_undefined() || symbol.is_local() {
None
} else {
symbol.name().map(|name| name.as_bytes().to_vec()).ok()
}
})
.collect::<Vec<_>>(),
);
}
Err(err) => {
let err = err.to_string();
if err == "Unknown file magic" {
// Not an object file; skip it.
} else if object::read::archive::ArchiveFile::parse(&*data).is_ok() {
// Nested archive file; skip it.
} else {
sess.fatal(&format!(
"error parsing `{}` during archive creation: {}",
String::from_utf8_lossy(&entry_name),
err
));
}
}
}
}
entries.push((entry_name, data));
}
let mut builder = if self.use_gnu_style_archive {
BuilderKind::Gnu(
ar::GnuBuilder::new(
File::create(output).unwrap_or_else(|err| {
sess.fatal(&format!(
"error opening destination during archive building: {}",
err
));
}),
entries.iter().map(|(name, _)| name.clone()).collect(),
ar::GnuSymbolTableFormat::Size32,
symbol_table,
)
.unwrap(),
)
} else {
BuilderKind::Bsd(
ar::Builder::new(
File::create(output).unwrap_or_else(|err| {
sess.fatal(&format!(
"error opening destination during archive building: {}",
err
));
}),
symbol_table,
)
.unwrap(),
)
};
let any_members = !entries.is_empty();
// Add all files
for (entry_name, data) in entries.into_iter() {
let header = ar::Header::new(entry_name, data.len() as u64);
match builder {
BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
}
}
// Finalize archive
std::mem::drop(builder);
if self.no_builtin_ranlib {
let ranlib = crate::toolchain::get_toolchain_binary(self.sess, "ranlib");
// Run ranlib to be able to link the archive
let status = std::process::Command::new(ranlib)
.arg(output)
.status()
.expect("Couldn't run ranlib");
if !status.success() {
self.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
}
}
any_members
unimplemented!("creating dll imports is not yet supported");
}
}

View File

@ -11,12 +11,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ar"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -212,10 +206,8 @@ dependencies = [
name = "rustc_codegen_gcc"
version = "0.1.0"
dependencies = [
"ar",
"gccjit",
"lang_tester",
"target-lexicon",
"tempfile",
]
@ -228,12 +220,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "target-lexicon"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d"
[[package]]
name = "tempfile"
version = "3.2.0"

View File

@ -27,10 +27,6 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
# Local copy.
#gccjit = { path = "../gccjit.rs" }
target-lexicon = "0.10.0"
ar = "0.8.0"
[dev-dependencies]
lang_tester = "0.3.9"
tempfile = "3.1.0"

View File

@ -1,44 +1,17 @@
use std::fs::File;
use std::path::{Path, PathBuf};
use crate::errors::RanlibFailure;
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use rustc_codegen_ssa::back::archive::{
get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
};
use rustc_session::Session;
use rustc_session::cstore::DllImport;
struct ArchiveConfig<'a> {
sess: &'a Session,
use_native_ar: bool,
use_gnu_style_archive: bool,
}
#[derive(Debug)]
enum ArchiveEntry {
FromArchive {
archive_index: usize,
entry_index: usize,
},
File(PathBuf),
}
pub struct ArArchiveBuilderBuilder;
pub(crate) struct ArArchiveBuilderBuilder;
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
let config = ArchiveConfig {
sess,
use_native_ar: false,
// FIXME test for linux and System V derivatives instead
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
};
Box::new(ArArchiveBuilder {
config,
src_archives: vec![],
entries: vec![],
})
Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols))
}
fn create_dll_import_lib(
@ -49,144 +22,6 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
unimplemented!();
}
}
pub struct ArArchiveBuilder<'a> {
config: ArchiveConfig<'a>,
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
// the end of an archive for linkers to not get confused.
entries: Vec<(String, ArchiveEntry)>,
}
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string(),
ArchiveEntry::File(file.to_owned()),
));
}
fn add_archive(
&mut self,
archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> std::io::Result<()> {
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
let archive_index = self.src_archives.len();
let mut i = 0;
while let Some(entry) = archive.next_entry() {
let entry = entry?;
let file_name = String::from_utf8(entry.header().identifier().to_vec())
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries
.push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
}
i += 1;
}
self.src_archives.push((archive_path.to_owned(), archive));
Ok(())
}
fn build(mut self: Box<Self>, output: &Path) -> bool {
use std::process::Command;
fn add_file_using_ar(archive: &Path, file: &Path) {
Command::new("ar")
.arg("r") // add or replace file
.arg("-c") // silence created file message
.arg(archive)
.arg(&file)
.status()
.unwrap();
}
enum BuilderKind<'a> {
Bsd(ar::Builder<File>),
Gnu(ar::GnuBuilder<File>),
NativeAr(&'a Path),
}
let mut builder = if self.config.use_native_ar {
BuilderKind::NativeAr(output)
} else if self.config.use_gnu_style_archive {
BuilderKind::Gnu(ar::GnuBuilder::new(
File::create(output).unwrap(),
self.entries
.iter()
.map(|(name, _)| name.as_bytes().to_vec())
.collect(),
))
} else {
BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap()))
};
let any_members = !self.entries.is_empty();
// Add all files
for (entry_name, entry) in self.entries.into_iter() {
match entry {
ArchiveEntry::FromArchive {
archive_index,
entry_index,
} => {
let (ref src_archive_path, ref mut src_archive) =
self.src_archives[archive_index];
let entry = src_archive.jump_to_entry(entry_index).unwrap();
let header = entry.header().clone();
match builder {
BuilderKind::Bsd(ref mut builder) => {
builder.append(&header, entry).unwrap()
}
BuilderKind::Gnu(ref mut builder) => {
builder.append(&header, entry).unwrap()
}
BuilderKind::NativeAr(archive_file) => {
Command::new("ar")
.arg("x")
.arg(src_archive_path)
.arg(&entry_name)
.status()
.unwrap();
add_file_using_ar(archive_file, Path::new(&entry_name));
std::fs::remove_file(entry_name).unwrap();
}
}
}
ArchiveEntry::File(file) =>
match builder {
BuilderKind::Bsd(ref mut builder) => {
builder
.append_file(entry_name.as_bytes(), &mut File::open(file).expect("file for bsd builder"))
.unwrap()
},
BuilderKind::Gnu(ref mut builder) => {
builder
.append_file(entry_name.as_bytes(), &mut File::open(&file).expect(&format!("file {:?} for gnu builder", file)))
.unwrap()
},
BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file),
},
}
}
// Finalize archive
std::mem::drop(builder);
// Run ranlib to be able to link the archive
let status =
std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
if !status.success() {
self.config.sess.emit_fatal(RanlibFailure::new(status.code()));
}
any_members
unimplemented!("creating dll imports is not yet supported");
}
}

View File

@ -16,18 +16,6 @@ impl IntoDiagnosticArg for ExitCode {
}
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_ranlib_failure)]
pub(crate) struct RanlibFailure {
exit_code: ExitCode,
}
impl RanlibFailure {
pub fn new(exit_code: Option<i32>) -> Self {
RanlibFailure { exit_code: ExitCode(exit_code) }
}
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
@ -227,7 +215,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
#[diag(codegen_gcc_linkage_const_or_mut_type)]
pub(crate) struct LinkageConstOrMutType {
#[primary_span]
pub span: Span
pub span: Span,
}
#[derive(Diagnostic)]
@ -238,5 +226,5 @@ pub(crate) struct LTONotSupported;
#[diag(codegen_gcc_unwinding_inline_asm)]
pub(crate) struct UnwindingInlineAsm {
#[primary_span]
pub span: Span
pub span: Span,
}

View File

@ -11,7 +11,7 @@ bitflags = "1.0"
cstr = "0.2"
libc = "0.2"
measureme = "10.0.0"
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] }
object = { version = "0.29.0", default-features = false, features = ["std", "read"] }
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc-demangle = "0.1.21"

View File

@ -258,13 +258,12 @@ pub fn from_fn_attrs<'ll, 'tcx>(
OptimizeAttr::Speed => {}
}
let inline = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
InlineAttr::Never
} else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
InlineAttr::Hint
} else {
codegen_fn_attrs.inline
};
let inline =
if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
InlineAttr::Hint
} else {
codegen_fn_attrs.inline
};
to_add.extend(inline_attr(cx, inline));
// The `uwtable` attribute according to LLVM is:

View File

@ -1,31 +1,30 @@
//! A helper class for dealing with static archives
use std::env;
use std::ffi::{CStr, CString, OsString};
use std::fs;
use std::io::{self, Write};
use std::ffi::{c_char, c_void, CStr, CString, OsString};
use std::io;
use std::mem;
use std::path::{Path, PathBuf};
use std::ptr;
use std::str;
use object::read::macho::FatArch;
use crate::common;
use crate::errors::{
ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
ErrorWritingDEFFile, UnknownArchiveKind,
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
};
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use rustc_data_structures::memmap::Mmap;
use rustc_codegen_ssa::back::archive::{
get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
};
use rustc_session::cstore::DllImport;
use rustc_session::Session;
/// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the archive"]
pub struct LlvmArchiveBuilder<'a> {
pub(crate) struct LlvmArchiveBuilder<'a> {
sess: &'a Session,
additions: Vec<Addition>,
}
@ -61,57 +60,6 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
}
}
fn try_filter_fat_archs(
archs: object::read::Result<&[impl FatArch]>,
target_arch: object::Architecture,
archive_path: &Path,
archive_map_data: &[u8],
) -> io::Result<Option<PathBuf>> {
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
Some(a) => a,
None => return Ok(None),
};
let (mut new_f, extracted_path) = tempfile::Builder::new()
.suffix(archive_path.file_name().unwrap())
.tempfile()?
.keep()
.unwrap();
new_f.write_all(
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
)?;
Ok(Some(extracted_path))
}
fn try_extract_macho_fat_archive(
sess: &Session,
archive_path: &Path,
) -> io::Result<Option<PathBuf>> {
let archive_map = unsafe { Mmap::map(fs::File::open(&archive_path)?)? };
let target_arch = match sess.target.arch.as_ref() {
"aarch64" => object::Architecture::Aarch64,
"x86_64" => object::Architecture::X86_64,
_ => return Ok(None),
};
match object::macho::FatHeader::parse(&*archive_map) {
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
}
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
}
// Not a FatHeader at all, just return None.
_ => Ok(None),
}
}
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
fn add_archive(
&mut self,
@ -160,7 +108,11 @@ pub struct LlvmArchiveBuilderBuilder;
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
if sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
} else {
Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))
}
}
fn create_dll_import_lib(
@ -309,6 +261,61 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
}
}
// The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files.
// As such we need to use LLVM for them.
#[deny(unsafe_op_in_unsafe_fn)]
fn get_llvm_object_symbols(
buf: &[u8],
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
) -> io::Result<bool> {
let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };
// COFF bigobj file, msvc LTO file or import library. See
// https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");
if is_bitcode || is_unsupported_windows_obj_file {
let mut state = Box::new(f);
let err = unsafe {
llvm::LLVMRustGetSymbols(
buf.as_ptr(),
buf.len(),
&mut *state as *mut &mut _ as *mut c_void,
callback,
error_callback,
)
};
if err.is_null() {
return Ok(true);
} else {
return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
}
unsafe extern "C" fn callback(
state: *mut c_void,
symbol_name: *const c_char,
) -> *mut c_void {
let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
Ok(()) => std::ptr::null_mut(),
Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
}
}
unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
let error = unsafe { CStr::from_ptr(error) };
Box::into_raw(Box::new(io::Error::new(
io::ErrorKind::Other,
format!("LLVM error: {}", error.to_string_lossy()),
))) as *mut c_void
}
} else {
get_native_object_symbols(buf, f)
}
}
impl<'a> LlvmArchiveBuilder<'a> {
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
let kind = &*self.sess.target.archive_format;

View File

@ -72,12 +72,6 @@ pub(crate) struct LinkageConstOrMutType {
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
pub(crate) struct SanitizerMemtagRequiresMte;
#[derive(Diagnostic)]
#[diag(codegen_llvm_archive_build_failure)]
pub(crate) struct ArchiveBuildFailure {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_writing_def_file)]
pub(crate) struct ErrorWritingDEFFile {
@ -97,12 +91,6 @@ pub(crate) struct DlltoolFailImportLibrary<'a> {
pub stderr: Cow<'a, str>,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_unknown_archive_kind)]
pub(crate) struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_dynamic_linking_with_lto)]
#[note]

View File

@ -983,6 +983,9 @@ pub type SelfProfileBeforePassCallback =
unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
extern "C" {
pub fn LLVMRustInstallFatalErrorHandler();
pub fn LLVMRustDisableSystemDialogsOnCrash();
@ -2474,4 +2477,14 @@ extern "C" {
pub fn LLVMRustGetMangledName(V: &Value, out: &RustString);
pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32;
pub fn LLVMRustIsBitcode(ptr: *const u8, len: usize) -> bool;
pub fn LLVMRustGetSymbols(
buf_ptr: *const u8,
buf_len: usize,
state: *mut c_void,
callback: GetSymbolsCallback,
error_callback: GetSymbolsErrorCallback,
) -> *mut c_void;
}

View File

@ -494,6 +494,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
.flatten();
features.extend(feats);
// FIXME: Move v8a to target definition list when earliest supported LLVM is 14.
if get_version() >= (14, 0, 0) && sess.target.arch == "aarch64" {
features.push("+v8a".into());
}
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
sess.emit_err(TargetFeatureDisableOrEnable {
features: f,

View File

@ -7,6 +7,7 @@ edition = "2021"
test = false
[dependencies]
ar_archive_writer = "0.1.1"
bitflags = "1.2.1"
cc = "1.0.69"
itertools = "0.10.1"

View File

@ -6,14 +6,19 @@ use rustc_span::symbol::Symbol;
use super::metadata::search_for_section;
pub use ar_archive_writer::get_native_object_symbols;
use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
use object::read::archive::ArchiveFile;
use object::read::macho::FatArch;
use tempfile::Builder as TempFileBuilder;
use std::error::Error;
use std::fs::File;
use std::io;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use crate::errors::ExtractBundledLibsError;
// Re-exporting for rustc_codegen_llvm::back::archive
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
pub trait ArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a>;
@ -80,3 +85,225 @@ pub trait ArchiveBuilder<'a> {
fn build(self: Box<Self>, output: &Path) -> bool;
}
#[must_use = "must call build() to finish building the archive"]
pub struct ArArchiveBuilder<'a> {
sess: &'a Session,
get_object_symbols:
fn(buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>) -> io::Result<bool>,
src_archives: Vec<(PathBuf, Mmap)>,
// Don't use an `HashMap` here, as the order is important. `lib.rmeta` needs
// to be at the end of an archive in some cases for linkers to not get confused.
entries: Vec<(Vec<u8>, ArchiveEntry)>,
}
#[derive(Debug)]
enum ArchiveEntry {
FromArchive { archive_index: usize, file_range: (u64, u64) },
File(PathBuf),
}
impl<'a> ArArchiveBuilder<'a> {
pub fn new(
sess: &'a Session,
get_object_symbols: fn(
buf: &[u8],
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
) -> io::Result<bool>,
) -> ArArchiveBuilder<'a> {
ArArchiveBuilder { sess, get_object_symbols, src_archives: vec![], entries: vec![] }
}
}
fn try_filter_fat_archs(
archs: object::read::Result<&[impl FatArch]>,
target_arch: object::Architecture,
archive_path: &Path,
archive_map_data: &[u8],
) -> io::Result<Option<PathBuf>> {
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
Some(a) => a,
None => return Ok(None),
};
let (mut new_f, extracted_path) = tempfile::Builder::new()
.suffix(archive_path.file_name().unwrap())
.tempfile()?
.keep()
.unwrap();
new_f.write_all(
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
)?;
Ok(Some(extracted_path))
}
pub fn try_extract_macho_fat_archive(
sess: &Session,
archive_path: &Path,
) -> io::Result<Option<PathBuf>> {
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
let target_arch = match sess.target.arch.as_ref() {
"aarch64" => object::Architecture::Aarch64,
"x86_64" => object::Architecture::X86_64,
_ => return Ok(None),
};
match object::macho::FatHeader::parse(&*archive_map) {
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
}
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
}
// Not a FatHeader at all, just return None.
_ => Ok(None),
}
}
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn add_archive(
&mut self,
archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> {
let mut archive_path = archive_path.to_path_buf();
if self.sess.target.llvm_target.contains("-apple-macosx") {
if let Some(new_archive_path) =
try_extract_macho_fat_archive(&self.sess, &archive_path)?
{
archive_path = new_archive_path
}
}
if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
return Ok(());
}
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
let archive = ArchiveFile::parse(&*archive_map)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let archive_index = self.src_archives.len();
for entry in archive.members() {
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
}
}
self.src_archives.push((archive_path.to_owned(), archive_map));
Ok(())
}
/// Adds an arbitrary file to this archive
fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
ArchiveEntry::File(file.to_owned()),
));
}
/// Combine the provided files, rlibs, and native libraries into a single
/// `Archive`.
fn build(self: Box<Self>, output: &Path) -> bool {
let sess = self.sess;
match self.build_inner(output) {
Ok(any_members) => any_members,
Err(e) => sess.emit_fatal(ArchiveBuildFailure { error: e }),
}
}
}
impl<'a> ArArchiveBuilder<'a> {
fn build_inner(self, output: &Path) -> io::Result<bool> {
let archive_kind = match &*self.sess.target.archive_format {
"gnu" => ArchiveKind::Gnu,
"bsd" => ArchiveKind::Bsd,
"darwin" => ArchiveKind::Darwin,
"coff" => ArchiveKind::Coff,
kind => {
self.sess.emit_fatal(UnknownArchiveKind { kind });
}
};
let mut entries = Vec::new();
for (entry_name, entry) in self.entries {
let data =
match entry {
ArchiveEntry::FromArchive { archive_index, file_range } => {
let src_archive = &self.src_archives[archive_index];
let data = &src_archive.1
[file_range.0 as usize..file_range.0 as usize + file_range.1 as usize];
Box::new(data) as Box<dyn AsRef<[u8]>>
}
ArchiveEntry::File(file) => unsafe {
Box::new(
Mmap::map(File::open(file).map_err(|err| {
io_error_context("failed to open object file", err)
})?)
.map_err(|err| io_error_context("failed to map object file", err))?,
) as Box<dyn AsRef<[u8]>>
},
};
entries.push(NewArchiveMember {
buf: data,
get_symbols: self.get_object_symbols,
member_name: String::from_utf8(entry_name).unwrap(),
mtime: 0,
uid: 0,
gid: 0,
perms: 0o644,
})
}
// Write to a temporary file first before atomically renaming to the final name.
// This prevents programs (including rustc) from attempting to read a partial archive.
// It also enables writing an archive with the same filename as a dependency on Windows as
// required by a test.
let mut archive_tmpfile = TempFileBuilder::new()
.suffix(".temp-archive")
.tempfile_in(output.parent().unwrap_or_else(|| Path::new("")))
.map_err(|err| io_error_context("couldn't create a temp file", err))?;
write_archive_to_stream(
archive_tmpfile.as_file_mut(),
&entries,
true,
archive_kind,
true,
false,
)?;
let any_entries = !entries.is_empty();
drop(entries);
// Drop src_archives to unmap all input archives, which is necessary if we want to write the
// output archive to the same location as an input archive on Windows.
drop(self.src_archives);
archive_tmpfile
.persist(output)
.map_err(|err| io_error_context("failed to rename archive file", err.error))?;
Ok(any_entries)
}
}
fn io_error_context(context: &str, err: io::Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("{context}: {err}"))
}

View File

@ -534,3 +534,17 @@ pub struct ReadFileError {
#[derive(Diagnostic)]
#[diag(codegen_ssa_unsupported_link_self_contained)]
pub struct UnsupportedLinkSelfContained;
#[derive(Diagnostic)]
#[diag(codegen_ssa_archive_build_failure)]
// Public for rustc_codegen_llvm::back::archive
pub struct ArchiveBuildFailure {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_unknown_archive_kind)]
// Public for rustc_codegen_llvm::back::archive
pub struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}

View File

@ -309,14 +309,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
// In the algorithm above, we can change
// cast(relative_tag) + niche_variants.start()
// into
// cast(tag) + (niche_variants.start() - niche_start)
// cast(tag + (niche_variants.start() - niche_start))
// if either the casted type is no larger than the original
// type, or if the niche values are contiguous (in either the
// signed or unsigned sense).
let can_incr_after_cast = cast_smaller || niches_ule || niches_sle;
let can_incr = cast_smaller || niches_ule || niches_sle;
let data_for_boundary_niche = || -> Option<(IntPredicate, u128)> {
if !can_incr_after_cast {
if !can_incr {
None
} else if niche_start == low_unsigned {
Some((IntPredicate::IntULE, niche_end))
@ -353,24 +353,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
// The algorithm is now this:
// is_niche = tag <= niche_end
// discr = if is_niche {
// cast(tag) + (niche_variants.start() - niche_start)
// cast(tag + (niche_variants.start() - niche_start))
// } else {
// untagged_variant
// }
// (the first line may instead be tag >= niche_start,
// and may be a signed or unsigned comparison)
// The arithmetic must be done before the cast, so we can
// have the correct wrapping behavior. See issue #104519 for
// the consequences of getting this wrong.
let is_niche =
bx.icmp(predicate, tag, bx.cx().const_uint_big(tag_llty, constant));
let cast_tag = if cast_smaller {
bx.intcast(tag, cast_to, false)
} else if niches_ule {
bx.zext(tag, cast_to)
let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
let incr_tag = if delta == 0 {
tag
} else {
bx.sext(tag, cast_to)
bx.add(tag, bx.cx().const_uint_big(tag_llty, delta))
};
let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
(is_niche, cast_tag, delta)
let cast_tag = if cast_smaller {
bx.intcast(incr_tag, cast_to, false)
} else if niches_ule {
bx.zext(incr_tag, cast_to)
} else {
bx.sext(incr_tag, cast_to)
};
(is_niche, cast_tag, 0)
} else {
// The special cases don't apply, so we'll have to go with
// the general algorithm.

View File

@ -72,7 +72,7 @@ impl<'a, T: PartialOrd> PartialOrd for Interned<'a, T> {
if ptr::eq(self.0, other.0) {
Some(Ordering::Equal)
} else {
let res = self.0.partial_cmp(&other.0);
let res = self.0.partial_cmp(other.0);
debug_assert_ne!(res, Some(Ordering::Equal));
res
}
@ -86,7 +86,7 @@ impl<'a, T: Ord> Ord for Interned<'a, T> {
if ptr::eq(self.0, other.0) {
Ordering::Equal
} else {
let res = self.0.cmp(&other.0);
let res = self.0.cmp(other.0);
debug_assert_ne!(res, Ordering::Equal);
res
}

View File

@ -36,6 +36,12 @@ impl Deref for Mmap {
#[inline]
fn deref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for Mmap {
fn as_ref(&self) -> &[u8] {
&*self.0
}
}
@ -96,13 +102,13 @@ impl Deref for MmapMut {
#[inline]
fn deref(&self) -> &[u8] {
&*self.0
&self.0
}
}
impl DerefMut for MmapMut {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
&mut *self.0
&mut self.0
}
}

View File

@ -899,25 +899,25 @@ unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {}
impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> {
fn as_ref(&self) -> &T {
&*self
self
}
}
impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> {
fn as_ref(&self) -> &T {
&*self
self
}
}
impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
self
}
}
impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> {
fn borrow(&self) -> &T {
&*self
self
}
}
@ -1021,7 +1021,7 @@ where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
(&*self as &T).eq(&*other as &T)
self.deref().eq(other.deref())
}
}
@ -1032,7 +1032,7 @@ where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(&*self as &T).partial_cmp(&*other as &T)
self.deref().partial_cmp(other.deref())
}
}
@ -1041,7 +1041,7 @@ where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
(&*self as &T).cmp(&*other as &T)
self.deref().cmp(other.deref())
}
}
@ -1050,7 +1050,7 @@ where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
(&*self as &T).hash(state);
self.deref().hash(state);
}
}
@ -1059,7 +1059,7 @@ where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
(&*self as &T).eq(&*other as &T)
self.deref().eq(other.deref())
}
}
@ -1070,7 +1070,7 @@ where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(&*self as &T).partial_cmp(&*other as &T)
self.deref().partial_cmp(other.deref())
}
}
@ -1079,7 +1079,7 @@ where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
(&*self as &T).cmp(&*other as &T)
self.deref().cmp(other.deref())
}
}
@ -1088,7 +1088,7 @@ where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
(&*self as &T).hash(state);
self.deref().hash(state);
}
}

View File

@ -192,7 +192,7 @@ impl SelfProfilerRef {
F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>,
{
let profiler = profiler_ref.profiler.as_ref().unwrap();
f(&**profiler)
f(profiler)
}
if self.event_filter_mask.contains(event_filter) {
@ -466,7 +466,7 @@ impl SelfProfilerRef {
pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
if let Some(profiler) = &self.profiler {
f(&profiler)
f(profiler)
}
}
@ -733,7 +733,7 @@ impl Drop for VerboseTimingGuard<'_> {
if let Some((start_time, start_rss, ref message)) = self.start_and_message {
let end_rss = get_resident_set_size();
let dur = start_time.elapsed();
print_time_passes_entry(&message, dur, start_rss, end_rss);
print_time_passes_entry(message, dur, start_rss, end_rss);
}
}
}

View File

@ -366,7 +366,7 @@ impl<CTX> HashStable<CTX> for [u8] {
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
#[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
(&self[..]).hash_stable(ctx, hasher);
self[..].hash_stable(ctx, hasher);
}
}
@ -405,7 +405,7 @@ where
{
#[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
(&self[..]).hash_stable(ctx, hasher);
self[..].hash_stable(ctx, hasher);
}
}
@ -440,7 +440,7 @@ impl<CTX> HashStable<CTX> for str {
impl<CTX> HashStable<CTX> for String {
#[inline]
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
(&self[..]).hash_stable(hcx, hasher);
self[..].hash_stable(hcx, hasher);
}
}

View File

@ -201,7 +201,7 @@ cfg_if! {
#[inline(always)]
fn deref(&self) -> &T {
&*self.0
&self.0
}
}

View File

@ -245,10 +245,8 @@ fn run_compiler(
interface::run_compiler(config, |compiler| {
let sopts = &compiler.session().opts;
if sopts.describe_lints {
let mut lint_store = rustc_lint::new_lint_store(
sopts.unstable_opts.no_interleave_lints,
compiler.session().enable_internal_lints(),
);
let mut lint_store =
rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
let registered_lints =
if let Some(register_lints) = compiler.register_lints() {
register_lints(compiler.session(), &mut lint_store);

View File

@ -1,6 +1,3 @@
codegen_gcc_ranlib_failure =
Ranlib exited with code {$exit_code}
codegen_gcc_linkage_const_or_mut_type =
must have type `*const T` or `*mut T` due to `#[linkage]` attribute

View File

@ -29,9 +29,6 @@ codegen_llvm_linkage_const_or_mut_type =
codegen_llvm_sanitizer_memtag_requires_mte =
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
codegen_llvm_archive_build_failure =
failed to build archive: {$error}
codegen_llvm_error_writing_def_file =
Error writing .DEF file: {$error}
@ -41,9 +38,6 @@ codegen_llvm_error_calling_dlltool =
codegen_llvm_dlltool_fail_import_library =
Dlltool could not create import library: {$stdout}\n{$stderr}
codegen_llvm_unknown_archive_kind =
Don't know how to build archive of type: {$kind}
codegen_llvm_target_feature_disable_or_enable =
the target features {$features} must all be either enabled or disabled together

View File

@ -186,3 +186,9 @@ codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {erro
codegen_ssa_read_file = failed to read file: {message}
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
codegen_ssa_archive_build_failure =
failed to build archive: {$error}
codegen_ssa_unknown_archive_kind =
Don't know how to build archive of type: {$kind}

View File

@ -39,7 +39,7 @@ impl Translate for AnnotateSnippetEmitterWriter {
}
fn fallback_fluent_bundle(&self) -> &FluentBundle {
&**self.fallback_bundle
&self.fallback_bundle
}
}
@ -49,7 +49,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
let fluent_args = to_fluent_args(diag.args());
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args);
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
&mut primary_span,
@ -65,7 +65,7 @@ impl Emitter for AnnotateSnippetEmitterWriter {
&diag.code,
&primary_span,
&children,
&suggestions,
suggestions,
);
}

View File

@ -292,7 +292,7 @@ impl Diagnostic {
let lint_index = expectation_id.get_lint_index();
expectation_id.set_lint_index(None);
let mut stable_id = unstable_to_stable
.get(&expectation_id)
.get(expectation_id)
.expect("each unstable `LintExpectationId` must have a matching stable id")
.normalize();

View File

@ -283,7 +283,7 @@ pub trait Emitter: Translate {
if self
.source_map()
.map(|sm| is_case_difference(
&**sm,
sm,
substitution,
sugg.substitutions[0].parts[0].span,
))
@ -525,7 +525,7 @@ impl Translate for EmitterWriter {
}
fn fallback_fluent_bundle(&self) -> &FluentBundle {
&**self.fallback_bundle
&self.fallback_bundle
}
}
@ -538,7 +538,7 @@ impl Emitter for EmitterWriter {
let fluent_args = to_fluent_args(diag.args());
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args);
debug!("emit_diagnostic: suggestions={:?}", suggestions);
self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
@ -555,7 +555,7 @@ impl Emitter for EmitterWriter {
&diag.code,
&primary_span,
&children,
&suggestions,
suggestions,
self.track_diagnostics.then_some(&diag.emitted_at),
);
}
@ -801,7 +801,7 @@ impl EmitterWriter {
}
let source_string = match file.get_line(line.line_index - 1) {
Some(s) => normalize_whitespace(&*s),
Some(s) => normalize_whitespace(&s),
None => return Vec::new(),
};
@ -1148,7 +1148,7 @@ impl EmitterWriter {
(pos + 2, annotation.start_col.saturating_sub(left))
};
if let Some(ref label) = annotation.label {
buffer.puts(line_offset + pos, code_offset + col, &label, style);
buffer.puts(line_offset + pos, code_offset + col, label, style);
}
}
@ -1358,7 +1358,7 @@ impl EmitterWriter {
// only render error codes, not lint codes
if let Some(DiagnosticId::Error(ref code)) = *code {
buffer.append(0, "[", Style::Level(*level));
buffer.append(0, &code, Style::Level(*level));
buffer.append(0, code, Style::Level(*level));
buffer.append(0, "]", Style::Level(*level));
label_width += 2 + code.len();
}
@ -1683,7 +1683,7 @@ impl EmitterWriter {
};
// Render the replacements for each suggestion
let suggestions = suggestion.splice_lines(&**sm);
let suggestions = suggestion.splice_lines(sm);
debug!("emit_suggestion_default: suggestions={:?}", suggestions);
if suggestions.is_empty() {
@ -1784,7 +1784,7 @@ impl EmitterWriter {
buffer.puts(
row_num - 1 + line - line_start,
max_line_num_len + 3,
&normalize_whitespace(&*file_lines.file.get_line(line - 1).unwrap()),
&normalize_whitespace(&file_lines.file.get_line(line - 1).unwrap()),
Style::Removal,
);
}
@ -1926,7 +1926,7 @@ impl EmitterWriter {
buffer.putc(
row_num,
(padding as isize + p) as usize,
if part.is_addition(&sm) { '+' } else { '~' },
if part.is_addition(sm) { '+' } else { '~' },
Style::Addition,
);
}
@ -1973,7 +1973,7 @@ impl EmitterWriter {
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
} else if notice_capitalization {
let msg = "notice the capitalization difference";
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
buffer.puts(row_num, max_line_num_len + 3, msg, Style::NoStyle);
}
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
Ok(())
@ -2028,7 +2028,7 @@ impl EmitterWriter {
for child in children {
let span = child.render_span.as_ref().unwrap_or(&child.span);
if let Err(err) = self.emit_message_default(
&span,
span,
&child.message,
args,
&None,
@ -2113,7 +2113,7 @@ impl EmitterWriter {
*row_num - 1,
max_line_num_len + 3,
&normalize_whitespace(
&*file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(),
&file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(),
),
Style::NoStyle,
);

View File

@ -136,7 +136,7 @@ impl Translate for JsonEmitter {
}
fn fallback_fluent_bundle(&self) -> &FluentBundle {
&**self.fallback_bundle
&self.fallback_bundle
}
}

View File

@ -470,6 +470,7 @@ pub enum StashKey {
/// Maybe there was a typo where a comma was forgotten before
/// FRU syntax
MaybeFruTypo,
CallAssocMethod,
}
fn default_track_diagnostic(_: &Diagnostic) {}
@ -1328,7 +1329,7 @@ impl HandlerInner {
diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {});
self.emitter.emit_diagnostic(&diagnostic);
self.emitter.emit_diagnostic(diagnostic);
if diagnostic.is_error() {
self.deduplicated_err_count += 1;
} else if let Warning(_) = diagnostic.level {

View File

@ -59,13 +59,13 @@ pub trait Translate {
trace!(?message, ?args);
let (identifier, attr) = match message {
DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
return Cow::Borrowed(&msg);
return Cow::Borrowed(msg);
}
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
};
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
let message = bundle.get_message(&identifier)?;
let message = bundle.get_message(identifier)?;
let value = match attr {
Some(attr) => message.get_attribute(attr)?.value(),
None => message.value()?,
@ -73,7 +73,7 @@ pub trait Translate {
debug!(?message, ?value);
let mut errs = vec![];
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
let translated = bundle.format_pattern(value, Some(args), &mut errs);
debug!(?translated, ?errs);
Some((translated, errs))
};

View File

@ -539,6 +539,9 @@ impl<'a> ExtCtxt<'a> {
fn_decl,
body,
fn_decl_span: span,
// FIXME(SarthakSingh31): This points to the start of the declaration block and
// not the span of the argument block.
fn_arg_span: span,
})),
)
}

View File

@ -65,7 +65,7 @@ pub enum LinkOrCopy {
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
let p = p.as_ref();
let q = q.as_ref();
match fs::remove_file(&q) {
match fs::remove_file(q) {
Ok(()) => (),
Err(err) if err.kind() == io::ErrorKind::NotFound => (),
Err(err) => return Err(err),

View File

@ -410,7 +410,7 @@ impl<'a> Id<'a> {
}
pub fn as_slice(&'a self) -> &'a str {
&*self.name
&self.name
}
}
@ -515,7 +515,7 @@ impl<'a> LabelText<'a> {
pub fn to_dot_string(&self) -> String {
match *self {
LabelStr(ref s) => format!("\"{}\"", s.escape_default()),
EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)),
EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)),
HtmlStr(ref s) => format!("<{}>", s),
}
}
@ -529,7 +529,7 @@ impl<'a> LabelText<'a> {
EscStr(s) => s,
LabelStr(s) => {
if s.contains('\\') {
(&*s).escape_default().to_string().into()
s.escape_default().to_string().into()
} else {
s
}

View File

@ -943,7 +943,10 @@ pub struct Closure<'hir> {
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub fn_decl: &'hir FnDecl<'hir>,
pub body: BodyId,
/// The span of the declaration block: 'move |...| -> ...'
pub fn_decl_span: Span,
/// The span of the argument block `|...|`
pub fn_arg_span: Option<Span>,
pub movability: Option<Movability>,
}
@ -2434,7 +2437,7 @@ impl<'hir> Ty<'hir> {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = &ty;
final_ty = ty;
}
final_ty
}

View File

@ -116,7 +116,7 @@ impl Ord for HirId {
impl PartialOrd for HirId {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other))
Some(self.cmp(other))
}
}

View File

@ -448,7 +448,7 @@ pub trait Visitor<'v>: Sized {
pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
visitor.visit_id(param.hir_id);
visitor.visit_pat(&param.pat);
visitor.visit_pat(param.pat);
}
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
@ -470,7 +470,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
}
ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header),
&sig.decl,
sig.decl,
body_id,
item.span,
item.hir_id(),
@ -544,7 +544,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
walk_list!(visitor, visit_param, body.params);
visitor.visit_expr(&body.value);
visitor.visit_expr(body.value);
}
pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) {
@ -580,7 +580,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
// dominates the local's definition.
walk_list!(visitor, visit_expr, &local.init);
visitor.visit_id(local.hir_id);
visitor.visit_pat(&local.pat);
visitor.visit_pat(local.pat);
if let Some(els) = local.els {
visitor.visit_block(els);
}
@ -606,7 +606,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
visitor.visit_id(arm.hir_id);
visitor.visit_pat(&arm.pat);
visitor.visit_pat(arm.pat);
if let Some(ref g) = arm.guard {
match g {
Guard::If(ref e) => visitor.visit_expr(e),
@ -615,7 +615,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
}
}
}
visitor.visit_expr(&arm.body);
visitor.visit_expr(arm.body);
}
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
@ -660,7 +660,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) {
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
visitor.visit_pat(&field.pat)
visitor.visit_pat(field.pat)
}
pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
@ -740,6 +740,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
body,
capture_clause: _,
fn_decl_span: _,
fn_arg_span: _,
movability: _,
}) => {
walk_list!(visitor, visit_generic_param, bound_generic_params);
@ -799,7 +800,7 @@ pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>)
pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) {
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
visitor.visit_expr(&field.expr)
visitor.visit_expr(field.expr)
}
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
@ -807,10 +808,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
match typ.kind {
TyKind::Slice(ref ty) => visitor.visit_ty(ty),
TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty),
TyKind::Rptr(ref lifetime, ref mutable_type) => {
visitor.visit_lifetime(lifetime);
visitor.visit_ty(&mutable_type.ty)
visitor.visit_ty(mutable_type.ty)
}
TyKind::Never => {}
TyKind::Tup(tuple_element_types) => {
@ -818,7 +819,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
}
TyKind::BareFn(ref function_declaration) => {
walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
visitor.visit_fn_decl(&function_declaration.decl);
visitor.visit_fn_decl(function_declaration.decl);
}
TyKind::Path(ref qpath) => {
visitor.visit_qpath(qpath, typ.hir_id, typ.span);
@ -951,8 +952,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
visitor.visit_ident(ident);
visitor.visit_generics(&generics);
visitor.visit_defaultness(&defaultness);
visitor.visit_generics(generics);
visitor.visit_defaultness(defaultness);
match *kind {
TraitItemKind::Const(ref ty, default) => {
visitor.visit_id(hir_id);
@ -961,13 +962,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
}
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
visitor.visit_id(hir_id);
visitor.visit_fn_decl(&sig.decl);
visitor.visit_fn_decl(sig.decl);
for &param_name in param_names {
visitor.visit_ident(param_name);
}
}
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id);
visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id);
}
TraitItemKind::Type(bounds, ref default) => {
visitor.visit_id(hir_id);
@ -1009,7 +1010,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
ImplItemKind::Fn(ref sig, body_id) => {
visitor.visit_fn(
FnKind::Method(impl_item.ident, sig),
&sig.decl,
sig.decl,
body_id,
impl_item.span,
impl_item.hir_id(),
@ -1042,7 +1043,7 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
visitor.visit_id(trait_ref.hir_ref_id);
visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id)
}
pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
@ -1074,7 +1075,7 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(
pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) {
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
visitor.visit_ty(&field.ty);
visitor.visit_ty(field.ty);
}
pub fn walk_enum_def<'v, V: Visitor<'v>>(

View File

@ -11,7 +11,6 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::{
self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
};
@ -83,9 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
let param_name = tcx.hir().ty_param_name(param_local_id);
let infcx = tcx.infer_ctxt().build();
let param_type =
infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id));
let param_type = tcx.type_of(param.def_id);
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
tcx.def_span(src_def_id),

View File

@ -347,7 +347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assert!(self_ty.is_some());
}
} else {
assert!(self_ty.is_none() && parent_substs.is_empty());
assert!(self_ty.is_none());
}
let arg_count = Self::check_generic_arg_count(
@ -1821,7 +1821,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Check if we have an enum variant.
let mut variant_resolution = None;
if let ty::Adt(adt_def, _) = qself_ty.kind() {
if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() {
if adt_def.is_enum() {
let variant_def = adt_def
.variants()
@ -1923,8 +1923,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
continue;
};
// FIXME(inherent_associated_types): This does not substitute parameters.
let ty = tcx.type_of(assoc_ty_did);
let item_substs = self.create_substs_for_associated_item(
span,
assoc_ty_did,
assoc_segment,
adt_substs,
);
let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
}
}

View File

@ -173,13 +173,11 @@ fn compare_predicate_entailment<'tcx>(
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
// Check region bounds.
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, &trait_m_generics, &impl_m_generics)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?;
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
@ -338,6 +336,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
// First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
let trait_to_impl_substs = impl_trait_ref.substs;
@ -722,12 +721,14 @@ fn check_region_bounds_on_impl_item<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
trait_m: &ty::AssocItem,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
let trait_params = trait_generics.own_counts().lifetimes;
let impl_generics = tcx.generics_of(impl_m.def_id);
let impl_params = impl_generics.own_counts().lifetimes;
let trait_generics = tcx.generics_of(trait_m.def_id);
let trait_params = trait_generics.own_counts().lifetimes;
debug!(
"check_region_bounds_on_impl_item: \
trait_generics={:?} \
@ -761,12 +762,16 @@ fn check_region_bounds_on_impl_item<'tcx>(
None
};
let reported = tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
span,
item_kind: assoc_item_kind_str(impl_m),
ident: impl_m.ident(tcx),
generics_span,
});
let reported = tcx
.sess
.create_err(LifetimesOrBoundsMismatchOnTrait {
span,
item_kind: assoc_item_kind_str(impl_m),
ident: impl_m.ident(tcx),
generics_span,
})
.emit_unless(delay);
return Err(reported);
}
@ -1504,18 +1509,10 @@ fn compare_type_predicate_entailment<'tcx>(
let trait_to_impl_substs =
impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
let impl_ty_generics = tcx.generics_of(impl_ty.def_id);
let trait_ty_generics = tcx.generics_of(trait_ty.def_id);
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
check_region_bounds_on_impl_item(
tcx,
impl_ty,
trait_ty,
&trait_ty_generics,
&impl_ty_generics,
)?;
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);

View File

@ -241,17 +241,46 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
// scopes, meaning that temporaries cannot outlive them.
// This ensures fixed size stacks.
hir::ExprKind::Binary(
source_map::Spanned { node: hir::BinOpKind::And, .. },
_,
ref r,
)
| hir::ExprKind::Binary(
source_map::Spanned { node: hir::BinOpKind::Or, .. },
_,
source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
ref l,
ref r,
) => {
// For shortcircuiting operators, mark the RHS as a terminating
// scope since it only executes conditionally.
// expr is a short circuiting operator (|| or &&). As its
// functionality can't be overridden by traits, it always
// processes bool sub-expressions. bools are Copy and thus we
// can drop any temporaries in evaluation (read) order
// (with the exception of potentially failing let expressions).
// We achieve this by enclosing the operands in a terminating
// scope, both the LHS and the RHS.
// We optimize this a little in the presence of chains.
// Chains like a && b && c get lowered to AND(AND(a, b), c).
// In here, b and c are RHS, while a is the only LHS operand in
// that chain. This holds true for longer chains as well: the
// leading operand is always the only LHS operand that is not a
// binop itself. Putting a binop like AND(a, b) into a
// terminating scope is not useful, thus we only put the LHS
// into a terminating scope if it is not a binop.
let terminate_lhs = match l.kind {
// let expressions can create temporaries that live on
hir::ExprKind::Let(_) => false,
// binops already drop their temporaries, so there is no
// need to put them into a terminating scope.
// This is purely an optimization to reduce the number of
// terminating scopes.
hir::ExprKind::Binary(
source_map::Spanned {
node: hir::BinOpKind::And | hir::BinOpKind::Or, ..
},
..,
) => false,
// otherwise: mark it as terminating
_ => true,
};
if terminate_lhs {
terminating(l.hir_id.local_id);
}
// `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
// should live beyond the immediate expression

View File

@ -1544,7 +1544,7 @@ fn check_fn_or_method<'tcx>(
check_where_clauses(wfcx, span, def_id);
check_return_position_impl_trait_in_trait_bounds(
tcx,
wfcx,
def_id,
sig.output(),
hir_decl.output.span(),
@ -1580,13 +1580,14 @@ fn check_fn_or_method<'tcx>(
/// Basically `check_associated_type_bounds`, but separated for now and should be
/// deduplicated when RPITITs get lowered into real associated items.
#[tracing::instrument(level = "trace", skip(tcx))]
#[tracing::instrument(level = "trace", skip(wfcx))]
fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
wfcx: &WfCheckingCtxt<'_, 'tcx>,
fn_def_id: LocalDefId,
fn_output: Ty<'tcx>,
span: Span,
) {
let tcx = wfcx.tcx();
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
{
@ -1596,22 +1597,20 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
&& tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
&& tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
{
// Create a new context, since we want the opaque's ParamEnv and not the parent's.
let span = tcx.def_span(proj.item_def_id);
enter_wf_checking_ctxt(tcx, span, proj.item_def_id.expect_local(), |wfcx| {
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
wfcx.infcx,
wfcx.param_env,
wfcx.body_id,
normalized_bound,
bound_span,
)
});
wfcx.register_obligations(wf_obligations);
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
wfcx.infcx,
wfcx.param_env,
wfcx.body_id,
normalized_bound,
bound_span,
)
});
wfcx.register_obligations(wf_obligations);
}
}
}

View File

@ -56,25 +56,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx
.maybe_unused_extern_crates(())
.iter()
.filter(|&&(def_id, _)| {
// The `def_id` here actually was calculated during resolution (at least
// at the time of this writing) and is being shipped to us via a side
// channel of the tcx. There may have been extra expansion phases,
// however, which ended up removing the `def_id` *after* expansion.
//
// As a result we need to verify that `def_id` is indeed still valid for
// our AST and actually present in the HIR map. If it's not there then
// there's safely nothing to warn about, and otherwise we carry on with
// our execution.
//
// Note that if we carry through to the `extern_mod_stmt_cnum` query
// below it'll cause a panic because `def_id` is actually bogus at this
// point in time otherwise.
if tcx.hir().find(tcx.hir().local_def_id_to_hir_id(def_id)).is_none() {
return false;
}
true
})
.filter(|&&(def_id, _)| {
tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| {
!tcx.is_compiler_builtins(cnum)

View File

@ -2073,6 +2073,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
codegen_fn_attrs.inline = InlineAttr::Never;
}
// Weak lang items have the same semantics as "std internal" symbols in the
// sense that they're preserved through all our LTO passes and only
// strippable by the linker.

View File

@ -1480,6 +1480,7 @@ impl<'a> State<'a> {
fn_decl,
body,
fn_decl_span: _,
fn_arg_span: _,
movability: _,
def_id: _,
}) => {

View File

@ -456,10 +456,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter()
.map(|ty| ArgKind::from_expected_ty(*ty, None))
.collect();
let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) {
Some((sp, args)) => (Some(sp), args),
None => (None, Vec::new()),
};
let (closure_span, closure_arg_span, found_args) =
match self.get_fn_like_arguments(expr_map_node) {
Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args),
None => (None, None, Vec::new()),
};
let expected_span =
expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
self.report_arg_count_mismatch(
@ -468,6 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_args,
found_args,
true,
closure_arg_span,
)
.emit();

View File

@ -528,6 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
let ty = match res {
Res::Err => {
self.suggest_assoc_method_call(segs);
let e =
self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);

View File

@ -1918,6 +1918,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
receiver: Option<&'tcx hir::Expr<'tcx>>,
args: &'tcx [hir::Expr<'tcx>],
) -> bool {
// Do not call `fn_sig` on non-functions.
if !matches!(
self.tcx.def_kind(def_id),
DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..)
) {
return false;
}
let sig = self.tcx.fn_sig(def_id).skip_binder();
let args_referencing_param: Vec<_> = sig
.inputs()

View File

@ -22,7 +22,7 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span};
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use std::cell::{Cell, RefCell};
use std::ops::Deref;
@ -162,6 +162,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infcx: &self.infcx,
typeck_results: Some(self.typeck_results.borrow()),
fallback_has_occurred: self.fallback_has_occurred.get(),
normalize_fn_sig: Box::new(|fn_sig| {
if fn_sig.has_escaping_bound_vars() {
return fn_sig;
}
self.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(self);
let normalized_fn_sig =
ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig);
if ocx.select_all_or_error().is_empty() {
let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig);
if !normalized_fn_sig.needs_infer() {
return normalized_fn_sig;
}
}
fn_sig
})
}),
}
}

View File

@ -10,7 +10,7 @@ use rustc_hir::{
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
};
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::{self, TyCtxtInferExt};
use rustc_infer::infer;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
@ -921,19 +921,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = self.normalize(expr.span, ty);
let ty = match self.tcx.asyncness(fn_id.owner) {
hir::IsAsync::Async => {
let infcx = self.tcx.infer_ctxt().build();
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(
fn_decl.output.span(),
"failed to get output type of async function"
)
})
}
hir::IsAsync::Async => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(fn_decl.output.span(), "failed to get output type of async function")
}),
hir::IsAsync::NotAsync => ty,
};
let ty = self.normalize(expr.span, ty);
if self.can_coerce(found, ty) {
err.multipart_suggestion(
"you might have meant to return this value",

View File

@ -1,7 +1,6 @@
use super::callee::DeferredCallResolution;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
@ -11,9 +10,7 @@ use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap;
use rustc_span::{self, Span};
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCtxt, TraitEngine, TraitEngineExt as _,
};
use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
use std::cell::RefCell;
use std::ops::Deref;
@ -92,29 +89,7 @@ impl<'tcx> Inherited<'tcx> {
infcx: tcx
.infer_ctxt()
.ignoring_regions()
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id))
.with_normalize_fn_sig_for_diagnostic(Lrc::new(move |infcx, fn_sig| {
if fn_sig.has_escaping_bound_vars() {
return fn_sig;
}
infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let normalized_fn_sig = ocx.normalize(
&ObligationCause::dummy(),
// FIXME(compiler-errors): This is probably not the right param-env...
infcx.tcx.param_env(def_id),
fn_sig,
);
if ocx.select_all_or_error().is_empty() {
let normalized_fn_sig =
infcx.resolve_vars_if_possible(normalized_fn_sig);
if !normalized_fn_sig.needs_infer() {
return normalized_fn_sig;
}
}
fn_sig
})
})),
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)),
def_id,
typeck_results: RefCell::new(ty::TypeckResults::new(hir_owner)),
}

View File

@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable};
use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitable};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// We probe again, taking all traits into account (not only those in scope).
let mut candidates =
let candidates =
match self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::AllTraits) {
// If we find a different result the caller probably forgot to import a trait.
Ok(ref new_pick) if pick.differs_from(new_pick) => {
@ -236,7 +236,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect(),
_ => Vec::new(),
};
candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id));
return Err(IllegalSizedBound(candidates, needs_mut, span));
}

View File

@ -9,7 +9,6 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def::Namespace;
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@ -1876,6 +1875,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.tcx.erase_late_bound_regions(value)
}
/// Determine if the given associated item type is relevant in the current context.
fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
match (self.mode, kind) {
(Mode::MethodCall, ty::AssocKind::Fn) => true,
(Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn) => true,
_ => false,
}
}
/// Finds the method with the appropriate name (or return type, as the case may be). If
/// `allow_similar_names` is set, find methods with close-matching names.
// The length of the returned iterator is nearly always 0 or 1 and this
@ -1888,7 +1896,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.associated_items(def_id)
.in_definition_order()
.filter(|x| {
if x.kind.namespace() != Namespace::ValueNS {
if !self.is_relevant_kind_for_mode(x.kind) {
return false;
}
match lev_distance_with_substrings(name.as_str(), x.name.as_str(), max_dist)
@ -1902,10 +1910,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} else {
self.fcx
.associated_value(def_id, name)
.filter(|x| self.is_relevant_kind_for_mode(x.kind))
.map_or_else(SmallVec::new, |x| SmallVec::from_buf([x]))
}
} else {
self.tcx.associated_items(def_id).in_definition_order().copied().collect()
self.tcx
.associated_items(def_id)
.in_definition_order()
.filter(|x| self.is_relevant_kind_for_mode(x.kind))
.copied()
.collect()
}
}
}

View File

@ -5,6 +5,7 @@ use crate::errors;
use crate::FnCtxt;
use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::StashKey;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
MultiSpan,
@ -13,6 +14,8 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::PatKind::Binding;
use rustc_hir::PathSegment;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::{
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
@ -35,11 +38,11 @@ use rustc_trait_selection::traits::{
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
};
use std::cmp::Ordering;
use std::iter;
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
use rustc_hir::intravisit::Visitor;
use std::cmp::Ordering;
use std::iter;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
@ -1462,6 +1465,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}
/// For code `rect::area(...)`,
/// if `rect` is a local variable and `area` is a valid assoc method for it,
/// we try to suggest `rect.area()`
pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
debug!("suggest_assoc_method_call segs: {:?}", segs);
let [seg1, seg2] = segs else { return; };
let Some(mut diag) =
self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
else { return };
let map = self.infcx.tcx.hir();
let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
struct LetVisitor<'a> {
result: Option<&'a hir::Expr<'a>>,
ident_name: Symbol,
}
impl<'v> Visitor<'v> for LetVisitor<'v> {
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind {
if let Binding(_, _, ident, ..) = pat.kind &&
ident.name == self.ident_name {
self.result = *init;
}
}
hir::intravisit::walk_stmt(self, ex);
}
}
let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
visitor.visit_body(&body);
let parent = self.tcx.hir().get_parent_node(seg1.hir_id);
if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
let Some(expr) = visitor.result {
let self_ty = self.node_ty(expr.hir_id);
let probe = self.lookup_probe(
seg2.ident,
self_ty,
call_expr,
ProbeScope::TraitsInScope,
);
if probe.is_ok() {
let sm = self.infcx.tcx.sess.source_map();
diag.span_suggestion_verbose(
sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
"you may have meant to call an instance method",
".".to_string(),
Applicability::MaybeIncorrect
);
}
}
diag.emit();
}
/// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
fn suggest_calling_method_on_field(
&self,

View File

@ -77,10 +77,6 @@ impl<'tcx> InferCtxt<'tcx> {
err_count_on_creation: self.err_count_on_creation,
in_snapshot: self.in_snapshot.clone(),
universe: self.universe.clone(),
normalize_fn_sig_for_diagnostic: self
.normalize_fn_sig_for_diagnostic
.as_ref()
.map(|f| f.clone()),
intercrate: self.intercrate,
}
}

View File

@ -95,6 +95,7 @@ pub mod nice_region_error;
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
pub fallback_has_occurred: bool,
}
@ -1007,22 +1008,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
fn normalize_fn_sig_for_diagnostic(&self, sig: ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> {
if let Some(normalize) = &self.normalize_fn_sig_for_diagnostic {
normalize(self, sig)
} else {
sig
}
}
/// Given two `fn` signatures highlight only sub-parts that are different.
fn cmp_fn_sig(
&self,
sig1: &ty::PolyFnSig<'tcx>,
sig2: &ty::PolyFnSig<'tcx>,
) -> (DiagnosticStyledString, DiagnosticStyledString) {
let sig1 = &self.normalize_fn_sig_for_diagnostic(*sig1);
let sig2 = &self.normalize_fn_sig_for_diagnostic(*sig2);
let sig1 = &(self.normalize_fn_sig)(*sig1);
let sig2 = &(self.normalize_fn_sig)(*sig2);
let get_lifetimes = |sig| {
use rustc_hir::def::Namespace;
@ -1262,7 +1255,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let num_display_types = consts_offset - regions_len;
for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
let i = i + regions_len;
if ta1 == ta2 {
if ta1 == ta2 && !self.tcx.sess.verbose() {
values.0.push_normal("_");
values.1.push_normal("_");
} else {
@ -1278,7 +1271,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let const_arguments = sub1.consts().zip(sub2.consts());
for (i, (ca1, ca2)) in const_arguments.enumerate() {
let i = i + consts_offset;
if ca1 == ca2 {
if ca1 == ca2 && !self.tcx.sess.verbose() {
values.0.push_normal("_");
values.1.push_normal("_");
} else {
@ -1457,7 +1450,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
_ => {
if t1 == t2 {
if t1 == t2 && !self.tcx.sess.verbose() {
// The two types are the same, elide and don't highlight.
(DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
} else {

View File

@ -80,7 +80,6 @@ pub struct InferOk<'tcx, T> {
}
pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
pub type Bound<T> = Option<T>;
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
@ -334,9 +333,6 @@ pub struct InferCtxt<'tcx> {
/// bound.
universe: Cell<ty::UniverseIndex>,
normalize_fn_sig_for_diagnostic:
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
/// During coherence we have to assume that other crates may add
/// additional impls which we currently don't know about.
///
@ -573,8 +569,6 @@ pub struct InferCtxtBuilder<'tcx> {
considering_regions: bool,
/// Whether we are in coherence mode.
intercrate: bool,
normalize_fn_sig_for_diagnostic:
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
}
pub trait TyCtxtInferExt<'tcx> {
@ -587,7 +581,6 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
considering_regions: true,
normalize_fn_sig_for_diagnostic: None,
intercrate: false,
}
}
@ -615,14 +608,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self
}
pub fn with_normalize_fn_sig_for_diagnostic(
mut self,
fun: Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>,
) -> Self {
self.normalize_fn_sig_for_diagnostic = Some(fun);
self
}
/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
@ -644,13 +629,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}
pub fn build(&mut self) -> InferCtxt<'tcx> {
let InferCtxtBuilder {
tcx,
defining_use_anchor,
considering_regions,
ref normalize_fn_sig_for_diagnostic,
intercrate,
} = *self;
let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self;
InferCtxt {
tcx,
defining_use_anchor,
@ -666,9 +645,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
in_snapshot: Cell::new(false),
skip_leak_check: Cell::new(false),
universe: Cell::new(ty::UniverseIndex::ROOT),
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
.as_ref()
.map(|f| f.clone()),
intercrate,
}
}
@ -709,7 +685,12 @@ impl<'tcx> InferCtxt<'tcx> {
/// Creates a `TypeErrCtxt` for emitting various inference errors.
/// During typeck, use `FnCtxt::err_ctxt` instead.
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
TypeErrCtxt { infcx: self, typeck_results: None, fallback_has_occurred: false }
TypeErrCtxt {
infcx: self,
typeck_results: None,
fallback_has_occurred: false,
normalize_fn_sig: Box::new(|fn_sig| fn_sig),
}
}
pub fn is_in_snapshot(&self) -> bool {

View File

@ -207,10 +207,7 @@ pub fn register_plugins<'a>(
});
}
let mut lint_store = rustc_lint::new_lint_store(
sess.opts.unstable_opts.no_interleave_lints,
sess.enable_internal_lints(),
);
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
register_lints(sess, &mut lint_store);
let registrars =

View File

@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(mir_pretty_relative_line_numbers, true);
untracked!(nll_facts, true);
untracked!(no_analysis, true);
untracked!(no_interleave_lints, true);
untracked!(no_leak_check, true);
untracked!(no_parallel_llvm, true);
untracked!(parse_only, true);

View File

@ -19,4 +19,4 @@ unicode-xid = "0.2.0"
unic-emoji-char = "0.9.0"
[dev-dependencies]
expect-test = "1.0"
expect-test = "1.4.0"

View File

@ -25,8 +25,6 @@ use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::Span;
use std::slice;
macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
$cx.pass.$f(&$cx.context, $($args),*);
}) }
@ -300,20 +298,14 @@ impl LintPass for EarlyLintPassObjects<'_> {
}
}
macro_rules! expand_early_lint_pass_impl_methods {
([$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
$(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
for obj in self.lints.iter_mut() {
obj.$name(context, $($param),*);
}
})*
)
}
macro_rules! early_lint_pass_impl {
([], [$($methods:tt)*]) => (
([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
impl EarlyLintPass for EarlyLintPassObjects<'_> {
expand_early_lint_pass_impl_methods!([$($methods)*]);
$(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
for obj in self.lints.iter_mut() {
obj.$name(context, $($param),*);
}
})*
}
)
}
@ -371,87 +363,36 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
}
}
fn early_lint_node<'a>(
sess: &Session,
warn_about_weird_lints: bool,
lint_store: &LintStore,
registered_tools: &RegisteredTools,
buffered: LintBuffer,
pass: impl EarlyLintPass,
check_node: impl EarlyCheckNode<'a>,
) -> LintBuffer {
let mut cx = EarlyContextAndPass {
context: EarlyContext::new(
sess,
warn_about_weird_lints,
lint_store,
registered_tools,
buffered,
),
pass,
};
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
cx.context.buffered
}
pub fn check_ast_node<'a>(
sess: &Session,
pre_expansion: bool,
lint_store: &LintStore,
registered_tools: &RegisteredTools,
lint_buffer: Option<LintBuffer>,
builtin_lints: impl EarlyLintPass,
builtin_lints: impl EarlyLintPass + 'static,
check_node: impl EarlyCheckNode<'a>,
) {
let passes =
if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect();
let mut buffered = lint_buffer.unwrap_or_default();
passes.push(Box::new(builtin_lints));
if sess.opts.unstable_opts.no_interleave_lints {
for (i, pass) in passes.iter_mut().enumerate() {
buffered =
sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| {
early_lint_node(
sess,
!pre_expansion && i == 0,
lint_store,
registered_tools,
buffered,
EarlyLintPassObjects { lints: slice::from_mut(pass) },
check_node,
)
});
}
} else {
buffered = early_lint_node(
let mut cx = EarlyContextAndPass {
context: EarlyContext::new(
sess,
!pre_expansion,
lint_store,
registered_tools,
buffered,
builtin_lints,
check_node,
);
if !passes.is_empty() {
buffered = early_lint_node(
sess,
false,
lint_store,
registered_tools,
buffered,
EarlyLintPassObjects { lints: &mut passes[..] },
check_node,
);
}
}
lint_buffer.unwrap_or_default(),
),
pass: EarlyLintPassObjects { lints: &mut passes[..] },
};
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
// All of the buffered lints should have been emitted at this point.
// If not, that means that we somehow buffered a lint for a node id
// that was not lint-checked (perhaps it doesn't exist?). This is a bug.
for (id, lints) in buffered.map {
for (id, lints) in cx.context.buffered.map {
for early_lint in lints {
sess.delay_span_bug(
early_lint.span,

View File

@ -28,7 +28,6 @@ use rustc_span::Span;
use std::any::Any;
use std::cell::Cell;
use std::slice;
/// Extract the `LintStore` from the query context.
/// This function exists because we've erased `LintStore` as `dyn Any` in the context.
@ -313,45 +312,42 @@ impl LintPass for LateLintPassObjects<'_, '_> {
}
}
macro_rules! expand_late_lint_pass_impl_methods {
([$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
$(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) {
for obj in self.lints.iter_mut() {
obj.$name(context, $($param),*);
}
})*
)
}
macro_rules! late_lint_pass_impl {
([], [$hir:tt], $methods:tt) => {
([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => {
impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> {
expand_late_lint_pass_impl_methods!([$hir], $methods);
$(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) {
for obj in self.lints.iter_mut() {
obj.$name(context, $($param),*);
}
})*
}
};
}
crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]);
fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
tcx: TyCtxt<'tcx>,
module_def_id: LocalDefId,
pass: T,
builtin_lints: T,
) {
let effective_visibilities = &tcx.effective_visibilities(());
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
effective_visibilities,
effective_visibilities: &tcx.effective_visibilities(()),
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id),
generics: None,
only_module: true,
};
let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
passes.push(Box::new(builtin_lints));
let pass = LateLintPassObjects { lints: &mut passes[..] };
let mut cx = LateContextAndPass { context, pass };
let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
@ -365,46 +361,29 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
}
}
pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
tcx: TyCtxt<'tcx>,
module_def_id: LocalDefId,
builtin_lints: T,
) {
if tcx.sess.opts.unstable_opts.no_interleave_lints {
// These passes runs in late_lint_crate with -Z no_interleave_lints
return;
}
late_lint_mod_pass(tcx, module_def_id, builtin_lints);
let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
if !passes.is_empty() {
late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
}
}
fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
let effective_visibilities = &tcx.effective_visibilities(());
fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
effective_visibilities,
effective_visibilities: &tcx.effective_visibilities(()),
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
generics: None,
only_module: false,
};
let mut passes =
unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
passes.push(Box::new(builtin_lints));
let pass = LateLintPassObjects { lints: &mut passes[..] };
let mut cx = LateContextAndPass { context, pass };
// Visit the whole crate.
cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
// since the root module isn't visited as an item (because it isn't an
// Since the root module isn't visited as an item (because it isn't an
// item), warn for it here.
lint_callback!(cx, check_crate,);
tcx.hir().walk_toplevel_module(cx);
@ -413,41 +392,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
})
}
fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
let mut passes =
unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
if !tcx.sess.opts.unstable_opts.no_interleave_lints {
if !passes.is_empty() {
late_lint_pass_crate(tcx, LateLintPassObjects { lints: &mut passes[..] });
}
late_lint_pass_crate(tcx, builtin_lints);
} else {
for pass in &mut passes {
tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run(
|| {
late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
},
);
}
let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
for pass in &mut passes {
tcx.sess
.prof
.verbose_generic_activity_with_arg("run_late_module_lint", pass.name())
.run(|| {
late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
});
}
}
}
/// Performs lint checking on a crate.
pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
tcx: TyCtxt<'tcx>,
builtin_lints: impl FnOnce() -> T + Send,
) {

View File

@ -127,132 +127,116 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
}
macro_rules! pre_expansion_lint_passes {
($macro:path, $args:tt) => {
$macro!($args, [KeywordIdents: KeywordIdents,]);
};
}
early_lint_methods!(
declare_combined_early_lint_pass,
[
pub BuiltinCombinedPreExpansionLintPass,
[
KeywordIdents: KeywordIdents,
]
]
);
macro_rules! early_lint_passes {
($macro:path, $args:tt) => {
$macro!(
$args,
[
UnusedParens: UnusedParens,
UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode,
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
NonCamelCaseTypes: NonCamelCaseTypes,
DeprecatedAttr: DeprecatedAttr::new(),
WhileTrue: WhileTrue,
NonAsciiIdents: NonAsciiIdents,
HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
IncompleteFeatures: IncompleteFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
UnexpectedCfgs: UnexpectedCfgs,
]
);
};
}
macro_rules! declare_combined_early_pass {
([$name:ident], $passes:tt) => (
early_lint_methods!(declare_combined_early_lint_pass, [pub $name, $passes]);
)
}
pre_expansion_lint_passes!(declare_combined_early_pass, [BuiltinCombinedPreExpansionLintPass]);
early_lint_passes!(declare_combined_early_pass, [BuiltinCombinedEarlyLintPass]);
macro_rules! late_lint_passes {
($macro:path, $args:tt) => {
$macro!(
$args,
[
// Tracks state across modules
UnnameableTestItems: UnnameableTestItems::new(),
// Tracks attributes of parents
MissingDoc: MissingDoc::new(),
// Builds a global list of all impls of `Debug`.
// FIXME: Turn the computation of types which implement Debug into a query
// and change this to a module lint pass
MissingDebugImplementations: MissingDebugImplementations::default(),
// Keeps a global list of foreign declarations.
ClashingExternDeclarations: ClashingExternDeclarations::new(),
]
);
};
}
macro_rules! late_lint_mod_passes {
($macro:path, $args:tt) => {
$macro!(
$args,
[
ForLoopsOverFallibles: ForLoopsOverFallibles,
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
HardwiredLints: HardwiredLints,
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
VariantSizeDifferences: VariantSizeDifferences,
BoxPointers: BoxPointers,
PathStatements: PathStatements,
LetUnderscore: LetUnderscore,
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals,
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
UnusedAllocation: UnusedAllocation,
// Depends on types used in type definitions
MissingCopyImplementations: MissingCopyImplementations,
// Depends on referenced function signatures in expressions
MutableTransmutes: MutableTransmutes,
TypeAliasBounds: TypeAliasBounds,
TrivialConstraints: TrivialConstraints,
TypeLimits: TypeLimits::new(),
NonSnakeCase: NonSnakeCase,
InvalidNoMangleItems: InvalidNoMangleItems,
// Depends on effective visibilities
UnreachablePub: UnreachablePub,
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,
DerefNullPtr: DerefNullPtr,
// May Depend on constants elsewhere
UnusedBrokenConst: UnusedBrokenConst,
UnstableFeatures: UnstableFeatures,
ArrayIntoIter: ArrayIntoIter::default(),
DropTraitConstraints: DropTraitConstraints,
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
NonPanicFmt: NonPanicFmt,
NoopMethodCall: NoopMethodCall,
EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums,
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
]
);
};
}
macro_rules! declare_combined_late_pass {
([$v:vis $name:ident], $passes:tt) => (
late_lint_methods!(declare_combined_late_lint_pass, [$v $name, $passes], ['tcx]);
)
}
early_lint_methods!(
declare_combined_early_lint_pass,
[
pub BuiltinCombinedEarlyLintPass,
[
UnusedParens: UnusedParens,
UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode,
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
NonCamelCaseTypes: NonCamelCaseTypes,
DeprecatedAttr: DeprecatedAttr::new(),
WhileTrue: WhileTrue,
NonAsciiIdents: NonAsciiIdents,
HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
IncompleteFeatures: IncompleteFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
UnexpectedCfgs: UnexpectedCfgs,
]
]
);
// FIXME: Make a separate lint type which do not require typeck tables
late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]);
late_lint_methods!(
declare_combined_late_lint_pass,
[
pub BuiltinCombinedLateLintPass,
[
// Tracks state across modules
UnnameableTestItems: UnnameableTestItems::new(),
// Tracks attributes of parents
MissingDoc: MissingDoc::new(),
// Builds a global list of all impls of `Debug`.
// FIXME: Turn the computation of types which implement Debug into a query
// and change this to a module lint pass
MissingDebugImplementations: MissingDebugImplementations::default(),
// Keeps a global list of foreign declarations.
ClashingExternDeclarations: ClashingExternDeclarations::new(),
]
],
['tcx]
);
late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]);
late_lint_methods!(
declare_combined_late_lint_pass,
[
BuiltinCombinedModuleLateLintPass,
[
ForLoopsOverFallibles: ForLoopsOverFallibles,
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
HardwiredLints: HardwiredLints,
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
VariantSizeDifferences: VariantSizeDifferences,
BoxPointers: BoxPointers,
PathStatements: PathStatements,
LetUnderscore: LetUnderscore,
// Depends on referenced function signatures in expressions
UnusedResults: UnusedResults,
NonUpperCaseGlobals: NonUpperCaseGlobals,
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
UnusedAllocation: UnusedAllocation,
// Depends on types used in type definitions
MissingCopyImplementations: MissingCopyImplementations,
// Depends on referenced function signatures in expressions
MutableTransmutes: MutableTransmutes,
TypeAliasBounds: TypeAliasBounds,
TrivialConstraints: TrivialConstraints,
TypeLimits: TypeLimits::new(),
NonSnakeCase: NonSnakeCase,
InvalidNoMangleItems: InvalidNoMangleItems,
// Depends on effective visibilities
UnreachablePub: UnreachablePub,
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,
DerefNullPtr: DerefNullPtr,
// May Depend on constants elsewhere
UnusedBrokenConst: UnusedBrokenConst,
UnstableFeatures: UnstableFeatures,
ArrayIntoIter: ArrayIntoIter::default(),
DropTraitConstraints: DropTraitConstraints,
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
NonPanicFmt: NonPanicFmt,
NoopMethodCall: NoopMethodCall,
EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums,
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
]
],
['tcx]
);
pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintStore {
pub fn new_lint_store(internal_lints: bool) -> LintStore {
let mut lint_store = LintStore::new();
register_builtins(&mut lint_store, no_interleave_lints);
register_builtins(&mut lint_store);
if internal_lints {
register_internals(&mut lint_store);
}
@ -263,54 +247,17 @@ pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> LintSt
/// Tell the `LintStore` about all the built-in lints (the ones
/// defined in this crate and the ones defined in
/// `rustc_session::lint::builtin`).
fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
fn register_builtins(store: &mut LintStore) {
macro_rules! add_lint_group {
($name:expr, $($lint:ident),*) => (
store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]);
)
}
macro_rules! register_early_pass {
($method:ident, $ty:ident, $constructor:expr) => {
store.register_lints(&$ty::get_lints());
store.$method(|| Box::new($constructor));
};
}
macro_rules! register_late_pass {
($method:ident, $ty:ident, $constructor:expr) => {
store.register_lints(&$ty::get_lints());
store.$method(|_| Box::new($constructor));
};
}
macro_rules! register_early_passes {
($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
$(
register_early_pass!($method, $passes, $constructor);
)*
)
}
macro_rules! register_late_passes {
($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
$(
register_late_pass!($method, $passes, $constructor);
)*
)
}
if no_interleave_lints {
pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass);
early_lint_passes!(register_early_passes, register_early_pass);
late_lint_passes!(register_late_passes, register_late_pass);
late_lint_mod_passes!(register_late_passes, register_late_mod_pass);
} else {
store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
}
store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
add_lint_group!(
"nonstandard_style",

View File

@ -1,7 +1,6 @@
use crate::context::{EarlyContext, LateContext};
use rustc_ast as ast;
use rustc_data_structures::sync;
use rustc_hir as hir;
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
@ -66,16 +65,10 @@ macro_rules! late_lint_methods {
// FIXME: eliminate the duplication with `Visitor`. But this also
// contains a few lint-specific methods with no equivalent in `Visitor`.
macro_rules! expand_lint_pass_methods {
($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
$(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
)
}
macro_rules! declare_late_lint_pass {
([], [$hir:tt], [$($methods:tt)*]) => (
([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
pub trait LateLintPass<$hir>: LintPass {
expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]);
$(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})*
}
)
}
@ -175,16 +168,10 @@ macro_rules! early_lint_methods {
)
}
macro_rules! expand_early_lint_pass_methods {
($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
$(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
)
}
macro_rules! declare_early_lint_pass {
([], [$($methods:tt)*]) => (
([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
pub trait EarlyLintPass: LintPass {
expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
$(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})*
}
)
}
@ -243,5 +230,5 @@ macro_rules! declare_combined_early_lint_pass {
}
/// A lint pass boxed up as a trait object.
pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>;
pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>;
pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>;

View File

@ -222,6 +222,7 @@ fn main() {
.file("llvm-wrapper/RustWrapper.cpp")
.file("llvm-wrapper/ArchiveWrapper.cpp")
.file("llvm-wrapper/CoverageMappingWrapper.cpp")
.file("llvm-wrapper/SymbolWrapper.cpp")
.file("llvm-wrapper/Linker.cpp")
.cpp(true)
.cpp_link_stdlib(None) // we handle this below

View File

@ -1967,3 +1967,7 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
#endif
return -1;
}
extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) {
return identify_magic(StringRef(ptr, len)) == file_magic::bitcode;
}

View File

@ -0,0 +1,96 @@
// Derived from code in LLVM, which is:
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Derived from:
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ADT/Optional.h"
using namespace llvm;
using namespace llvm::sys;
using namespace llvm::object;
static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
Expected<uint32_t> SymFlagsOrErr = S.getFlags();
if (!SymFlagsOrErr)
// FIXME: Actually report errors helpfully.
report_fatal_error(SymFlagsOrErr.takeError());
if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
return false;
if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
return false;
if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
return false;
return true;
}
typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *);
typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *);
// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't
// implement getSymbolName, only printSymbolName, which is inaccessible from the C api.
extern "C" void *LLVMRustGetSymbols(
char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback,
LLVMRustGetSymbolsErrorCallback ErrorCallback) {
std::unique_ptr<MemoryBuffer> Buf =
MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"),
false);
SmallString<0> SymNameBuf;
raw_svector_ostream SymName(SymNameBuf);
// In the scenario when LLVMContext is populated SymbolicFile will contain a
// reference to it, thus SymbolicFile should be destroyed first.
LLVMContext Context;
std::unique_ptr<object::SymbolicFile> Obj;
const file_magic Type = identify_magic(Buf->getBuffer());
if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) {
return 0;
}
if (Type == file_magic::bitcode) {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
Buf->getMemBufferRef(), file_magic::bitcode, &Context);
if (!ObjOrErr) {
Error E = ObjOrErr.takeError();
SmallString<0> ErrorBuf;
raw_svector_ostream Error(ErrorBuf);
Error << E << '\0';
return ErrorCallback(Error.str().data());
}
Obj = std::move(*ObjOrErr);
} else {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef());
if (!ObjOrErr) {
Error E = ObjOrErr.takeError();
SmallString<0> ErrorBuf;
raw_svector_ostream Error(ErrorBuf);
Error << E << '\0';
return ErrorCallback(Error.str().data());
}
Obj = std::move(*ObjOrErr);
}
for (const object::BasicSymbolRef &S : Obj->symbols()) {
if (!isArchiveSymbol(S))
continue;
if (Error E = S.printName(SymName)) {
SmallString<0> ErrorBuf;
raw_svector_ostream Error(ErrorBuf);
Error << E << '\0';
return ErrorCallback(Error.str().data());
}
SymName << '\0';
if (void *E = Callback(State, SymNameBuf.str().data())) {
return E;
}
SymNameBuf.clear();
}
return 0;
}

View File

@ -29,8 +29,8 @@ impl<'a> DiagnosticDerive<'a> {
let DiagnosticDerive { mut structure, mut builder } = self;
let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
let preamble = builder.preamble(&variant);
let body = builder.body(&variant);
let preamble = builder.preamble(variant);
let body = builder.body(variant);
let diag = &builder.parent.diag;
let DiagnosticDeriveKind::Diagnostic { handler } = &builder.parent.kind else {
@ -39,7 +39,7 @@ impl<'a> DiagnosticDerive<'a> {
let init = match builder.slug.value_ref() {
None => {
span_err(builder.span, "diagnostic slug not specified")
.help(&format!(
.help(format!(
"specify the slug as the first argument to the `#[diag(...)]` \
attribute, such as `#[diag(hir_analysis_example_error)]`",
))
@ -48,10 +48,10 @@ impl<'a> DiagnosticDerive<'a> {
}
Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => {
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
.note(&format!(
.note(format!(
"slug is `{slug_name}` but the crate name is `{crate_name}`"
))
.help(&format!(
.help(format!(
"expected a slug starting with `{slug_prefix}_...`"
))
.emit();
@ -113,8 +113,8 @@ impl<'a> LintDiagnosticDerive<'a> {
let LintDiagnosticDerive { mut structure, mut builder } = self;
let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
let preamble = builder.preamble(&variant);
let body = builder.body(&variant);
let preamble = builder.preamble(variant);
let body = builder.body(variant);
let diag = &builder.parent.diag;
let formatting_init = &builder.formatting_init;
@ -128,28 +128,28 @@ impl<'a> LintDiagnosticDerive<'a> {
let msg = builder.each_variant(&mut structure, |mut builder, variant| {
// Collect the slug by generating the preamble.
let _ = builder.preamble(&variant);
let _ = builder.preamble(variant);
match builder.slug.value_ref() {
None => {
span_err(builder.span, "diagnostic slug not specified")
.help(&format!(
.help(format!(
"specify the slug as the first argument to the attribute, such as \
`#[diag(compiletest_example)]`",
))
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
DiagnosticDeriveError::ErrorHandled.to_compile_error()
}
Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => {
span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
.note(&format!(
.note(format!(
"slug is `{slug_name}` but the crate name is `{crate_name}`"
))
.help(&format!(
.help(format!(
"expected a slug starting with `{slug_prefix}_...`"
))
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
DiagnosticDeriveError::ErrorHandled.to_compile_error()
}
Some(slug) => {
quote! {

View File

@ -100,7 +100,7 @@ impl DiagnosticDeriveBuilder {
_ => variant.ast().ident.span().unwrap(),
};
let builder = DiagnosticDeriveVariantBuilder {
parent: &self,
parent: self,
span,
field_map: build_field_mapping(variant),
formatting_init: TokenStream::new(),
@ -211,7 +211,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
nested_iter.next();
}
Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| diag
Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag
.help("a diagnostic slug is required as the first argument")),
None => throw_invalid_attr!(attr, &meta, |diag| diag
.help("a diagnostic slug is required as the first argument")),
@ -227,13 +227,13 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
..
})) => (value, path),
NestedMeta::Meta(Meta::Path(_)) => {
invalid_nested_attr(attr, &nested_attr)
invalid_nested_attr(attr, nested_attr)
.help("diagnostic slug must be the first argument")
.emit();
continue;
}
_ => {
invalid_nested_attr(attr, &nested_attr).emit();
invalid_nested_attr(attr, nested_attr).emit();
continue;
}
};
@ -251,7 +251,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
});
}
_ => invalid_nested_attr(attr, &nested_attr)
_ => invalid_nested_attr(attr, nested_attr)
.help("only `code` is a valid nested attributes following the slug")
.emit(),
}
@ -427,9 +427,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
}
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
if type_matches_path(info.ty, &["rustc_span", "Span"]) {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
} else if type_is_unit(&info.ty) {
} else if type_is_unit(info.ty) {
Ok(self.add_subdiagnostic(&fn_ident, slug))
} else {
report_type_error(attr, "`Span` or `()`")?

View File

@ -409,7 +409,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
let mut code = None;
for nested_attr in list.nested.iter() {
let NestedMeta::Meta(ref meta) = nested_attr else {
throw_invalid_nested_attr!(attr, &nested_attr);
throw_invalid_nested_attr!(attr, nested_attr);
};
let span = meta.span().unwrap();
@ -427,7 +427,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
);
code.set_once((code_field, formatting_init), span);
}
_ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
_ => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
diag.help("`code` is the only valid nested attribute")
}),
}

View File

@ -80,7 +80,7 @@ fn report_error_if_not_applied_to_ty(
path: &[&str],
ty_name: &str,
) -> Result<(), DiagnosticDeriveError> {
if !type_matches_path(&info.ty, path) {
if !type_matches_path(info.ty, path) {
report_type_error(attr, ty_name)?;
}
@ -105,8 +105,8 @@ pub(crate) fn report_error_if_not_applied_to_span(
attr: &Attribute,
info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
if !type_matches_path(&info.ty, &["rustc_span", "Span"])
&& !type_matches_path(&info.ty, &["rustc_errors", "MultiSpan"])
if !type_matches_path(info.ty, &["rustc_span", "Span"])
&& !type_matches_path(info.ty, &["rustc_errors", "MultiSpan"])
{
report_type_error(attr, "`Span` or `MultiSpan`")?;
}
@ -686,7 +686,7 @@ impl SubdiagnosticKind {
let meta = match nested_attr {
NestedMeta::Meta(ref meta) => meta,
NestedMeta::Lit(_) => {
invalid_nested_attr(attr, &nested_attr).emit();
invalid_nested_attr(attr, nested_attr).emit();
continue;
}
};
@ -698,7 +698,7 @@ impl SubdiagnosticKind {
let string_value = match meta {
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value),
Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
diag.help("a diagnostic slug must be the first argument to the attribute")
}),
_ => None,
@ -720,7 +720,7 @@ impl SubdiagnosticKind {
| SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
) => {
let Some(value) = string_value else {
invalid_nested_attr(attr, &nested_attr).emit();
invalid_nested_attr(attr, nested_attr).emit();
continue;
};
@ -736,7 +736,7 @@ impl SubdiagnosticKind {
| SubdiagnosticKind::MultipartSuggestion { .. },
) => {
let Some(value) = string_value else {
invalid_nested_attr(attr, &nested_attr).emit();
invalid_nested_attr(attr, nested_attr).emit();
continue;
};
@ -752,19 +752,19 @@ impl SubdiagnosticKind {
// Invalid nested attribute
(_, SubdiagnosticKind::Suggestion { .. }) => {
invalid_nested_attr(attr, &nested_attr)
invalid_nested_attr(attr, nested_attr)
.help(
"only `style`, `code` and `applicability` are valid nested attributes",
)
.emit();
}
(_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
invalid_nested_attr(attr, &nested_attr)
invalid_nested_attr(attr, nested_attr)
.help("only `style` and `applicability` are valid nested attributes")
.emit()
}
_ => {
invalid_nested_attr(attr, &nested_attr).emit();
invalid_nested_attr(attr, nested_attr).emit();
}
}
}

View File

@ -1022,7 +1022,7 @@ impl<'hir> Map<'hir> {
..
}) => {
// Ensure that the returned span has the item's SyntaxContext.
fn_decl_span.find_ancestor_in_same_ctxt(*span).unwrap_or(*span)
fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span)
}
_ => self.span_with_body(hir_id),
};

View File

@ -100,13 +100,9 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
/// pass will be named after the type, and it will consist of a main
/// loop that goes over each available MIR and applies `run_pass`.
pub trait MirPass<'tcx> {
fn name(&self) -> Cow<'_, str> {
fn name(&self) -> &str {
let name = std::any::type_name::<Self>();
if let Some(tail) = name.rfind(':') {
Cow::from(&name[tail + 1..])
} else {
Cow::from(name)
}
if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
}
/// Returns `true` if this pass is enabled with the current combination of compiler flags.
@ -182,35 +178,6 @@ impl RuntimePhase {
}
}
impl Display for MirPhase {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
MirPhase::Built => write!(f, "built"),
MirPhase::Analysis(p) => write!(f, "analysis-{}", p),
MirPhase::Runtime(p) => write!(f, "runtime-{}", p),
}
}
}
impl Display for AnalysisPhase {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
AnalysisPhase::Initial => write!(f, "initial"),
AnalysisPhase::PostCleanup => write!(f, "post_cleanup"),
}
}
}
impl Display for RuntimePhase {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
RuntimePhase::Initial => write!(f, "initial"),
RuntimePhase::PostCleanup => write!(f, "post_cleanup"),
RuntimePhase::Optimized => write!(f, "optimized"),
}
}
}
/// Where a specific `mir::Body` comes from.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
@ -368,7 +335,7 @@ impl<'tcx> Body<'tcx> {
let mut body = Body {
phase: MirPhase::Built,
pass_count: 1,
pass_count: 0,
source,
basic_blocks: BasicBlocks::new(basic_blocks),
source_scopes,
@ -403,7 +370,7 @@ impl<'tcx> Body<'tcx> {
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
let mut body = Body {
phase: MirPhase::Built,
pass_count: 1,
pass_count: 0,
source: MirSource::item(CRATE_DEF_ID.to_def_id()),
basic_blocks: BasicBlocks::new(basic_blocks),
source_scopes: IndexVec::new(),

View File

@ -16,7 +16,6 @@ use rustc_middle::mir::interpret::{
Pointer, Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::MirSource;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::Size;
@ -74,7 +73,7 @@ pub enum PassWhere {
#[inline]
pub fn dump_mir<'tcx, F>(
tcx: TyCtxt<'tcx>,
pass_num: Option<&dyn Display>,
pass_num: bool,
pass_name: &str,
disambiguator: &dyn Display,
body: &Body<'tcx>,
@ -111,7 +110,7 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) ->
fn dump_matched_mir_node<'tcx, F>(
tcx: TyCtxt<'tcx>,
pass_num: Option<&dyn Display>,
pass_num: bool,
pass_name: &str,
disambiguator: &dyn Display,
body: &Body<'tcx>,
@ -120,8 +119,7 @@ fn dump_matched_mir_node<'tcx, F>(
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
{
let _: io::Result<()> = try {
let mut file =
create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body.source)?;
let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body)?;
// see notes on #41697 above
let def_path =
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
@ -143,16 +141,14 @@ fn dump_matched_mir_node<'tcx, F>(
if tcx.sess.opts.unstable_opts.dump_mir_graphviz {
let _: io::Result<()> = try {
let mut file =
create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body.source)?;
let mut file = create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body)?;
write_mir_fn_graphviz(tcx, body, false, &mut file)?;
};
}
if let Some(spanview) = tcx.sess.opts.unstable_opts.dump_mir_spanview {
let _: io::Result<()> = try {
let file_basename =
dump_file_basename(tcx, pass_num, pass_name, disambiguator, body.source);
let file_basename = dump_file_basename(tcx, pass_num, pass_name, disambiguator, body);
let mut file = create_dump_file_with_basename(tcx, &file_basename, "html")?;
if body.source.def_id().is_local() {
write_mir_fn_spanview(tcx, body, spanview, &file_basename, &mut file)?;
@ -165,11 +161,12 @@ fn dump_matched_mir_node<'tcx, F>(
/// where we should dump a MIR representation output files.
fn dump_file_basename<'tcx>(
tcx: TyCtxt<'tcx>,
pass_num: Option<&dyn Display>,
pass_num: bool,
pass_name: &str,
disambiguator: &dyn Display,
source: MirSource<'tcx>,
body: &Body<'tcx>,
) -> String {
let source = body.source;
let promotion_id = match source.promoted {
Some(id) => format!("-{:?}", id),
None => String::new(),
@ -178,9 +175,10 @@ fn dump_file_basename<'tcx>(
let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
String::new()
} else {
match pass_num {
None => ".-------".to_string(),
Some(pass_num) => format!(".{}", pass_num),
if pass_num {
format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
} else {
".-------".to_string()
}
};
@ -250,14 +248,14 @@ fn create_dump_file_with_basename(
pub fn create_dump_file<'tcx>(
tcx: TyCtxt<'tcx>,
extension: &str,
pass_num: Option<&dyn Display>,
pass_num: bool,
pass_name: &str,
disambiguator: &dyn Display,
source: MirSource<'tcx>,
body: &Body<'tcx>,
) -> io::Result<io::BufWriter<fs::File>> {
create_dump_file_with_basename(
tcx,
&dump_file_basename(tcx, pass_num, pass_name, disambiguator, source),
&dump_file_basename(tcx, pass_num, pass_name, disambiguator, body),
extension,
)
}

View File

@ -89,6 +89,19 @@ pub enum MirPhase {
Runtime(RuntimePhase),
}
impl MirPhase {
pub fn name(&self) -> &'static str {
match *self {
MirPhase::Built => "built",
MirPhase::Analysis(AnalysisPhase::Initial) => "analysis",
MirPhase::Analysis(AnalysisPhase::PostCleanup) => "analysis-post-cleanup",
MirPhase::Runtime(RuntimePhase::Initial) => "runtime",
MirPhase::Runtime(RuntimePhase::PostCleanup) => "runtime-post-cleanup",
MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
}
}
}
/// See [`MirPhase::Analysis`].
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable)]

View File

@ -1109,6 +1109,7 @@ rustc_queries! {
desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
feedable
}
/// Gets the span for the identifier of the definition.

View File

@ -1507,7 +1507,9 @@ impl<'tcx> TyCtxt<'tcx> {
self.def_path(def_id).to_string_no_crate_verbose()
)
}
}
impl<'tcx> TyCtxtAt<'tcx> {
/// Create a new definition within the incr. comp. engine.
pub fn create_def(
self,
@ -1536,9 +1538,13 @@ impl<'tcx> TyCtxt<'tcx> {
// - this write will have happened before these queries are called.
let def_id = self.definitions.write().create_def(parent, data);
TyCtxtFeed { tcx: self, def_id }
let feed = TyCtxtFeed { tcx: self.tcx, def_id };
feed.def_span(self.span);
feed
}
}
impl<'tcx> TyCtxt<'tcx> {
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
// Create a dependency to the red node to be sure we re-execute this when the amount of
// definitions change.

View File

@ -344,12 +344,10 @@ macro_rules! define_feedable {
match cached {
Ok(old) => {
assert_eq!(
value, old,
"Trying to feed an already recorded value for query {} key={key:?}",
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
);
return old;
}
Err(()) => (),
}

View File

@ -32,13 +32,23 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
}
impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self {
let err = tcx.ty_error();
// FIXME(compiler-errors): It would be nice if we could get the
// query key, so we could at least generate a fn signature that
// has the right arity.
let arity = if let Some(frame) = stack.get(0)
&& frame.query.name == "fn_sig"
&& let Some(def_id) = frame.query.def_id
&& let Some(node) = tcx.hir().get_if_local(def_id)
&& let Some(sig) = node.fn_sig()
{
sig.decl.inputs.len() + sig.decl.implicit_self.has_implicit_self() as usize
} else {
tcx.sess.abort_if_errors();
unreachable!()
};
let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig(
[].into_iter(),
std::iter::repeat(err).take(arity),
err,
false,
rustc_hir::Unsafety::Normal,

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