mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
commit
552b63c161
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -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"
|
||||
|
32
Cargo.lock
32
Cargo.lock
@ -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",
|
||||
|
15
LICENSES/LLVM-exception.txt
Normal file
15
LICENSES/LLVM-exception.txt
Normal 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.
|
@ -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!();
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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`.
|
||||
|
@ -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(..)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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..]
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(¶m.attrs);
|
||||
|
||||
match ¶m.kind {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
};
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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}"))
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ cfg_if! {
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &T {
|
||||
&*self.0
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -136,7 +136,7 @@ impl Translate for JsonEmitter {
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
&self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
};
|
||||
|
@ -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,
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(¶m.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 ¶m_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>>(
|
||||
|
@ -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),
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -1480,6 +1480,7 @@ impl<'a> State<'a> {
|
||||
fn_decl,
|
||||
body,
|
||||
fn_decl_span: _,
|
||||
fn_arg_span: _,
|
||||
movability: _,
|
||||
def_id: _,
|
||||
}) => {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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)),
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
) {
|
||||
|
@ -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",
|
||||
|
@ -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>;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
96
compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Normal file
96
compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Normal 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;
|
||||
}
|
@ -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! {
|
||||
|
@ -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 `()`")?
|
||||
|
@ -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")
|
||||
}),
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
};
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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(()) => (),
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user