Merge from rustc
This commit is contained in:
commit
aab3bcecb7
357 changed files with 4813 additions and 3062 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -28,7 +28,7 @@
|
|||
[submodule "src/llvm-project"]
|
||||
path = src/llvm-project
|
||||
url = https://github.com/rust-lang/llvm-project.git
|
||||
branch = rustc/15.0-2022-08-09
|
||||
branch = rustc/15.0-2022-12-07
|
||||
[submodule "src/doc/embedded-book"]
|
||||
path = src/doc/embedded-book
|
||||
url = https://github.com/rust-embedded/book.git
|
||||
|
|
|
|||
82
Cargo.lock
82
Cargo.lock
|
|
@ -581,6 +581,7 @@ dependencies = [
|
|||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
|
@ -730,6 +731,16 @@ dependencies = [
|
|||
"rustc-semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "collect-license-metadata"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"spdx-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.6.2"
|
||||
|
|
@ -1552,6 +1563,15 @@ dependencies = [
|
|||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generate-copyright"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
|
|
@ -2085,9 +2105,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.135"
|
||||
version = "0.2.138"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -4328,6 +4348,7 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"termize",
|
||||
"tracing",
|
||||
"winapi",
|
||||
]
|
||||
|
|
@ -4864,6 +4885,35 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spdx-expression"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spdx-rs"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"nom",
|
||||
"serde",
|
||||
"spdx-expression",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
|
@ -4967,6 +5017,25 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.102"
|
||||
|
|
@ -5596,6 +5665,15 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ members = [
|
|||
"src/tools/bump-stage0",
|
||||
"src/tools/replace-version-placeholder",
|
||||
"src/tools/lld-wrapper",
|
||||
"src/tools/collect-license-metadata",
|
||||
"src/tools/generate-copyright",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
|
|||
use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::StableOrd;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_Generic;
|
||||
|
|
@ -403,6 +405,11 @@ pub struct Size {
|
|||
raw: u64,
|
||||
}
|
||||
|
||||
// Safety: Ord is implement as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
#[cfg(feature = "nightly")]
|
||||
unsafe impl StableOrd for Size {}
|
||||
|
||||
// This is debug-printed a lot in larger structs, don't waste too much space there
|
||||
impl fmt::Debug for Size {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_hir::def::Res;
|
|||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
|
|
@ -147,6 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
),
|
||||
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
|
||||
*capture_clause,
|
||||
None,
|
||||
*closure_node_id,
|
||||
None,
|
||||
e.span,
|
||||
|
|
@ -435,18 +436,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let lhs = self.lower_cond(lhs);
|
||||
let rhs = self.lower_cond(rhs);
|
||||
|
||||
self.arena.alloc(self.expr(
|
||||
cond.span,
|
||||
hir::ExprKind::Binary(op, lhs, rhs),
|
||||
AttrVec::new(),
|
||||
))
|
||||
self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
|
||||
}
|
||||
ExprKind::Let(..) => self.lower_expr(cond),
|
||||
_ => {
|
||||
let cond = self.lower_expr(cond);
|
||||
let reason = DesugaringKind::CondTemporary;
|
||||
let span_block = self.mark_span_with_reason(reason, cond.span, None);
|
||||
self.expr_drop_temps(span_block, cond, AttrVec::new())
|
||||
self.expr_drop_temps(span_block, cond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -476,12 +473,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::ExprKind<'hir> {
|
||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
|
||||
let then = self.lower_block_expr(body);
|
||||
let expr_break = self.expr_break(span, AttrVec::new());
|
||||
let expr_break = self.expr_break(span);
|
||||
let stmt_break = self.stmt_expr(span, expr_break);
|
||||
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
|
||||
let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
|
||||
let else_expr = self.arena.alloc(self.expr_block(else_blk));
|
||||
let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
|
||||
let if_expr = self.expr(span, if_kind, AttrVec::new());
|
||||
let if_expr = self.expr(span, if_kind);
|
||||
let block = self.block_expr(self.arena.alloc(if_expr));
|
||||
let span = self.lower_span(span.with_hi(cond.span.hi()));
|
||||
let opt_label = self.lower_label(opt_label);
|
||||
|
|
@ -537,12 +534,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
expr: &'hir hir::Expr<'hir>,
|
||||
overall_span: Span,
|
||||
) -> &'hir hir::Expr<'hir> {
|
||||
let constructor = self.arena.alloc(self.expr_lang_item_path(
|
||||
method_span,
|
||||
lang_item,
|
||||
AttrVec::new(),
|
||||
None,
|
||||
));
|
||||
let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None));
|
||||
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
|
||||
}
|
||||
|
||||
|
|
@ -584,6 +576,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
pub(super) fn make_async_expr(
|
||||
&mut self,
|
||||
capture_clause: CaptureBy,
|
||||
outer_hir_id: Option<hir::HirId>,
|
||||
closure_node_id: NodeId,
|
||||
ret_ty: Option<hir::FnRetTy<'hir>>,
|
||||
span: Span,
|
||||
|
|
@ -592,14 +585,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::ExprKind<'hir> {
|
||||
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
||||
|
||||
// Resume argument type: `ResumeTy`
|
||||
let unstable_span =
|
||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
|
||||
// Resume argument type, which should be `&mut Context<'_>`.
|
||||
// NOTE: Using the `'static` lifetime here is technically cheating.
|
||||
// The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot
|
||||
// express the fact that we are not storing it across yield-points yet,
|
||||
// and we would thus run into lifetime errors.
|
||||
// See <https://github.com/rust-lang/rust/issues/68923>.
|
||||
// Our lowering makes sure we are not mis-using the `_task_context` input type
|
||||
// in the sense that we are indeed not using it across yield points. We
|
||||
// get a fresh `&mut Context` for each resume / call of `Future::poll`.
|
||||
// This "cheating" was previously done with a `ResumeTy` that contained a raw
|
||||
// pointer, and a `get_context` accessor that pulled the `Context` lifetimes
|
||||
// out of thin air.
|
||||
let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime);
|
||||
let context_lifetime = self.arena.alloc(hir::Lifetime {
|
||||
hir_id: self.next_id(),
|
||||
ident: context_lifetime_ident,
|
||||
res: hir::LifetimeName::Static,
|
||||
});
|
||||
let context_path =
|
||||
hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None);
|
||||
let context_ty = hir::MutTy {
|
||||
ty: self.arena.alloc(hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::Path(context_path),
|
||||
span: self.lower_span(span),
|
||||
}),
|
||||
mutbl: hir::Mutability::Mut,
|
||||
};
|
||||
let input_ty = hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::Path(resume_ty),
|
||||
span: unstable_span,
|
||||
kind: hir::TyKind::Rptr(context_lifetime, context_ty),
|
||||
span: self.lower_span(span),
|
||||
};
|
||||
|
||||
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
|
||||
|
|
@ -651,18 +668,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
hir::ExprKind::Closure(c)
|
||||
};
|
||||
let parent_has_track_caller = self
|
||||
.attrs
|
||||
.values()
|
||||
.find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some())
|
||||
.is_some();
|
||||
|
||||
let track_caller = outer_hir_id
|
||||
.and_then(|id| self.attrs.get(&id.local_id))
|
||||
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
|
||||
|
||||
let hir_id = self.lower_node_id(closure_node_id);
|
||||
let unstable_span =
|
||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||
|
||||
let hir_id = if parent_has_track_caller {
|
||||
let generator_hir_id = self.lower_node_id(closure_node_id);
|
||||
if track_caller {
|
||||
self.lower_attrs(
|
||||
generator_hir_id,
|
||||
hir_id,
|
||||
&[Attribute {
|
||||
kind: AttrKind::Normal(ptr::P(NormalAttr {
|
||||
item: AttrItem {
|
||||
|
|
@ -677,10 +693,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
span: unstable_span,
|
||||
}],
|
||||
);
|
||||
generator_hir_id
|
||||
} else {
|
||||
self.lower_node_id(closure_node_id)
|
||||
};
|
||||
}
|
||||
|
||||
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
|
||||
|
||||
|
|
@ -693,12 +706,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// E0700 in src/test/ui/self/self_lifetime-async.rs
|
||||
|
||||
// `future::identity_future`:
|
||||
let identity_future = self.expr_lang_item_path(
|
||||
unstable_span,
|
||||
hir::LangItem::IdentityFuture,
|
||||
AttrVec::new(),
|
||||
None,
|
||||
);
|
||||
let identity_future =
|
||||
self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
|
||||
|
||||
// `future::identity_future(generator)`:
|
||||
hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
|
||||
|
|
@ -710,7 +719,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
/// mut __awaitee => loop {
|
||||
/// match unsafe { ::std::future::Future::poll(
|
||||
/// <::std::pin::Pin>::new_unchecked(&mut __awaitee),
|
||||
/// ::std::future::get_context(task_context),
|
||||
/// task_context,
|
||||
/// ) } {
|
||||
/// ::std::task::Poll::Ready(result) => break result,
|
||||
/// ::std::task::Poll::Pending => {}
|
||||
|
|
@ -751,7 +760,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// unsafe {
|
||||
// ::std::future::Future::poll(
|
||||
// ::std::pin::Pin::new_unchecked(&mut __awaitee),
|
||||
// ::std::future::get_context(task_context),
|
||||
// task_context,
|
||||
// )
|
||||
// }
|
||||
let poll_expr = {
|
||||
|
|
@ -769,16 +778,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
arena_vec![self; ref_mut_awaitee],
|
||||
Some(expr_hir_id),
|
||||
);
|
||||
let get_context = self.expr_call_lang_item_fn_mut(
|
||||
gen_future_span,
|
||||
hir::LangItem::GetContext,
|
||||
arena_vec![self; task_context],
|
||||
Some(expr_hir_id),
|
||||
);
|
||||
let call = self.expr_call_lang_item_fn(
|
||||
span,
|
||||
hir::LangItem::FuturePoll,
|
||||
arena_vec![self; new_unchecked, get_context],
|
||||
arena_vec![self; new_unchecked, task_context],
|
||||
Some(expr_hir_id),
|
||||
);
|
||||
self.arena.alloc(self.expr_unsafe(call))
|
||||
|
|
@ -801,7 +804,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let break_x = self.with_loop_scope(loop_node_id, move |this| {
|
||||
let expr_break =
|
||||
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
|
||||
this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
|
||||
this.arena.alloc(this.expr(gen_future_span, expr_break))
|
||||
});
|
||||
self.arm(ready_pat, break_x)
|
||||
};
|
||||
|
|
@ -834,17 +837,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let yield_expr = self.expr(
|
||||
span,
|
||||
hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
|
||||
AttrVec::new(),
|
||||
);
|
||||
let yield_expr = self.arena.alloc(yield_expr);
|
||||
|
||||
if let Some(task_context_hid) = self.task_context {
|
||||
let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
|
||||
let assign = self.expr(
|
||||
span,
|
||||
hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
|
||||
AttrVec::new(),
|
||||
);
|
||||
let assign =
|
||||
self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));
|
||||
self.stmt_expr(span, assign)
|
||||
} else {
|
||||
// Use of `await` outside of an async context. Return `yield_expr` so that we can
|
||||
|
|
@ -1019,13 +1018,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let async_body = this.make_async_expr(
|
||||
capture_clause,
|
||||
// FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
|
||||
// can be applied on async closures as well.
|
||||
None,
|
||||
inner_closure_id,
|
||||
async_ret_ty,
|
||||
body.span,
|
||||
hir::AsyncGeneratorKind::Closure,
|
||||
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
|
||||
);
|
||||
this.expr(fn_decl_span, async_body, AttrVec::new())
|
||||
this.expr(fn_decl_span, async_body)
|
||||
});
|
||||
body_id
|
||||
});
|
||||
|
|
@ -1285,7 +1287,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let ident = self.expr_ident(lhs.span, ident, binding);
|
||||
let assign =
|
||||
hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
|
||||
let expr = self.expr(lhs.span, assign, AttrVec::new());
|
||||
let expr = self.expr(lhs.span, assign);
|
||||
assignments.push(self.stmt_expr(lhs.span, expr));
|
||||
pat
|
||||
}
|
||||
|
|
@ -1326,8 +1328,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let e2 = self.lower_expr_mut(e2);
|
||||
let fn_path =
|
||||
hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
|
||||
let fn_expr =
|
||||
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
|
||||
let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
|
||||
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
|
||||
}
|
||||
|
||||
|
|
@ -1499,8 +1500,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
// `None => break`
|
||||
let none_arm = {
|
||||
let break_expr =
|
||||
self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
|
||||
let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span));
|
||||
let pat = self.pat_none(for_span);
|
||||
self.arm(pat, break_expr)
|
||||
};
|
||||
|
|
@ -1509,7 +1509,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let some_arm = {
|
||||
let some_pat = self.pat_some(pat_span, pat);
|
||||
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
|
||||
let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
|
||||
let body_expr = self.arena.alloc(self.expr_block(body_block));
|
||||
self.arm(some_pat, body_expr)
|
||||
};
|
||||
|
||||
|
|
@ -1572,7 +1572,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// surrounding scope of the `match` since the `match` is not a terminating scope.
|
||||
//
|
||||
// Also, add the attributes to the outer returned expr node.
|
||||
self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone())
|
||||
let expr = self.expr_drop_temps_mut(for_span, match_expr);
|
||||
self.lower_attrs(expr.hir_id, &e.attrs);
|
||||
expr
|
||||
}
|
||||
|
||||
/// Desugar `ExprKind::Try` from: `<expr>?` into:
|
||||
|
|
@ -1627,12 +1629,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let continue_arm = {
|
||||
let val_ident = Ident::with_dummy_span(sym::val);
|
||||
let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
|
||||
let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
|
||||
span,
|
||||
val_ident,
|
||||
val_pat_nid,
|
||||
attrs.clone(),
|
||||
));
|
||||
let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
|
||||
self.lower_attrs(val_expr.hir_id, &attrs);
|
||||
let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
|
||||
self.arm(continue_pat, val_expr)
|
||||
};
|
||||
|
|
@ -1658,15 +1656,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::Destination { label: None, target_id },
|
||||
Some(from_residual_expr),
|
||||
),
|
||||
attrs,
|
||||
))
|
||||
} else {
|
||||
self.arena.alloc(self.expr(
|
||||
try_span,
|
||||
hir::ExprKind::Ret(Some(from_residual_expr)),
|
||||
attrs,
|
||||
))
|
||||
self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
|
||||
};
|
||||
self.lower_attrs(ret_expr.hir_id, &attrs);
|
||||
|
||||
let break_pat = self.pat_cf_break(try_span, residual_local);
|
||||
self.arm(break_pat, ret_expr)
|
||||
|
|
@ -1731,18 +1725,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
span: Span,
|
||||
expr: &'hir hir::Expr<'hir>,
|
||||
attrs: AttrVec,
|
||||
) -> &'hir hir::Expr<'hir> {
|
||||
self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
|
||||
self.arena.alloc(self.expr_drop_temps_mut(span, expr))
|
||||
}
|
||||
|
||||
pub(super) fn expr_drop_temps_mut(
|
||||
&mut self,
|
||||
span: Span,
|
||||
expr: &'hir hir::Expr<'hir>,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
|
||||
self.expr(span, hir::ExprKind::DropTemps(expr))
|
||||
}
|
||||
|
||||
fn expr_match(
|
||||
|
|
@ -1752,29 +1744,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
arms: &'hir [hir::Arm<'hir>],
|
||||
source: hir::MatchSource,
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
|
||||
self.expr(span, hir::ExprKind::Match(arg, arms, source))
|
||||
}
|
||||
|
||||
fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
|
||||
fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> {
|
||||
let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
|
||||
self.expr(span, expr_break, attrs)
|
||||
self.expr(span, expr_break)
|
||||
}
|
||||
|
||||
fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
|
||||
let expr_break = self.expr_break(span, attrs);
|
||||
fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
|
||||
let expr_break = self.expr_break(span);
|
||||
self.arena.alloc(expr_break)
|
||||
}
|
||||
|
||||
fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
|
||||
self.expr(
|
||||
span,
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
|
||||
AttrVec::new(),
|
||||
)
|
||||
self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e))
|
||||
}
|
||||
|
||||
fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
|
||||
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
|
||||
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
|
||||
}
|
||||
|
||||
fn expr_call_mut(
|
||||
|
|
@ -1783,7 +1771,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
e: &'hir hir::Expr<'hir>,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
|
||||
self.expr(span, hir::ExprKind::Call(e, args))
|
||||
}
|
||||
|
||||
fn expr_call(
|
||||
|
|
@ -1802,8 +1790,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
args: &'hir [hir::Expr<'hir>],
|
||||
hir_id: Option<hir::HirId>,
|
||||
) -> hir::Expr<'hir> {
|
||||
let path =
|
||||
self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
|
||||
let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id));
|
||||
self.expr_call_mut(span, path, args)
|
||||
}
|
||||
|
||||
|
|
@ -1821,13 +1808,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
span: Span,
|
||||
lang_item: hir::LangItem,
|
||||
attrs: AttrVec,
|
||||
hir_id: Option<hir::HirId>,
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr(
|
||||
span,
|
||||
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
|
||||
attrs,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1841,20 +1826,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
pub(super) fn expr_ident_mut(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
ident: Ident,
|
||||
binding: hir::HirId,
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
|
||||
}
|
||||
|
||||
fn expr_ident_with_attrs(
|
||||
&mut self,
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
binding: hir::HirId,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
let hir_id = self.next_id();
|
||||
let res = Res::Local(binding);
|
||||
|
|
@ -1867,7 +1842,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}),
|
||||
));
|
||||
|
||||
self.expr(span, expr_path, attrs)
|
||||
self.expr(span, expr_path)
|
||||
}
|
||||
|
||||
fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
|
||||
|
|
@ -1886,32 +1861,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}),
|
||||
None,
|
||||
),
|
||||
AttrVec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
|
||||
let blk = self.block_all(span, &[], None);
|
||||
let expr = self.expr_block(blk, AttrVec::new());
|
||||
let expr = self.expr_block(blk);
|
||||
self.arena.alloc(expr)
|
||||
}
|
||||
|
||||
pub(super) fn expr_block(
|
||||
&mut self,
|
||||
b: &'hir hir::Block<'hir>,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
|
||||
pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> {
|
||||
self.expr(b.span, hir::ExprKind::Block(b, None))
|
||||
}
|
||||
|
||||
pub(super) fn expr(
|
||||
&mut self,
|
||||
span: Span,
|
||||
kind: hir::ExprKind<'hir>,
|
||||
attrs: AttrVec,
|
||||
) -> hir::Expr<'hir> {
|
||||
pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
|
||||
let hir_id = self.next_id();
|
||||
self.lower_attrs(hir_id, &attrs);
|
||||
hir::Expr { hir_id, kind, span: self.lower_span(span) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -253,8 +253,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let asyncness = header.asyncness;
|
||||
let body_id =
|
||||
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
|
||||
let body_id = this.lower_maybe_async_body(
|
||||
span,
|
||||
hir_id,
|
||||
&decl,
|
||||
asyncness,
|
||||
body.as_deref(),
|
||||
);
|
||||
|
||||
let mut itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
||||
|
|
@ -701,6 +706,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
let hir_id = self.lower_node_id(i.id);
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let trait_item_def_id = hir_id.expect_owner();
|
||||
|
||||
let (generics, kind, has_default) = match &i.kind {
|
||||
|
|
@ -724,7 +730,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
||||
let asyncness = sig.header.asyncness;
|
||||
let body_id =
|
||||
self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
|
||||
self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body));
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
|
|
@ -759,7 +765,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
|
||||
};
|
||||
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let item = hir::TraitItem {
|
||||
owner_id: trait_item_def_id,
|
||||
ident: self.lower_ident(i.ident),
|
||||
|
|
@ -791,13 +796,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
/// Construct `ExprKind::Err` for the given `span`.
|
||||
pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
|
||||
self.expr(span, hir::ExprKind::Err, AttrVec::new())
|
||||
self.expr(span, hir::ExprKind::Err)
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||
// Since `default impl` is not yet implemented, this is always true in impls.
|
||||
let has_value = true;
|
||||
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
||||
let hir_id = self.lower_node_id(i.id);
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
|
||||
let (generics, kind) = match &i.kind {
|
||||
AssocItemKind::Const(_, ty, expr) => {
|
||||
|
|
@ -810,8 +817,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
||||
self.current_item = Some(i.span);
|
||||
let asyncness = sig.header.asyncness;
|
||||
let body_id =
|
||||
self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref());
|
||||
let body_id = self.lower_maybe_async_body(
|
||||
i.span,
|
||||
hir_id,
|
||||
&sig.decl,
|
||||
asyncness,
|
||||
body.as_deref(),
|
||||
);
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
generics,
|
||||
sig,
|
||||
|
|
@ -844,8 +856,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
|
||||
};
|
||||
|
||||
let hir_id = self.lower_node_id(i.id);
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let item = hir::ImplItem {
|
||||
owner_id: hir_id.expect_owner(),
|
||||
ident: self.lower_ident(i.ident),
|
||||
|
|
@ -978,6 +988,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn lower_maybe_async_body(
|
||||
&mut self,
|
||||
span: Span,
|
||||
fn_id: hir::HirId,
|
||||
decl: &FnDecl,
|
||||
asyncness: Async,
|
||||
body: Option<&Block>,
|
||||
|
|
@ -1128,6 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value,
|
||||
Some(fn_id),
|
||||
closure_id,
|
||||
None,
|
||||
body.span,
|
||||
|
|
@ -1139,11 +1151,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||
let desugared_span =
|
||||
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
||||
let user_body = this.expr_drop_temps(
|
||||
desugared_span,
|
||||
this.arena.alloc(user_body),
|
||||
AttrVec::new(),
|
||||
);
|
||||
let user_body =
|
||||
this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
||||
|
||||
// As noted above, create the final block like
|
||||
//
|
||||
|
|
@ -1160,14 +1169,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Some(user_body),
|
||||
);
|
||||
|
||||
this.expr_block(body, AttrVec::new())
|
||||
this.expr_block(body)
|
||||
},
|
||||
);
|
||||
|
||||
(
|
||||
this.arena.alloc_from_iter(parameters),
|
||||
this.expr(body.span, async_expr, AttrVec::new()),
|
||||
)
|
||||
(this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -259,6 +259,8 @@ enum ImplTraitContext {
|
|||
},
|
||||
/// Impl trait in type aliases.
|
||||
TypeAliasesOpaqueTy,
|
||||
/// `impl Trait` is unstably accepted in this position.
|
||||
FeatureGated(ImplTraitPosition, Symbol),
|
||||
/// `impl Trait` is not accepted in this position.
|
||||
Disallowed(ImplTraitPosition),
|
||||
}
|
||||
|
|
@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
path
|
||||
}
|
||||
ImplTraitContext::Disallowed(
|
||||
position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
|
||||
) => {
|
||||
ImplTraitContext::FeatureGated(position, feature) => {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedImplTrait {
|
||||
span: t.span,
|
||||
position: DiagnosticArgFromDisplay(&position),
|
||||
position: DiagnosticArgFromDisplay(position),
|
||||
},
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
*feature,
|
||||
)
|
||||
.emit();
|
||||
hir::TyKind::Err
|
||||
|
|
@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ImplTraitContext::Disallowed(position) => {
|
||||
self.tcx.sess.emit_err(MisplacedImplTrait {
|
||||
span: t.span,
|
||||
position: DiagnosticArgFromDisplay(&position),
|
||||
position: DiagnosticArgFromDisplay(position),
|
||||
});
|
||||
hir::TyKind::Err
|
||||
}
|
||||
|
|
@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
} else {
|
||||
match &decl.output {
|
||||
FnRetTy::Ty(ty) => {
|
||||
let mut context = if kind.return_impl_trait_allowed(self.tcx) {
|
||||
let context = if kind.return_impl_trait_allowed(self.tcx) {
|
||||
let fn_def_id = self.local_def_id(fn_node_id);
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
in_trait: matches!(kind, FnDeclKind::Trait),
|
||||
}
|
||||
} else {
|
||||
ImplTraitContext::Disallowed(match kind {
|
||||
let position = match kind {
|
||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||
unreachable!("fn should allow in-band lifetimes")
|
||||
}
|
||||
|
|
@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
||||
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
|
||||
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
||||
})
|
||||
};
|
||||
match kind {
|
||||
FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
|
||||
position,
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
),
|
||||
_ => ImplTraitContext::Disallowed(position),
|
||||
}
|
||||
};
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
|
||||
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
||||
}
|
||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
||||
}
|
||||
|
|
@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
output,
|
||||
span,
|
||||
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
|
||||
ImplTraitContext::FeatureGated(
|
||||
ImplTraitPosition::TraitReturn,
|
||||
sym::return_position_impl_trait_in_trait,
|
||||
)
|
||||
} else {
|
||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||
|
|
@ -2291,7 +2301,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// has no attributes and is not targeted by a `break`.
|
||||
fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
|
||||
let block = self.lower_block(b, false);
|
||||
self.expr_block(block, AttrVec::new())
|
||||
self.expr_block(block)
|
||||
}
|
||||
|
||||
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
|
@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
|
||||
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
|
||||
// ```
|
||||
FnRetTy::Ty(ty)
|
||||
if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
|
||||
&& self.tcx.features().impl_trait_in_fn_trait_return =>
|
||||
{
|
||||
self.lower_ty(&ty, itctx)
|
||||
FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
|
||||
if self.tcx.features().impl_trait_in_fn_trait_return {
|
||||
self.lower_ty(&ty, itctx)
|
||||
} else {
|
||||
self.lower_ty(
|
||||
&ty,
|
||||
&ImplTraitContext::FeatureGated(
|
||||
ImplTraitPosition::FnTraitReturn,
|
||||
sym::impl_trait_in_fn_trait_return,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
FnRetTy::Ty(ty) => {
|
||||
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||
|
|
|
|||
|
|
@ -348,21 +348,10 @@ impl<'a> State<'a> {
|
|||
self.head(visibility_qualified(&item.vis, "trait"));
|
||||
self.print_ident(item.ident);
|
||||
self.print_generic_params(&generics.params);
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
// FIXME(durka) this seems to be some quite outdated syntax
|
||||
for b in bounds.iter() {
|
||||
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
|
||||
self.space();
|
||||
self.word_space("for ?");
|
||||
self.print_trait_ref(&ptr.trait_ref);
|
||||
} else {
|
||||
real_bounds.push(b.clone());
|
||||
}
|
||||
}
|
||||
self.nbsp();
|
||||
if !real_bounds.is_empty() {
|
||||
if !bounds.is_empty() {
|
||||
self.word_nbsp("=");
|
||||
self.print_type_bounds(&real_bounds);
|
||||
self.print_type_bounds(&bounds);
|
||||
}
|
||||
self.print_where_clause(&generics.where_clause);
|
||||
self.word(";");
|
||||
|
|
|
|||
|
|
@ -277,8 +277,7 @@ where
|
|||
allowed_through_unstable_modules = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
|
||||
let meta = meta.as_ref().unwrap();
|
||||
else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
|
||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
handle_errors(
|
||||
|
|
@ -533,25 +532,24 @@ where
|
|||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
if let Some((ref mut stab, _)) = const_stab {
|
||||
stab.promotable = promotable;
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
|
||||
}
|
||||
}
|
||||
|
||||
if allowed_through_unstable_modules {
|
||||
if let Some((
|
||||
Stability {
|
||||
level: StabilityLevel::Stable { ref mut allowed_through_unstable_modules, .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
)) = stab
|
||||
{
|
||||
*allowed_through_unstable_modules = true;
|
||||
} else {
|
||||
sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
|
||||
match &mut stab {
|
||||
Some((
|
||||
Stability {
|
||||
level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
)) => *allowed_through_unstable_modules = true,
|
||||
_ => {
|
||||
sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -654,8 +652,8 @@ pub fn eval_condition(
|
|||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
match cfg.kind {
|
||||
ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
|
||||
match &cfg.kind {
|
||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
let (min_version, span) = match &mis[..] {
|
||||
[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||
|
|
@ -688,7 +686,7 @@ pub fn eval_condition(
|
|||
rustc_version >= min_version
|
||||
}
|
||||
}
|
||||
ast::MetaItemKind::List(ref mis) => {
|
||||
ast::MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if !mi.is_meta_item() {
|
||||
handle_errors(
|
||||
|
|
@ -759,7 +757,7 @@ pub fn eval_condition(
|
|||
sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||
true
|
||||
}
|
||||
MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
|
||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||
handle_errors(
|
||||
sess,
|
||||
lit.span,
|
||||
|
|
@ -1036,52 +1034,58 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
});
|
||||
}
|
||||
} else if let Some(meta_item) = item.meta_item() {
|
||||
if let MetaItemKind::NameValue(ref value) = meta_item.kind {
|
||||
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
|
||||
let name = meta_item.name_or_empty().to_ident_string();
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||
span: item.span(),
|
||||
repr_arg: &name,
|
||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||
item.span(),
|
||||
&value.kind,
|
||||
&name,
|
||||
),
|
||||
});
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
match &meta_item.kind {
|
||||
MetaItemKind::NameValue(value) => {
|
||||
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
|
||||
let name = meta_item.name_or_empty().to_ident_string();
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||
span: item.span(),
|
||||
repr_arg: &name,
|
||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||
item.span(),
|
||||
&value.kind,
|
||||
&name,
|
||||
),
|
||||
});
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if let MetaItemKind::List(_) = meta_item.kind {
|
||||
if meta_item.has_name(sym::align) {
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||
span: meta_item.span,
|
||||
});
|
||||
} else if meta_item.has_name(sym::packed) {
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
span: meta_item.span,
|
||||
});
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
MetaItemKind::List(_) => {
|
||||
if meta_item.has_name(sym::align) {
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||
span: meta_item.span,
|
||||
});
|
||||
} else if meta_item.has_name(sym::packed) {
|
||||
recognised = true;
|
||||
sess.emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if !recognised {
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
|||
rvalue: &mir::Rvalue<'tcx>,
|
||||
location: mir::Location,
|
||||
) {
|
||||
if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
|
||||
if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue {
|
||||
if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
|
||||
debug!("ignoring_borrow of {:?}", borrowed_place);
|
||||
return;
|
||||
|
|
@ -211,7 +211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
|||
region,
|
||||
reserve_location: location,
|
||||
activation_location: TwoPhaseActivation::NotTwoPhase,
|
||||
borrowed_place: *borrowed_place,
|
||||
borrowed_place,
|
||||
assigned_place: *assigned_place,
|
||||
};
|
||||
let (idx, _) = self.location_map.insert_full(location, borrow);
|
||||
|
|
@ -273,14 +273,14 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
|
||||
if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
|
||||
if let &mir::Rvalue::Ref(region, kind, place) = rvalue {
|
||||
// double-check that we already registered a BorrowData for this
|
||||
|
||||
let borrow_data = &self.location_map[&location];
|
||||
assert_eq!(borrow_data.reserve_location, location);
|
||||
assert_eq!(borrow_data.kind, kind);
|
||||
assert_eq!(borrow_data.region, region.to_region_vid());
|
||||
assert_eq!(borrow_data.borrowed_place, *place);
|
||||
assert_eq!(borrow_data.borrowed_place, place);
|
||||
}
|
||||
|
||||
self.super_rvalue(rvalue, location)
|
||||
|
|
|
|||
|
|
@ -358,9 +358,9 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
stmt: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
match stmt.kind {
|
||||
mir::StatementKind::Assign(box (lhs, ref rhs)) => {
|
||||
if let mir::Rvalue::Ref(_, _, place) = *rhs {
|
||||
match &stmt.kind {
|
||||
mir::StatementKind::Assign(box (lhs, rhs)) => {
|
||||
if let mir::Rvalue::Ref(_, _, place) = rhs {
|
||||
if place.ignore_borrow(
|
||||
self.tcx,
|
||||
self.body,
|
||||
|
|
@ -377,13 +377,13 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
|||
|
||||
// Make sure there are no remaining borrows for variables
|
||||
// that are assigned over.
|
||||
self.kill_borrows_on_place(trans, lhs);
|
||||
self.kill_borrows_on_place(trans, *lhs);
|
||||
}
|
||||
|
||||
mir::StatementKind::StorageDead(local) => {
|
||||
// Make sure there are no remaining borrows for locals that
|
||||
// are gone out of scope.
|
||||
self.kill_borrows_on_place(trans, Place::from(local));
|
||||
self.kill_borrows_on_place(trans, Place::from(*local));
|
||||
}
|
||||
|
||||
mir::StatementKind::FakeRead(..)
|
||||
|
|
|
|||
|
|
@ -243,9 +243,9 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
|||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
let (ref infcx, key, _) =
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_prove_predicate_with_cause(&ocx, key, cause);
|
||||
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
|
||||
}
|
||||
|
|
@ -284,9 +284,9 @@ where
|
|||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
let (ref infcx, key, _) =
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// FIXME(lqd): Unify and de-duplicate the following with the actual
|
||||
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
|
||||
|
|
@ -328,9 +328,9 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||
let (ref infcx, key, _) =
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
|
||||
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
|
||||
);
|
||||
let note_msg = match opt_name {
|
||||
Some(ref name) => format!("`{}`", name),
|
||||
Some(name) => format!("`{}`", name),
|
||||
None => "value".to_owned(),
|
||||
};
|
||||
if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg) {
|
||||
|
|
@ -1417,7 +1417,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// then just use the normal error. The closure isn't escaping
|
||||
// and `move` will not help here.
|
||||
(
|
||||
Some(ref name),
|
||||
Some(name),
|
||||
BorrowExplanation::MustBeValidFor {
|
||||
category:
|
||||
category @ (ConstraintCategory::Return(_)
|
||||
|
|
@ -1438,7 +1438,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&format!("`{}`", name),
|
||||
),
|
||||
(
|
||||
ref name,
|
||||
name,
|
||||
BorrowExplanation::MustBeValidFor {
|
||||
category: ConstraintCategory::Assignment,
|
||||
from_closure: false,
|
||||
|
|
@ -1450,7 +1450,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
span,
|
||||
..
|
||||
},
|
||||
) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
|
||||
) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
|
||||
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
|
||||
location,
|
||||
&name,
|
||||
|
|
@ -2452,7 +2452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// and it'll make sense.
|
||||
let location = borrow.reserve_location;
|
||||
debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
|
||||
if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) =
|
||||
if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
|
||||
&self.body[location.block].statements.get(location.statement_index)
|
||||
{
|
||||
debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
|
||||
|
|
@ -2480,8 +2480,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// Check if our `target` was captured by a closure.
|
||||
if let Rvalue::Aggregate(
|
||||
box AggregateKind::Closure(def_id, substs),
|
||||
ref operands,
|
||||
) = *rvalue
|
||||
operands,
|
||||
) = rvalue
|
||||
{
|
||||
for operand in operands {
|
||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
|
||||
|
|
@ -2505,7 +2505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// into a place then we should annotate the closure in
|
||||
// case it ends up being assigned into the return place.
|
||||
annotated_closure =
|
||||
self.annotate_fn_sig(def_id, substs.as_closure().sig());
|
||||
self.annotate_fn_sig(*def_id, substs.as_closure().sig());
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
annotated_closure={:?} assigned_from_local={:?} \
|
||||
|
|
|
|||
|
|
@ -469,8 +469,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
} else if self.was_captured_by_trait_object(borrow) {
|
||||
LaterUseKind::TraitCapture
|
||||
} else if location.statement_index == block.statements.len() {
|
||||
if let TerminatorKind::Call { ref func, from_hir_call: true, .. } =
|
||||
block.terminator().kind
|
||||
if let TerminatorKind::Call { func, from_hir_call: true, .. } =
|
||||
&block.terminator().kind
|
||||
{
|
||||
// Just point to the function, to reduce the chance of overlapping spans.
|
||||
let function_span = match func {
|
||||
|
|
@ -515,19 +515,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// will only ever have one item at any given time, but by using a vector, we can pop from
|
||||
// it which simplifies the termination logic.
|
||||
let mut queue = vec![location];
|
||||
let mut target = if let Some(&Statement {
|
||||
kind: StatementKind::Assign(box (ref place, _)),
|
||||
..
|
||||
}) = stmt
|
||||
{
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
let mut target =
|
||||
if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
|
||||
while let Some(current_location) = queue.pop() {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind {
|
||||
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
|
||||
match from {
|
||||
Operand::Copy(ref place) | Operand::Move(ref place)
|
||||
Operand::Copy(place) | Operand::Move(place)
|
||||
if target == place.local_or_deref_local() =>
|
||||
{
|
||||
target = into.local_or_deref_local()
|
||||
|
|
@ -101,7 +101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
|
||||
let closure = match args.first() {
|
||||
Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
|
||||
Some(Operand::Copy(place) | Operand::Move(place))
|
||||
if target == place.local_or_deref_local() =>
|
||||
{
|
||||
place.local_or_deref_local().unwrap()
|
||||
|
|
@ -439,9 +439,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if !is_terminator {
|
||||
continue;
|
||||
} else if let Some(Terminator {
|
||||
kind: TerminatorKind::Call { ref func, from_hir_call: false, .. },
|
||||
kind: TerminatorKind::Call { func, from_hir_call: false, .. },
|
||||
..
|
||||
}) = bbd.terminator
|
||||
}) = &bbd.terminator
|
||||
{
|
||||
if let Some(source) =
|
||||
BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
|
||||
|
|
@ -811,33 +811,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
};
|
||||
|
||||
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
|
||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
|
||||
match **kind {
|
||||
AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
|
||||
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
|
||||
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(def_id, moved_place, places)
|
||||
{
|
||||
return ClosureUse {
|
||||
generator_kind,
|
||||
args_span,
|
||||
capture_kind_span,
|
||||
path_span,
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
|
||||
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
|
||||
{
|
||||
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
|
||||
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(def_id, moved_place, places)
|
||||
{
|
||||
return ClosureUse {
|
||||
generator_kind,
|
||||
args_span,
|
||||
capture_kind_span,
|
||||
path_span,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// StatementKind::FakeRead only contains a def_id if they are introduced as a result
|
||||
// of pattern matching within a closure.
|
||||
if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
|
||||
if let StatementKind::FakeRead(box (cause, place)) = stmt.kind {
|
||||
match cause {
|
||||
FakeReadCause::ForMatchedPlace(Some(closure_def_id))
|
||||
| FakeReadCause::ForLet(Some(closure_def_id)) => {
|
||||
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
|
||||
let places = &[Operand::Move(*place)];
|
||||
let places = &[Operand::Move(place)];
|
||||
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
|
||||
self.closure_span(closure_def_id, moved_place, places)
|
||||
{
|
||||
|
|
@ -924,7 +921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
|
||||
|
||||
let target = match self.body[location.block].statements.get(location.statement_index) {
|
||||
Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => {
|
||||
Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
|
|
@ -940,9 +937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
|
||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
|
||||
stmt.kind
|
||||
{
|
||||
if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
|
||||
let (&def_id, is_generator) = match kind {
|
||||
box AggregateKind::Closure(def_id, _) => (def_id, false),
|
||||
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
|
||||
|
|
|
|||
|
|
@ -219,8 +219,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
PlaceRef {
|
||||
local,
|
||||
projection:
|
||||
&[
|
||||
ref proj_base @ ..,
|
||||
[
|
||||
proj_base @ ..,
|
||||
ProjectionElem::Deref,
|
||||
ProjectionElem::Field(field, _),
|
||||
ProjectionElem::Deref,
|
||||
|
|
@ -231,7 +231,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let Some(span) = get_mut_span_in_struct_field(
|
||||
self.infcx.tcx,
|
||||
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
|
||||
field,
|
||||
*field,
|
||||
) {
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -921,7 +921,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
hir::ExprKind::Block(blk, _) => {
|
||||
if let Some(ref expr) = blk.expr {
|
||||
if let Some(expr) = blk.expr {
|
||||
// only when the block is a closure
|
||||
if let hir::ExprKind::Closure(hir::Closure {
|
||||
capture_clause: hir::CaptureBy::Ref,
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
|
||||
|
||||
if let Some(ref value) = value {
|
||||
if let Some(value) = &value {
|
||||
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
self.consume_operand(location, op);
|
||||
}
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
|
||||
ref src,
|
||||
ref dst,
|
||||
ref count,
|
||||
src,
|
||||
dst,
|
||||
count,
|
||||
})) => {
|
||||
self.consume_operand(location, src);
|
||||
self.consume_operand(location, dst);
|
||||
|
|
@ -106,7 +106,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
self.check_activations(location);
|
||||
|
||||
match &terminator.kind {
|
||||
TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
|
||||
TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
|
||||
self.consume_operand(location, discr);
|
||||
}
|
||||
TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
|
||||
|
|
@ -119,7 +119,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
}
|
||||
TerminatorKind::DropAndReplace {
|
||||
place: drop_place,
|
||||
value: ref new_value,
|
||||
value: new_value,
|
||||
target: _,
|
||||
unwind: _,
|
||||
} => {
|
||||
|
|
@ -127,8 +127,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
self.consume_operand(location, new_value);
|
||||
}
|
||||
TerminatorKind::Call {
|
||||
ref func,
|
||||
ref args,
|
||||
func,
|
||||
args,
|
||||
destination,
|
||||
target: _,
|
||||
cleanup: _,
|
||||
|
|
@ -141,15 +141,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
}
|
||||
self.mutate_place(location, *destination, Deep);
|
||||
}
|
||||
TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
|
||||
TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
|
||||
self.consume_operand(location, cond);
|
||||
use rustc_middle::mir::AssertKind;
|
||||
if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
|
||||
if let AssertKind::BoundsCheck { len, index } = msg {
|
||||
self.consume_operand(location, len);
|
||||
self.consume_operand(location, index);
|
||||
}
|
||||
}
|
||||
TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
|
||||
TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => {
|
||||
self.consume_operand(location, value);
|
||||
|
||||
// Invalidate all borrows of local places
|
||||
|
|
@ -175,25 +175,25 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
}
|
||||
TerminatorKind::InlineAsm {
|
||||
template: _,
|
||||
ref operands,
|
||||
operands,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
destination: _,
|
||||
cleanup: _,
|
||||
} => {
|
||||
for op in operands {
|
||||
match *op {
|
||||
InlineAsmOperand::In { reg: _, ref value } => {
|
||||
match op {
|
||||
InlineAsmOperand::In { reg: _, value } => {
|
||||
self.consume_operand(location, value);
|
||||
}
|
||||
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
|
||||
if let Some(place) = place {
|
||||
if let &Some(place) = place {
|
||||
self.mutate_place(location, place, Shallow(None));
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
|
||||
InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
|
||||
self.consume_operand(location, in_value);
|
||||
if let Some(out_place) = out_place {
|
||||
if let &Some(out_place) = out_place {
|
||||
self.mutate_place(location, out_place, Shallow(None));
|
||||
}
|
||||
}
|
||||
|
|
@ -252,8 +252,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
|
||||
// Simulates consumption of an rvalue
|
||||
fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
|
||||
match *rvalue {
|
||||
Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
let access_kind = match bk {
|
||||
BorrowKind::Shallow => {
|
||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
|
|
@ -272,7 +272,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(mutability, place) => {
|
||||
&Rvalue::AddressOf(mutability, place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
|
|
@ -288,20 +288,19 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
|
||||
Rvalue::ThreadLocalRef(_) => {}
|
||||
|
||||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, operand)
|
||||
}
|
||||
Rvalue::CopyForDeref(ref place) => {
|
||||
let op = &Operand::Copy(*place);
|
||||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
|
||||
|
||||
&Rvalue::CopyForDeref(place) => {
|
||||
let op = &Operand::Copy(place);
|
||||
self.consume_operand(location, op);
|
||||
}
|
||||
|
||||
Rvalue::Len(place) | Rvalue::Discriminant(place) => {
|
||||
let af = match *rvalue {
|
||||
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
|
||||
let af = match rvalue {
|
||||
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
|
||||
Rvalue::Discriminant(..) => None,
|
||||
_ => unreachable!(),
|
||||
|
|
@ -314,15 +313,15 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
self.consume_operand(location, operand1);
|
||||
self.consume_operand(location, operand2);
|
||||
}
|
||||
|
||||
Rvalue::NullaryOp(_op, _ty) => {}
|
||||
|
||||
Rvalue::Aggregate(_, ref operands) => {
|
||||
Rvalue::Aggregate(_, operands) => {
|
||||
for operand in operands {
|
||||
self.consume_operand(location, operand);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -578,12 +578,12 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
self.check_activations(location, span, flow_state);
|
||||
|
||||
match &stmt.kind {
|
||||
StatementKind::Assign(box (lhs, ref rhs)) => {
|
||||
StatementKind::Assign(box (lhs, rhs)) => {
|
||||
self.consume_rvalue(location, (rhs, span), flow_state);
|
||||
|
||||
self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
|
||||
}
|
||||
StatementKind::FakeRead(box (_, ref place)) => {
|
||||
StatementKind::FakeRead(box (_, place)) => {
|
||||
// Read for match doesn't access any memory and is used to
|
||||
// assert that a place is safe and live. So we don't have to
|
||||
// do any checks here.
|
||||
|
|
@ -601,7 +601,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
flow_state,
|
||||
);
|
||||
}
|
||||
StatementKind::Intrinsic(box ref kind) => match kind {
|
||||
StatementKind::Intrinsic(box kind) => match kind {
|
||||
NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
|
||||
span,
|
||||
|
|
@ -643,8 +643,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
|
||||
self.check_activations(loc, span, flow_state);
|
||||
|
||||
match term.kind {
|
||||
TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
|
||||
match &term.kind {
|
||||
TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
|
||||
self.consume_operand(loc, (discr, span), flow_state);
|
||||
}
|
||||
TerminatorKind::Drop { place, target: _, unwind: _ } => {
|
||||
|
|
@ -656,7 +656,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
|
||||
self.access_place(
|
||||
loc,
|
||||
(place, span),
|
||||
(*place, span),
|
||||
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
|
||||
LocalMutationIsAllowed::Yes,
|
||||
flow_state,
|
||||
|
|
@ -664,16 +664,16 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
}
|
||||
TerminatorKind::DropAndReplace {
|
||||
place: drop_place,
|
||||
value: ref new_value,
|
||||
value: new_value,
|
||||
target: _,
|
||||
unwind: _,
|
||||
} => {
|
||||
self.mutate_place(loc, (drop_place, span), Deep, flow_state);
|
||||
self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
|
||||
self.consume_operand(loc, (new_value, span), flow_state);
|
||||
}
|
||||
TerminatorKind::Call {
|
||||
ref func,
|
||||
ref args,
|
||||
func,
|
||||
args,
|
||||
destination,
|
||||
target: _,
|
||||
cleanup: _,
|
||||
|
|
@ -684,43 +684,43 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
|
|||
for arg in args {
|
||||
self.consume_operand(loc, (arg, span), flow_state);
|
||||
}
|
||||
self.mutate_place(loc, (destination, span), Deep, flow_state);
|
||||
self.mutate_place(loc, (*destination, span), Deep, flow_state);
|
||||
}
|
||||
TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
|
||||
TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
|
||||
self.consume_operand(loc, (cond, span), flow_state);
|
||||
use rustc_middle::mir::AssertKind;
|
||||
if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
|
||||
if let AssertKind::BoundsCheck { len, index } = msg {
|
||||
self.consume_operand(loc, (len, span), flow_state);
|
||||
self.consume_operand(loc, (index, span), flow_state);
|
||||
}
|
||||
}
|
||||
|
||||
TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => {
|
||||
TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
|
||||
self.consume_operand(loc, (value, span), flow_state);
|
||||
self.mutate_place(loc, (resume_arg, span), Deep, flow_state);
|
||||
self.mutate_place(loc, (*resume_arg, span), Deep, flow_state);
|
||||
}
|
||||
|
||||
TerminatorKind::InlineAsm {
|
||||
template: _,
|
||||
ref operands,
|
||||
operands,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
destination: _,
|
||||
cleanup: _,
|
||||
} => {
|
||||
for op in operands {
|
||||
match *op {
|
||||
InlineAsmOperand::In { reg: _, ref value } => {
|
||||
match op {
|
||||
InlineAsmOperand::In { reg: _, value } => {
|
||||
self.consume_operand(loc, (value, span), flow_state);
|
||||
}
|
||||
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
|
||||
if let Some(place) = place {
|
||||
self.mutate_place(loc, (place, span), Shallow(None), flow_state);
|
||||
self.mutate_place(loc, (*place, span), Shallow(None), flow_state);
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
|
||||
InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
|
||||
self.consume_operand(loc, (in_value, span), flow_state);
|
||||
if let Some(out_place) = out_place {
|
||||
if let &Some(out_place) = out_place {
|
||||
self.mutate_place(
|
||||
loc,
|
||||
(out_place, span),
|
||||
|
|
@ -1164,8 +1164,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
match *rvalue {
|
||||
Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
let access_kind = match bk {
|
||||
BorrowKind::Shallow => {
|
||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||
|
|
@ -1203,7 +1203,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(mutability, place) => {
|
||||
&Rvalue::AddressOf(mutability, place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
|
|
@ -1232,14 +1232,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
Rvalue::ThreadLocalRef(_) => {}
|
||||
|
||||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
|
||||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, (operand, span), flow_state)
|
||||
}
|
||||
Rvalue::CopyForDeref(place) => {
|
||||
|
||||
&Rvalue::CopyForDeref(place) => {
|
||||
self.access_place(
|
||||
location,
|
||||
(place, span),
|
||||
|
|
@ -1257,7 +1258,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::Len(place) | Rvalue::Discriminant(place) => {
|
||||
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
|
||||
let af = match *rvalue {
|
||||
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
|
||||
Rvalue::Discriminant(..) => None,
|
||||
|
|
@ -1278,8 +1279,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
|
||||
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
|
||||
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
|
||||
self.consume_operand(location, (operand1, span), flow_state);
|
||||
self.consume_operand(location, (operand2, span), flow_state);
|
||||
}
|
||||
|
|
@ -1288,7 +1289,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// nullary ops take no dynamic input; no borrowck effect.
|
||||
}
|
||||
|
||||
Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
|
||||
Rvalue::Aggregate(aggregate_kind, operands) => {
|
||||
// We need to report back the list of mutable upvars that were
|
||||
// moved into the closure and subsequently used by the closure,
|
||||
// in order to populate our used_mut set.
|
||||
|
|
|
|||
|
|
@ -121,9 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
pub(super) fn prove_predicates(
|
||||
&mut self,
|
||||
predicates: impl IntoIterator<
|
||||
Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
|
||||
>,
|
||||
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
|
|
@ -135,7 +133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn prove_predicate(
|
||||
&mut self,
|
||||
predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
|
||||
predicate: impl ToPredicate<'tcx> + std::fmt::Debug,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1189,8 +1189,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
|
||||
let tcx = self.tcx();
|
||||
debug!("stmt kind: {:?}", stmt.kind);
|
||||
match stmt.kind {
|
||||
StatementKind::Assign(box (ref place, ref rv)) => {
|
||||
match &stmt.kind {
|
||||
StatementKind::Assign(box (place, rv)) => {
|
||||
// Assignments to temporaries are not "interesting";
|
||||
// they are not caused by the user, but rather artifacts
|
||||
// of lowering. Assignments to other sorts of places *are* interesting
|
||||
|
|
@ -1279,11 +1279,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
StatementKind::AscribeUserType(box (ref place, ref projection), variance) => {
|
||||
StatementKind::AscribeUserType(box (place, projection), variance) => {
|
||||
let place_ty = place.ty(body, tcx).ty;
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
place_ty,
|
||||
variance,
|
||||
*variance,
|
||||
projection,
|
||||
Locations::All(stmt.source_info.span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
|
|
@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
StatementKind::Intrinsic(box ref kind) => match kind {
|
||||
StatementKind::Intrinsic(box kind) => match kind {
|
||||
NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
|
||||
stmt.source_info.span,
|
||||
|
|
@ -1328,7 +1328,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
) {
|
||||
let tcx = self.tcx();
|
||||
debug!("terminator kind: {:?}", term.kind);
|
||||
match term.kind {
|
||||
match &term.kind {
|
||||
TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
|
|
@ -1342,7 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
// no checks needed for these
|
||||
}
|
||||
|
||||
TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => {
|
||||
TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
|
||||
let place_ty = place.ty(body, tcx).ty;
|
||||
let rv_ty = value.ty(body, tcx);
|
||||
|
||||
|
|
@ -1360,13 +1360,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
|
||||
TerminatorKind::SwitchInt { discr, switch_ty, .. } => {
|
||||
self.check_operand(discr, term_location);
|
||||
|
||||
let discr_ty = discr.ty(body, tcx);
|
||||
if let Err(terr) = self.sub_types(
|
||||
discr_ty,
|
||||
switch_ty,
|
||||
*switch_ty,
|
||||
term_location.to_locations(),
|
||||
ConstraintCategory::Assignment,
|
||||
) {
|
||||
|
|
@ -1384,14 +1384,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
// FIXME: check the values
|
||||
}
|
||||
TerminatorKind::Call {
|
||||
ref func,
|
||||
ref args,
|
||||
ref destination,
|
||||
from_hir_call,
|
||||
target,
|
||||
..
|
||||
} => {
|
||||
TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
|
||||
self.check_operand(func, term_location);
|
||||
for arg in args {
|
||||
self.check_operand(arg, term_location);
|
||||
|
|
@ -1431,7 +1424,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
ConstraintCategory::Boring,
|
||||
);
|
||||
let sig = self.normalize(sig, term_location);
|
||||
self.check_call_dest(body, term, &sig, *destination, target, term_location);
|
||||
self.check_call_dest(body, term, &sig, *destination, *target, term_location);
|
||||
|
||||
// The ordinary liveness rules will ensure that all
|
||||
// regions in the type of the callee are live here. We
|
||||
|
|
@ -1449,9 +1442,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
.add_element(region_vid, term_location);
|
||||
}
|
||||
|
||||
self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
|
||||
self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
|
||||
}
|
||||
TerminatorKind::Assert { ref cond, ref msg, .. } => {
|
||||
TerminatorKind::Assert { cond, msg, .. } => {
|
||||
self.check_operand(cond, term_location);
|
||||
|
||||
let cond_ty = cond.ty(body, tcx);
|
||||
|
|
@ -1459,7 +1452,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
|
||||
}
|
||||
|
||||
if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
|
||||
if let AssertKind::BoundsCheck { len, index } = msg {
|
||||
if len.ty(body, tcx) != tcx.types.usize {
|
||||
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
|
||||
}
|
||||
|
|
@ -1468,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::Yield { ref value, .. } => {
|
||||
TerminatorKind::Yield { value, .. } => {
|
||||
self.check_operand(value, term_location);
|
||||
|
||||
let value_ty = value.ty(body, tcx);
|
||||
|
|
@ -2630,7 +2623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
location: Location,
|
||||
) -> ty::InstantiatedPredicates<'tcx> {
|
||||
if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
|
||||
if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.borrowck_context.universal_regions,
|
||||
|
|
|
|||
|
|
@ -587,9 +587,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
|
||||
let fr_substs = match defining_ty {
|
||||
DefiningTy::Closure(_, ref substs)
|
||||
| DefiningTy::Generator(_, ref substs, _)
|
||||
| DefiningTy::InlineConst(_, ref substs) => {
|
||||
DefiningTy::Closure(_, substs)
|
||||
| DefiningTy::Generator(_, substs, _)
|
||||
| DefiningTy::InlineConst(_, substs) => {
|
||||
// In the case of closures, we rely on the fact that
|
||||
// the first N elements in the ClosureSubsts are
|
||||
// inherited from the `typeck_root_def_id`.
|
||||
|
|
|
|||
|
|
@ -17,32 +17,23 @@ pub fn expand(
|
|||
check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
|
||||
|
||||
let orig_item = item.clone();
|
||||
let not_function = || {
|
||||
ecx.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.span_err(item.span(), "alloc_error_handler must be a function");
|
||||
vec![orig_item.clone()]
|
||||
};
|
||||
|
||||
// Allow using `#[alloc_error_handler]` on an item statement
|
||||
// FIXME - if we get deref patterns, use them to reduce duplication here
|
||||
let (item, is_stmt, sig_span) = match &item {
|
||||
Annotatable::Item(item) => match item.kind {
|
||||
ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)),
|
||||
_ => return not_function(),
|
||||
},
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
StmtKind::Item(item_) => match item_.kind {
|
||||
ItemKind::Fn(ref fn_kind) => {
|
||||
(item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
||||
}
|
||||
_ => return not_function(),
|
||||
},
|
||||
_ => return not_function(),
|
||||
},
|
||||
_ => return not_function(),
|
||||
};
|
||||
let (item, is_stmt, sig_span) =
|
||||
if let Annotatable::Item(item) = &item
|
||||
&& let ItemKind::Fn(fn_kind) = &item.kind
|
||||
{
|
||||
(item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
||||
} else if let Annotatable::Stmt(stmt) = &item
|
||||
&& let StmtKind::Item(item) = &stmt.kind
|
||||
&& let ItemKind::Fn(fn_kind) = &item.kind
|
||||
{
|
||||
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
|
||||
} else {
|
||||
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
|
||||
return vec![orig_item.clone()];
|
||||
};
|
||||
|
||||
// Generate a bunch of new items using the AllocFnFactory
|
||||
let span = ecx.with_def_site_ctxt(item.span);
|
||||
|
|
|
|||
|
|
@ -191,19 +191,19 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
///
|
||||
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
|
||||
fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
|
||||
match (*expr).kind {
|
||||
ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
|
||||
match &mut expr.kind {
|
||||
ExprKind::AddrOf(_, mutability, local_expr) => {
|
||||
self.with_is_consumed_management(
|
||||
matches!(mutability, Mutability::Mut),
|
||||
|this| this.manage_cond_expr(local_expr)
|
||||
);
|
||||
}
|
||||
ExprKind::Array(ref mut local_exprs) => {
|
||||
ExprKind::Array(local_exprs) => {
|
||||
for local_expr in local_exprs {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
|
||||
ExprKind::Binary(op, lhs, rhs) => {
|
||||
self.with_is_consumed_management(
|
||||
matches!(
|
||||
op.node,
|
||||
|
|
@ -226,56 +226,56 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
}
|
||||
);
|
||||
}
|
||||
ExprKind::Call(_, ref mut local_exprs) => {
|
||||
ExprKind::Call(_, local_exprs) => {
|
||||
for local_expr in local_exprs {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Cast(ref mut local_expr, _) => {
|
||||
ExprKind::Cast(local_expr, _) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::Index(ref mut prefix, ref mut suffix) => {
|
||||
ExprKind::Index(prefix, suffix) => {
|
||||
self.manage_cond_expr(prefix);
|
||||
self.manage_cond_expr(suffix);
|
||||
}
|
||||
ExprKind::MethodCall(ref mut call) => {
|
||||
for arg in call.args.iter_mut() {
|
||||
ExprKind::MethodCall(call) => {
|
||||
for arg in &mut call.args {
|
||||
self.manage_cond_expr(arg);
|
||||
}
|
||||
}
|
||||
ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
|
||||
ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
|
||||
let path_ident = path_segment.ident;
|
||||
self.manage_initial_capture(expr, path_ident);
|
||||
}
|
||||
ExprKind::Paren(ref mut local_expr) => {
|
||||
ExprKind::Paren(local_expr) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::Range(ref mut prefix, ref mut suffix, _) => {
|
||||
if let Some(ref mut elem) = prefix {
|
||||
ExprKind::Range(prefix, suffix, _) => {
|
||||
if let Some(elem) = prefix {
|
||||
self.manage_cond_expr(elem);
|
||||
}
|
||||
if let Some(ref mut elem) = suffix {
|
||||
if let Some(elem) = suffix {
|
||||
self.manage_cond_expr(elem);
|
||||
}
|
||||
}
|
||||
ExprKind::Repeat(ref mut local_expr, ref mut elem) => {
|
||||
ExprKind::Repeat(local_expr, elem) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
self.manage_cond_expr(&mut elem.value);
|
||||
}
|
||||
ExprKind::Struct(ref mut elem) => {
|
||||
ExprKind::Struct(elem) => {
|
||||
for field in &mut elem.fields {
|
||||
self.manage_cond_expr(&mut field.expr);
|
||||
}
|
||||
if let StructRest::Base(ref mut local_expr) = elem.rest {
|
||||
if let StructRest::Base(local_expr) = &mut elem.rest {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Tup(ref mut local_exprs) => {
|
||||
ExprKind::Tup(local_exprs) => {
|
||||
for local_expr in local_exprs {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Unary(un_op, ref mut local_expr) => {
|
||||
ExprKind::Unary(un_op, local_expr) => {
|
||||
self.with_is_consumed_management(
|
||||
matches!(un_op, UnOp::Neg | UnOp::Not),
|
||||
|this| this.manage_cond_expr(local_expr)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub fn expand_concat(
|
|||
for e in es {
|
||||
match e.kind {
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => {
|
||||
Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
|
||||
accumulator.push_str(s.as_str());
|
||||
}
|
||||
Ok(ast::LitKind::Char(c)) => {
|
||||
|
|
|
|||
|
|
@ -144,8 +144,8 @@ pub fn expand_concat_bytes(
|
|||
let mut missing_literals = vec![];
|
||||
let mut has_errors = false;
|
||||
for e in es {
|
||||
match e.kind {
|
||||
ast::ExprKind::Array(ref exprs) => {
|
||||
match &e.kind {
|
||||
ast::ExprKind::Array(exprs) => {
|
||||
for expr in exprs {
|
||||
if let Some(elem) =
|
||||
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
|
||||
|
|
@ -154,7 +154,7 @@ pub fn expand_concat_bytes(
|
|||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Repeat(ref expr, ref count) => {
|
||||
ast::ExprKind::Repeat(expr, count) => {
|
||||
if let ast::ExprKind::Lit(token_lit) = count.value.kind
|
||||
&& let Ok(ast::LitKind::Int(count_val, _)) =
|
||||
ast::LitKind::from_token_lit(token_lit)
|
||||
|
|
@ -170,7 +170,7 @@ pub fn expand_concat_bytes(
|
|||
cx.span_err(count.value.span, "repeat count is not a positive number");
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
&ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
|
||||
Ok(ast::LitKind::Byte(val)) => {
|
||||
accumulator.push(val);
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ pub fn expand_concat_bytes(
|
|||
has_errors = true;
|
||||
}
|
||||
},
|
||||
ast::ExprKind::IncludedBytes(ref bytes) => {
|
||||
ast::ExprKind::IncludedBytes(bytes) => {
|
||||
accumulator.extend_from_slice(bytes);
|
||||
}
|
||||
ast::ExprKind::Err => {
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ pub fn expand_deriving_clone(
|
|||
let bounds;
|
||||
let substructure;
|
||||
let is_simple;
|
||||
match *item {
|
||||
Annotatable::Item(ref annitem) => match annitem.kind {
|
||||
ItemKind::Struct(_, Generics { ref params, .. })
|
||||
| ItemKind::Enum(_, Generics { ref params, .. }) => {
|
||||
match item {
|
||||
Annotatable::Item(annitem) => match &annitem.kind {
|
||||
ItemKind::Struct(_, Generics { params, .. })
|
||||
| ItemKind::Enum(_, Generics { params, .. }) => {
|
||||
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
|
||||
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
|
||||
if has_derive_copy
|
||||
|
|
@ -166,13 +166,13 @@ fn cs_clone(
|
|||
};
|
||||
|
||||
let vdata;
|
||||
match *substr.fields {
|
||||
Struct(vdata_, ref af) => {
|
||||
match substr.fields {
|
||||
Struct(vdata_, af) => {
|
||||
ctor_path = cx.path(trait_span, vec![substr.type_ident]);
|
||||
all_fields = af;
|
||||
vdata = vdata_;
|
||||
vdata = *vdata_;
|
||||
}
|
||||
EnumMatching(.., variant, ref af) => {
|
||||
EnumMatching(.., variant, af) => {
|
||||
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
|
||||
all_fields = af;
|
||||
vdata = &variant.data;
|
||||
|
|
|
|||
|
|
@ -78,11 +78,11 @@ fn decodable_substructure(
|
|||
let blkarg = Ident::new(sym::_d, trait_span);
|
||||
let blkdecoder = cx.expr_ident(trait_span, blkarg);
|
||||
|
||||
let expr = match *substr.fields {
|
||||
StaticStruct(_, ref summary) => {
|
||||
let nfields = match *summary {
|
||||
Unnamed(ref fields, _) => fields.len(),
|
||||
Named(ref fields) => fields.len(),
|
||||
let expr = match substr.fields {
|
||||
StaticStruct(_, summary) => {
|
||||
let nfields = match summary {
|
||||
Unnamed(fields, _) => fields.len(),
|
||||
Named(fields) => fields.len(),
|
||||
};
|
||||
let fn_read_struct_field_path: Vec<_> =
|
||||
cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]);
|
||||
|
|
@ -119,7 +119,7 @@ fn decodable_substructure(
|
|||
],
|
||||
)
|
||||
}
|
||||
StaticEnum(_, ref fields) => {
|
||||
StaticEnum(_, fields) => {
|
||||
let variant = Ident::new(sym::i, trait_span);
|
||||
|
||||
let mut arms = Vec::with_capacity(fields.len() + 1);
|
||||
|
|
@ -194,10 +194,10 @@ fn decode_static_fields<F>(
|
|||
where
|
||||
F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
|
||||
{
|
||||
match *fields {
|
||||
Unnamed(ref fields, is_tuple) => {
|
||||
match fields {
|
||||
Unnamed(fields, is_tuple) => {
|
||||
let path_expr = cx.expr_path(outer_pat_path);
|
||||
if !is_tuple {
|
||||
if !*is_tuple {
|
||||
path_expr
|
||||
} else {
|
||||
let fields = fields
|
||||
|
|
@ -209,7 +209,7 @@ where
|
|||
cx.expr_call(trait_span, path_expr, fields)
|
||||
}
|
||||
}
|
||||
Named(ref fields) => {
|
||||
Named(fields) => {
|
||||
// use the field's span to get nicer error messages.
|
||||
let fields = fields
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -62,15 +62,12 @@ fn default_struct_substructure(
|
|||
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
|
||||
|
||||
let expr = match summary {
|
||||
Unnamed(ref fields, is_tuple) => {
|
||||
if !is_tuple {
|
||||
cx.expr_ident(trait_span, substr.type_ident)
|
||||
} else {
|
||||
let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
|
||||
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
|
||||
}
|
||||
Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
|
||||
Unnamed(fields, true) => {
|
||||
let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
|
||||
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
|
||||
}
|
||||
Named(ref fields) => {
|
||||
Named(fields) => {
|
||||
let default_fields = fields
|
||||
.iter()
|
||||
.map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
|
||||
|
|
|
|||
|
|
@ -164,8 +164,8 @@ fn encodable_substructure(
|
|||
],
|
||||
));
|
||||
|
||||
match *substr.fields {
|
||||
Struct(_, ref fields) => {
|
||||
match substr.fields {
|
||||
Struct(_, fields) => {
|
||||
let fn_emit_struct_field_path =
|
||||
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
|
||||
let mut stmts = Vec::new();
|
||||
|
|
@ -224,7 +224,7 @@ fn encodable_substructure(
|
|||
BlockOrExpr::new_expr(expr)
|
||||
}
|
||||
|
||||
EnumMatching(idx, _, variant, ref fields) => {
|
||||
EnumMatching(idx, _, variant, fields) => {
|
||||
// We're not generating an AST that the borrow checker is expecting,
|
||||
// so we need to generate a unique local variable to take the
|
||||
// mutable loan out on, otherwise we get conflicts which don't
|
||||
|
|
@ -274,7 +274,7 @@ fn encodable_substructure(
|
|||
vec![
|
||||
blkencoder,
|
||||
name,
|
||||
cx.expr_usize(trait_span, idx),
|
||||
cx.expr_usize(trait_span, *idx),
|
||||
cx.expr_usize(trait_span, fields.len()),
|
||||
blk,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -369,15 +369,14 @@ fn find_type_parameters(
|
|||
|
||||
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
|
||||
fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||
if let ast::TyKind::Path(_, ref path) = ty.kind {
|
||||
if let Some(segment) = path.segments.first() {
|
||||
if self.ty_param_names.contains(&segment.ident.name) {
|
||||
self.type_params.push(TypeParameter {
|
||||
bound_generic_params: self.bound_generic_params_stack.clone(),
|
||||
ty: P(ty.clone()),
|
||||
});
|
||||
}
|
||||
}
|
||||
if let ast::TyKind::Path(_, path) = &ty.kind
|
||||
&& let Some(segment) = path.segments.first()
|
||||
&& self.ty_param_names.contains(&segment.ident.name)
|
||||
{
|
||||
self.type_params.push(TypeParameter {
|
||||
bound_generic_params: self.bound_generic_params_stack.clone(),
|
||||
ty: P(ty.clone()),
|
||||
});
|
||||
}
|
||||
|
||||
visit::walk_ty(self, ty)
|
||||
|
|
@ -428,8 +427,8 @@ impl<'a> TraitDef<'a> {
|
|||
push: &mut dyn FnMut(Annotatable),
|
||||
from_scratch: bool,
|
||||
) {
|
||||
match *item {
|
||||
Annotatable::Item(ref item) => {
|
||||
match item {
|
||||
Annotatable::Item(item) => {
|
||||
let is_packed = item.attrs.iter().any(|attr| {
|
||||
for r in attr::find_repr_attrs(&cx.sess, attr) {
|
||||
if let attr::ReprPacked(_) = r {
|
||||
|
|
@ -438,10 +437,10 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
false
|
||||
});
|
||||
let has_no_type_params = match item.kind {
|
||||
ast::ItemKind::Struct(_, ref generics)
|
||||
| ast::ItemKind::Enum(_, ref generics)
|
||||
| ast::ItemKind::Union(_, ref generics) => !generics
|
||||
let has_no_type_params = match &item.kind {
|
||||
ast::ItemKind::Struct(_, generics)
|
||||
| ast::ItemKind::Enum(_, generics)
|
||||
| ast::ItemKind::Union(_, generics) => !generics
|
||||
.params
|
||||
.iter()
|
||||
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
|
||||
|
|
@ -451,8 +450,8 @@ impl<'a> TraitDef<'a> {
|
|||
let copy_fields =
|
||||
is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
|
||||
|
||||
let newitem = match item.kind {
|
||||
ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def(
|
||||
let newitem = match &item.kind {
|
||||
ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
|
||||
cx,
|
||||
&struct_def,
|
||||
item.ident,
|
||||
|
|
@ -460,7 +459,7 @@ impl<'a> TraitDef<'a> {
|
|||
from_scratch,
|
||||
copy_fields,
|
||||
),
|
||||
ast::ItemKind::Enum(ref enum_def, ref generics) => {
|
||||
ast::ItemKind::Enum(enum_def, generics) => {
|
||||
// We ignore `is_packed` here, because `repr(packed)`
|
||||
// enums cause an error later on.
|
||||
//
|
||||
|
|
@ -468,7 +467,7 @@ impl<'a> TraitDef<'a> {
|
|||
// downstream in blatantly illegal code, so it is fine.
|
||||
self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
|
||||
}
|
||||
ast::ItemKind::Union(ref struct_def, ref generics) => {
|
||||
ast::ItemKind::Union(struct_def, generics) => {
|
||||
if self.supports_unions {
|
||||
self.expand_struct_def(
|
||||
cx,
|
||||
|
|
@ -663,12 +662,11 @@ impl<'a> TraitDef<'a> {
|
|||
|
||||
for field_ty_param in field_ty_params {
|
||||
// if we have already handled this type, skip it
|
||||
if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
|
||||
if p.segments.len() == 1
|
||||
&& ty_param_names.contains(&p.segments[0].ident.name)
|
||||
{
|
||||
continue;
|
||||
};
|
||||
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
|
||||
&& let [sole_segment] = &*p.segments
|
||||
&& ty_param_names.contains(&sole_segment.ident.name)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let mut bounds: Vec<_> = self
|
||||
.additional_bounds
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ impl Ty {
|
|||
self_ty: Ident,
|
||||
generics: &Generics,
|
||||
) -> ast::Path {
|
||||
match *self {
|
||||
match self {
|
||||
Self_ => {
|
||||
let params: Vec<_> = generics
|
||||
.params
|
||||
|
|
@ -135,7 +135,7 @@ impl Ty {
|
|||
|
||||
cx.path_all(span, false, vec![self_ty], params)
|
||||
}
|
||||
Path(ref p) => p.to_path(cx, span, self_ty, generics),
|
||||
Path(p) => p.to_path(cx, span, self_ty, generics),
|
||||
Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
|
||||
Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
|
||||
}
|
||||
|
|
@ -180,10 +180,7 @@ impl Bounds {
|
|||
let params = self
|
||||
.bounds
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let (name, ref bounds) = *t;
|
||||
mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
|
||||
})
|
||||
.map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics))
|
||||
.collect();
|
||||
|
||||
Generics {
|
||||
|
|
|
|||
|
|
@ -125,12 +125,12 @@ fn inject_impl_of_structural_trait(
|
|||
structural_path: generic::ty::Path,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
let Annotatable::Item(ref item) = *item else {
|
||||
let Annotatable::Item(item) = item else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
let generics = match item.kind {
|
||||
ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics,
|
||||
let generics = match &item.kind {
|
||||
ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
|
||||
// Do not inject `impl Structural for Union`. (`PartialEq` does not
|
||||
// support unions, so we will see error downstream.)
|
||||
ItemKind::Union(..) => return,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
|
|||
tts: TokenStream,
|
||||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
|
||||
Some(ref exprs) if exprs.is_empty() => {
|
||||
Some(exprs) if exprs.is_empty() => {
|
||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,23 +13,23 @@ pub(crate) mod printf {
|
|||
|
||||
impl<'a> Substitution<'a> {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => fmt.span,
|
||||
match self {
|
||||
Substitution::Format(fmt) => fmt.span,
|
||||
Substitution::Escape(_) => "%%",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<InnerSpan> {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => Some(fmt.position),
|
||||
Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
|
||||
match self {
|
||||
Substitution::Format(fmt) => Some(fmt.position),
|
||||
&Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, start: usize, end: usize) {
|
||||
match self {
|
||||
Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
|
||||
Substitution::Escape(ref mut pos) => *pos = (start, end),
|
||||
Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end),
|
||||
Substitution::Escape(pos) => *pos = (start, end),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ pub(crate) mod printf {
|
|||
/// This ignores cases where the substitution does not have an exact equivalent, or where
|
||||
/// the substitution would be unnecessary.
|
||||
pub fn translate(&self) -> Result<String, Option<String>> {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => fmt.translate(),
|
||||
match self {
|
||||
Substitution::Format(fmt) => fmt.translate(),
|
||||
Substitution::Escape(_) => Err(None),
|
||||
}
|
||||
}
|
||||
|
|
@ -635,23 +635,17 @@ pub mod shell {
|
|||
}
|
||||
|
||||
pub fn position(&self) -> Option<InnerSpan> {
|
||||
match self {
|
||||
Substitution::Ordinal(_, pos)
|
||||
| Substitution::Name(_, pos)
|
||||
| Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)),
|
||||
}
|
||||
let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
|
||||
Some(InnerSpan::new(pos.0, pos.1))
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, start: usize, end: usize) {
|
||||
match self {
|
||||
Substitution::Ordinal(_, ref mut pos)
|
||||
| Substitution::Name(_, ref mut pos)
|
||||
| Substitution::Escape(ref mut pos) => *pos = (start, end),
|
||||
}
|
||||
let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
|
||||
*pos = (start, end);
|
||||
}
|
||||
|
||||
pub fn translate(&self) -> Result<String, Option<String>> {
|
||||
match *self {
|
||||
match self {
|
||||
Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
|
||||
Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
|
||||
Substitution::Escape(_) => Err(None),
|
||||
|
|
|
|||
|
|
@ -20,27 +20,23 @@ pub fn expand(
|
|||
check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
|
||||
|
||||
let orig_item = item.clone();
|
||||
let not_static = || {
|
||||
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
|
||||
vec![orig_item.clone()]
|
||||
};
|
||||
|
||||
// Allow using `#[global_allocator]` on an item statement
|
||||
// FIXME - if we get deref patterns, use them to reduce duplication here
|
||||
let (item, is_stmt, ty_span) = match &item {
|
||||
Annotatable::Item(item) => match item.kind {
|
||||
ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
|
||||
_ => return not_static(),
|
||||
},
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
StmtKind::Item(item_) => match item_.kind {
|
||||
ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
|
||||
_ => return not_static(),
|
||||
},
|
||||
_ => return not_static(),
|
||||
},
|
||||
_ => return not_static(),
|
||||
};
|
||||
let (item, is_stmt, ty_span) =
|
||||
if let Annotatable::Item(item) = &item
|
||||
&& let ItemKind::Static(ty, ..) = &item.kind
|
||||
{
|
||||
(item, false, ecx.with_def_site_ctxt(ty.span))
|
||||
} else if let Annotatable::Stmt(stmt) = &item
|
||||
&& let StmtKind::Item(item) = &stmt.kind
|
||||
&& let ItemKind::Static(ty, ..) = &item.kind
|
||||
{
|
||||
(item, true, ecx.with_def_site_ctxt(ty.span))
|
||||
} else {
|
||||
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
|
||||
return vec![orig_item.clone()]
|
||||
};
|
||||
|
||||
// Generate a bunch of new items using the AllocFnFactory
|
||||
let span = ecx.with_def_site_ctxt(item.span);
|
||||
|
|
|
|||
|
|
@ -466,61 +466,67 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
|
|||
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
|
||||
let sd = &cx.sess.parse_sess.span_diagnostic;
|
||||
if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
|
||||
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
|
||||
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
|
||||
.span_label(span, "`unsafe` because of this")
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
|
||||
sd.struct_span_err(i.span, "async functions cannot be used for tests")
|
||||
.span_label(span, "`async` because of this")
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the termination trait is active, the compiler will check that the output
|
||||
// type implements the `Termination` trait as `libtest` enforces that.
|
||||
let has_output = match sig.decl.output {
|
||||
ast::FnRetTy::Default(..) => false,
|
||||
ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !sig.decl.inputs.is_empty() {
|
||||
sd.span_err(i.span, "functions used as tests can not have any arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
match (has_output, has_should_panic_attr) {
|
||||
(true, true) => {
|
||||
sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
|
||||
false
|
||||
match &i.kind {
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
|
||||
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
|
||||
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
|
||||
.span_label(span, "`unsafe` because of this")
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
(true, false) => {
|
||||
if !generics.params.is_empty() {
|
||||
sd.span_err(i.span, "functions used as tests must have signature fn() -> ()");
|
||||
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
|
||||
sd.struct_span_err(i.span, "async functions cannot be used for tests")
|
||||
.span_label(span, "`async` because of this")
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the termination trait is active, the compiler will check that the output
|
||||
// type implements the `Termination` trait as `libtest` enforces that.
|
||||
let has_output = match &sig.decl.output {
|
||||
ast::FnRetTy::Default(..) => false,
|
||||
ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !sig.decl.inputs.is_empty() {
|
||||
sd.span_err(i.span, "functions used as tests can not have any arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
match (has_output, has_should_panic_attr) {
|
||||
(true, true) => {
|
||||
sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
(true, false) => {
|
||||
if !generics.params.is_empty() {
|
||||
sd.span_err(
|
||||
i.span,
|
||||
"functions used as tests must have signature fn() -> ()",
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
(false, _) => true,
|
||||
}
|
||||
(false, _) => true,
|
||||
}
|
||||
} else {
|
||||
// should be unreachable because `is_test_fn_item` should catch all non-fn items
|
||||
false
|
||||
_ => {
|
||||
// should be unreachable because `is_test_fn_item` should catch all non-fn items
|
||||
debug_assert!(false);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
|
||||
let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
|
||||
let has_sig = match &i.kind {
|
||||
// N.B., inadequate check, but we're running
|
||||
// well before resolve, can't get too deep.
|
||||
sig.decl.inputs.len() == 1
|
||||
} else {
|
||||
false
|
||||
ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !has_sig {
|
||||
|
|
|
|||
|
|
@ -131,8 +131,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
|||
|
||||
// We don't want to recurse into anything other than mods, since
|
||||
// mods or tests inside of functions will break things
|
||||
if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind {
|
||||
let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans;
|
||||
if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
|
||||
item.kind
|
||||
{
|
||||
let prev_tests = mem::take(&mut self.tests);
|
||||
noop_visit_item_kind(&mut item.kind, self);
|
||||
self.add_test_cases(item.id, span, prev_tests);
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@ use rustc_middle::mir::mono::MonoItem;
|
|||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
|
||||
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::errors::LinkageConstOrMutType;
|
||||
use crate::type_of::LayoutGccExt;
|
||||
|
||||
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
|
|
@ -239,12 +237,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
Node::ForeignItem(&hir::ForeignItem {
|
||||
span,
|
||||
span: _,
|
||||
kind: hir::ForeignItemKind::Static(..),
|
||||
..
|
||||
}) => {
|
||||
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
check_and_apply_linkage(&self, &fn_attrs, ty, sym, span)
|
||||
check_and_apply_linkage(&self, &fn_attrs, ty, sym)
|
||||
}
|
||||
|
||||
item => bug!("get_static: expected static, found {:?}", item),
|
||||
|
|
@ -257,8 +255,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
//debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
|
||||
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
let span = self.tcx.def_span(def_id);
|
||||
let global = check_and_apply_linkage(&self, &attrs, ty, sym, span);
|
||||
let global = check_and_apply_linkage(&self, &attrs, ty, sym);
|
||||
|
||||
let needs_dll_storage_attr = false; // TODO(antoyo)
|
||||
|
||||
|
|
@ -355,24 +352,12 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
|
|||
Ok((const_alloc_to_gcc(cx, alloc), alloc))
|
||||
}
|
||||
|
||||
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
|
||||
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
|
||||
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
|
||||
let llty = cx.layout_of(ty).gcc_type(cx, true);
|
||||
if let Some(linkage) = attrs.linkage {
|
||||
// If this is a static with a linkage specified, then we need to handle
|
||||
// it a little specially. The typesystem prevents things like &T and
|
||||
// extern "C" fn() from being non-null, so we can't just declare a
|
||||
// static and call it a day. Some linkages (like weak) will make it such
|
||||
// that the static actually has a null value.
|
||||
let llty2 =
|
||||
if let ty::RawPtr(ref mt) = ty.kind() {
|
||||
cx.layout_of(mt.ty).gcc_type(cx, true)
|
||||
}
|
||||
else {
|
||||
cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
|
||||
};
|
||||
if let Some(linkage) = attrs.import_linkage {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
|
||||
let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
|
||||
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
// is initialized with the address of `foo`. If `foo` is
|
||||
|
|
|
|||
|
|
@ -211,13 +211,6 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
|
|||
pub in_elem: Ty<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_linkage_const_or_mut_type)]
|
||||
pub(crate) struct LinkageConstOrMutType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_lto_not_supported)]
|
||||
pub(crate) struct LTONotSupported;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::base;
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::debuginfo;
|
||||
use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
|
||||
use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
|
||||
use crate::llvm::{self, True};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -162,22 +162,12 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
def_id: DefId,
|
||||
) -> &'ll Value {
|
||||
let llty = cx.layout_of(ty).llvm_type(cx);
|
||||
if let Some(linkage) = attrs.linkage {
|
||||
if let Some(linkage) = attrs.import_linkage {
|
||||
debug!("get_static: sym={} linkage={:?}", sym, linkage);
|
||||
|
||||
// If this is a static with a linkage specified, then we need to handle
|
||||
// it a little specially. The typesystem prevents things like &T and
|
||||
// extern "C" fn() from being non-null, so we can't just declare a
|
||||
// static and call it a day. Some linkages (like weak) will make it such
|
||||
// that the static actually has a null value.
|
||||
let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
|
||||
cx.layout_of(mt.ty).llvm_type(cx)
|
||||
} else {
|
||||
cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
|
||||
};
|
||||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let g1 = cx.declare_global(sym, llty2);
|
||||
let g1 = cx.declare_global(sym, cx.type_i8());
|
||||
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
|
||||
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
|
|
@ -195,7 +185,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
|
||||
g2
|
||||
}
|
||||
} else if cx.tcx.sess.target.arch == "x86" &&
|
||||
|
|
|
|||
|
|
@ -61,13 +61,6 @@ pub(crate) struct InvalidMinimumAlignment {
|
|||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_linkage_const_or_mut_type)]
|
||||
pub(crate) struct LinkageConstOrMutType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ pub fn link_binary<'a>(
|
|||
sess,
|
||||
crate_type,
|
||||
outputs,
|
||||
codegen_results.crate_info.local_crate_name.as_str(),
|
||||
codegen_results.crate_info.local_crate_name,
|
||||
);
|
||||
match crate_type {
|
||||
CrateType::Rlib => {
|
||||
|
|
@ -2352,15 +2352,6 @@ fn add_native_libs_from_crate(
|
|||
&search_paths.get_or_init(|| archive_search_paths(sess)),
|
||||
);
|
||||
} else {
|
||||
// HACK/FIXME: Fixup a circular dependency between libgcc and libc
|
||||
// with glibc. This logic should be moved to the libc crate.
|
||||
if cnum != LOCAL_CRATE
|
||||
&& sess.target.os == "linux"
|
||||
&& sess.target.env == "gnu"
|
||||
&& name == "c"
|
||||
{
|
||||
cmd.link_staticlib("gcc", false);
|
||||
}
|
||||
cmd.link_staticlib(name, verbatim)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
|||
let align = ImmTy::from_uint(target_align, args[1].layout).into();
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
|
||||
|
||||
// We replace the entire entire function call with a "tail call".
|
||||
// We replace the entire function call with a "tail call".
|
||||
// Note that this happens before the frame of the original function
|
||||
// is pushed on the stack.
|
||||
self.eval_fn_call(
|
||||
|
|
|
|||
|
|
@ -676,6 +676,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
return_to_block: StackPopCleanup,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("body: {:#?}", body);
|
||||
// Clobber previous return place contents, nobody is supposed to be able to see them any more
|
||||
// This also checks dereferenceable, but not align. We rely on all constructed places being
|
||||
// sufficiently aligned (in particular we rely on `deref_operand` checking alignment).
|
||||
self.write_uninit(return_place)?;
|
||||
// first push a stack frame so we have access to the local substs
|
||||
let pre_frame = Frame {
|
||||
body,
|
||||
|
|
|
|||
|
|
@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Executes a retagging operation.
|
||||
/// Executes a retagging operation for a single pointer.
|
||||
/// Returns the possibly adjusted pointer.
|
||||
#[inline]
|
||||
fn retag(
|
||||
fn retag_ptr_value(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
val: &ImmTy<'tcx, Self::Provenance>,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
|
||||
Ok(val.clone())
|
||||
}
|
||||
|
||||
/// Executes a retagging operation on a compound value.
|
||||
/// Replaces all pointers stored in the given place.
|
||||
#[inline]
|
||||
fn retag_place_contents(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
_place: &PlaceTy<'tcx, Self::Provenance>,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::mir;
|
|||
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
|
||||
use super::{InterpCx, Machine};
|
||||
use super::{ImmTy, InterpCx, Machine};
|
||||
|
||||
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
||||
/// same type as the result.
|
||||
|
|
@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
// Stacked Borrows.
|
||||
Retag(kind, place) => {
|
||||
let dest = self.eval_place(**place)?;
|
||||
M::retag(self, *kind, &dest)?;
|
||||
M::retag_place_contents(self, *kind, &dest)?;
|
||||
}
|
||||
|
||||
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
|
||||
|
|
@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
|
||||
}
|
||||
|
||||
AddressOf(_, place) | Ref(_, _, place) => {
|
||||
Ref(_, borrow_kind, place) => {
|
||||
let src = self.eval_place(place)?;
|
||||
let place = self.force_allocation(&src)?;
|
||||
self.write_immediate(place.to_ref(self), &dest)?;
|
||||
let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
|
||||
// A fresh reference was created, make sure it gets retagged.
|
||||
let val = M::retag_ptr_value(
|
||||
self,
|
||||
if borrow_kind.allows_two_phase_borrow() {
|
||||
mir::RetagKind::TwoPhase
|
||||
} else {
|
||||
mir::RetagKind::Default
|
||||
},
|
||||
&val,
|
||||
)?;
|
||||
self.write_immediate(*val, &dest)?;
|
||||
}
|
||||
|
||||
AddressOf(_, place) => {
|
||||
// Figure out whether this is an addr_of of an already raw place.
|
||||
let place_base_raw = if place.has_deref() {
|
||||
let ty = self.frame().body.local_decls[place.local].ty;
|
||||
ty.is_unsafe_ptr()
|
||||
} else {
|
||||
// Not a deref, and thus not raw.
|
||||
false
|
||||
};
|
||||
|
||||
let src = self.eval_place(place)?;
|
||||
let place = self.force_allocation(&src)?;
|
||||
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
|
||||
if !place_base_raw {
|
||||
// If this was not already raw, it needs retagging.
|
||||
val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
|
||||
}
|
||||
self.write_immediate(*val, &dest)?;
|
||||
}
|
||||
|
||||
NullaryOp(null_op, ty) => {
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ impl stable_hasher::StableHasherResult for Fingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_via_hash!(Fingerprint);
|
||||
impl_stable_traits_for_trivial_type!(Fingerprint);
|
||||
|
||||
impl<E: Encoder> Encodable<E> for Fingerprint {
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher};
|
|||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
|
||||
use crate::fingerprint::Fingerprint;
|
||||
|
||||
mod private {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PrivateZst;
|
||||
|
|
@ -110,86 +108,5 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A helper type that you can wrap round your own type in order to automatically
|
||||
/// cache the stable hash on creation and not recompute it whenever the stable hash
|
||||
/// of the type is computed.
|
||||
/// This is only done in incremental mode. You can also opt out of caching by using
|
||||
/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
|
||||
/// This is useful if you have values that you intern but never (can?) use for stable
|
||||
/// hashing.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct WithStableHash<T> {
|
||||
pub internee: T,
|
||||
pub stable_hash: Fingerprint,
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for WithStableHash<T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.internee.eq(&other.internee)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for WithStableHash<T> {}
|
||||
|
||||
impl<T: Ord> PartialOrd for WithStableHash<T> {
|
||||
fn partial_cmp(&self, other: &WithStableHash<T>) -> Option<Ordering> {
|
||||
Some(self.internee.cmp(&other.internee))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Ord for WithStableHash<T> {
|
||||
fn cmp(&self, other: &WithStableHash<T>) -> Ordering {
|
||||
self.internee.cmp(&other.internee)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for WithStableHash<T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
&self.internee
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash> Hash for WithStableHash<T> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
if self.stable_hash != Fingerprint::ZERO {
|
||||
self.stable_hash.hash(s)
|
||||
} else {
|
||||
self.internee.hash(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithStableHash<T> {
|
||||
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
|
||||
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
|
||||
// No cached hash available. This can only mean that incremental is disabled.
|
||||
// We don't cache stable hashes in non-incremental mode, because they are used
|
||||
// so rarely that the performance actually suffers.
|
||||
|
||||
// We need to build the hash as if we cached it and then hash that hash, as
|
||||
// otherwise the hashes will differ between cached and non-cached mode.
|
||||
let stable_hash: Fingerprint = {
|
||||
let mut hasher = StableHasher::new();
|
||||
self.internee.hash_stable(hcx, &mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
|
||||
assert_eq!(
|
||||
stable_hash, self.stable_hash,
|
||||
"cached stable hash does not match freshly computed stable hash"
|
||||
);
|
||||
}
|
||||
stable_hash.hash_stable(hcx, hasher);
|
||||
} else {
|
||||
self.stable_hash.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::stable_hasher::{HashStable, StableHasher};
|
||||
use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::iter::FromIterator;
|
||||
|
|
@ -308,7 +308,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<K: HashStable<CTX>, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
|
||||
impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
|
||||
#[inline]
|
||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
||||
self.data.hash_stable(ctx, hasher);
|
||||
|
|
|
|||
|
|
@ -120,13 +120,20 @@ where
|
|||
self.items.hash(hasher)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, K, V, C> HashStable<C> for SortedIndexMultiMap<I, K, V>
|
||||
where
|
||||
K: HashStable<C>,
|
||||
V: HashStable<C>,
|
||||
{
|
||||
fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) {
|
||||
self.items.hash_stable(ctx, hasher)
|
||||
let SortedIndexMultiMap {
|
||||
items,
|
||||
// We can ignore this field because it is not observable from the outside.
|
||||
idx_sorted_by_item_key: _,
|
||||
} = self;
|
||||
|
||||
items.hash_stable(ctx, hasher)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -219,7 +219,35 @@ pub trait ToStableHashKey<HCX> {
|
|||
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
|
||||
}
|
||||
|
||||
/// Implement HashStable by just calling `Hash::hash()`.
|
||||
/// Trait for marking a type as having a sort order that is
|
||||
/// stable across compilation session boundaries. More formally:
|
||||
///
|
||||
/// ```txt
|
||||
/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2)
|
||||
/// where a2 = decode(encode(a1, context1), context2)
|
||||
/// b2 = decode(encode(b1, context1), context2)
|
||||
/// ```
|
||||
///
|
||||
/// i.e. the result of `Ord::cmp` is not influenced by encoding
|
||||
/// the values in one session and then decoding them in another
|
||||
/// session.
|
||||
///
|
||||
/// This is trivially true for types where encoding and decoding
|
||||
/// don't change the bytes of the values that are used during
|
||||
/// comparison and comparison only depends on these bytes (as
|
||||
/// opposed to some non-local state). Examples are u32, String,
|
||||
/// Path, etc.
|
||||
///
|
||||
/// But it is not true for:
|
||||
/// - `*const T` and `*mut T` because the values of these pointers
|
||||
/// will change between sessions.
|
||||
/// - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
|
||||
/// values depend on state that might be different between
|
||||
/// compilation sessions.
|
||||
pub unsafe trait StableOrd: Ord {}
|
||||
|
||||
/// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since
|
||||
/// that has the same requirements.
|
||||
///
|
||||
/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
|
||||
/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
|
||||
|
|
@ -227,7 +255,7 @@ pub trait ToStableHashKey<HCX> {
|
|||
/// here in this module.
|
||||
///
|
||||
/// Use `#[derive(HashStable_Generic)]` instead.
|
||||
macro_rules! impl_stable_hash_via_hash {
|
||||
macro_rules! impl_stable_traits_for_trivial_type {
|
||||
($t:ty) => {
|
||||
impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
|
||||
#[inline]
|
||||
|
|
@ -235,26 +263,28 @@ macro_rules! impl_stable_hash_via_hash {
|
|||
::std::hash::Hash::hash(self, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::stable_hasher::StableOrd for $t {}
|
||||
};
|
||||
}
|
||||
|
||||
impl_stable_hash_via_hash!(i8);
|
||||
impl_stable_hash_via_hash!(i16);
|
||||
impl_stable_hash_via_hash!(i32);
|
||||
impl_stable_hash_via_hash!(i64);
|
||||
impl_stable_hash_via_hash!(isize);
|
||||
impl_stable_traits_for_trivial_type!(i8);
|
||||
impl_stable_traits_for_trivial_type!(i16);
|
||||
impl_stable_traits_for_trivial_type!(i32);
|
||||
impl_stable_traits_for_trivial_type!(i64);
|
||||
impl_stable_traits_for_trivial_type!(isize);
|
||||
|
||||
impl_stable_hash_via_hash!(u8);
|
||||
impl_stable_hash_via_hash!(u16);
|
||||
impl_stable_hash_via_hash!(u32);
|
||||
impl_stable_hash_via_hash!(u64);
|
||||
impl_stable_hash_via_hash!(usize);
|
||||
impl_stable_traits_for_trivial_type!(u8);
|
||||
impl_stable_traits_for_trivial_type!(u16);
|
||||
impl_stable_traits_for_trivial_type!(u32);
|
||||
impl_stable_traits_for_trivial_type!(u64);
|
||||
impl_stable_traits_for_trivial_type!(usize);
|
||||
|
||||
impl_stable_hash_via_hash!(u128);
|
||||
impl_stable_hash_via_hash!(i128);
|
||||
impl_stable_traits_for_trivial_type!(u128);
|
||||
impl_stable_traits_for_trivial_type!(i128);
|
||||
|
||||
impl_stable_hash_via_hash!(char);
|
||||
impl_stable_hash_via_hash!(());
|
||||
impl_stable_traits_for_trivial_type!(char);
|
||||
impl_stable_traits_for_trivial_type!(());
|
||||
|
||||
impl<CTX> HashStable<CTX> for ! {
|
||||
fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
|
||||
|
|
@ -444,6 +474,10 @@ impl<CTX> HashStable<CTX> for String {
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: String comparison only depends on their contents and the
|
||||
// contents are not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for String {}
|
||||
|
||||
impl<HCX> ToStableHashKey<HCX> for String {
|
||||
type KeyType = String;
|
||||
#[inline]
|
||||
|
|
@ -459,6 +493,9 @@ impl<CTX> HashStable<CTX> for bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: sort order of bools is not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for bool {}
|
||||
|
||||
impl<T, CTX> HashStable<CTX> for Option<T>
|
||||
where
|
||||
T: HashStable<CTX>,
|
||||
|
|
@ -474,6 +511,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: the Option wrapper does not add instability to comparison.
|
||||
unsafe impl<T: StableOrd> StableOrd for Option<T> {}
|
||||
|
||||
impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
|
||||
where
|
||||
T1: HashStable<CTX>,
|
||||
|
|
@ -550,8 +590,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_via_hash!(::std::path::Path);
|
||||
impl_stable_hash_via_hash!(::std::path::PathBuf);
|
||||
impl_stable_traits_for_trivial_type!(::std::path::Path);
|
||||
impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
|
||||
|
||||
impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
|
||||
where
|
||||
|
|
@ -584,27 +624,26 @@ where
|
|||
|
||||
impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
|
||||
where
|
||||
K: ToStableHashKey<HCX>,
|
||||
K: HashStable<HCX> + StableOrd,
|
||||
V: HashStable<HCX>,
|
||||
{
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
value.hash_stable(hcx, hasher);
|
||||
});
|
||||
self.len().hash_stable(hcx, hasher);
|
||||
for entry in self.iter() {
|
||||
entry.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
|
||||
where
|
||||
K: ToStableHashKey<HCX>,
|
||||
K: HashStable<HCX> + StableOrd,
|
||||
{
|
||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
|
||||
let key = key.to_stable_hash_key(hcx);
|
||||
key.hash_stable(hcx, hasher);
|
||||
});
|
||||
self.len().hash_stable(hcx, hasher);
|
||||
for entry in self.iter() {
|
||||
entry.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst;
|
|||
use rustc_errors::registry::{InvalidErrorCode, Registry};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||
use rustc_feature::find_gated_cfg;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
|
||||
use rustc_interface::{interface, Queries};
|
||||
use rustc_lint::LintStore;
|
||||
|
|
@ -374,14 +375,14 @@ fn run_compiler(
|
|||
queries.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
let result = tcx.analysis(());
|
||||
if sess.opts.unstable_opts.save_analysis {
|
||||
let crate_name = queries.crate_name()?.peek().clone();
|
||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||
sess.time("save_analysis", || {
|
||||
save::process_crate(
|
||||
tcx,
|
||||
&crate_name,
|
||||
crate_name,
|
||||
compiler.input(),
|
||||
None,
|
||||
DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
|
||||
DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -678,7 +679,7 @@ fn print_crate_info(
|
|||
let crate_types = collect_crate_types(sess, attrs);
|
||||
for &style in &crate_types {
|
||||
let fname =
|
||||
rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
|
||||
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
|
||||
println!("{}", fname.file_name().unwrap().to_string_lossy());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -494,6 +494,7 @@ E0786: include_str!("./error_codes/E0786.md"),
|
|||
E0787: include_str!("./error_codes/E0787.md"),
|
||||
E0788: include_str!("./error_codes/E0788.md"),
|
||||
E0790: include_str!("./error_codes/E0790.md"),
|
||||
E0791: include_str!("./error_codes/E0791.md"),
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
|
|
|
|||
41
compiler/rustc_error_codes/src/error_codes/E0791.md
Normal file
41
compiler/rustc_error_codes/src/error_codes/E0791.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
Static variables with the `#[linkage]` attribute within external blocks
|
||||
must have one of the following types, which are equivalent to a nullable
|
||||
pointer in C:
|
||||
|
||||
* `*mut T` or `*const T`, where `T` may be any type.
|
||||
|
||||
* An enumerator type with no `#[repr]` attribute and with two variants, where
|
||||
one of the variants has no fields, and the other has a single field of one of
|
||||
the following non-nullable types:
|
||||
* Reference type
|
||||
* Function pointer type
|
||||
|
||||
The variants can appear in either order.
|
||||
|
||||
For example, the following declaration is invalid:
|
||||
|
||||
```compile_fail,E0791
|
||||
#![feature(linkage)]
|
||||
|
||||
extern "C" {
|
||||
#[linkage = "extern_weak"]
|
||||
static foo: i8;
|
||||
}
|
||||
```
|
||||
|
||||
The following declarations are valid:
|
||||
|
||||
```
|
||||
#![feature(linkage)]
|
||||
|
||||
extern "C" {
|
||||
#[linkage = "extern_weak"]
|
||||
static foo: Option<unsafe extern "C" fn()>;
|
||||
|
||||
#[linkage = "extern_weak"]
|
||||
static bar: Option<&'static i8>;
|
||||
|
||||
#[linkage = "extern_weak"]
|
||||
static baz: *mut i8;
|
||||
}
|
||||
```
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
codegen_gcc_linkage_const_or_mut_type =
|
||||
must have type `*const T` or `*mut T` due to `#[linkage]` attribute
|
||||
|
||||
codegen_gcc_unwinding_inline_asm =
|
||||
GCC backend does not support unwinding from inline asm
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ codegen_llvm_branch_protection_requires_aarch64 =
|
|||
codegen_llvm_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_llvm_linkage_const_or_mut_type =
|
||||
must have type `*const T` or `*mut T` due to `#[linkage]` attribute
|
||||
|
||||
codegen_llvm_sanitizer_memtag_requires_mte =
|
||||
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
|
|||
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
|
||||
.label = lifetimes do not match {$item_kind} in trait
|
||||
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
|
||||
.where_label = this `where` clause might not match the one in the trait
|
||||
.bounds_label = this bound might be missing in the impl
|
||||
|
||||
hir_analysis_drop_impl_on_wrong_item =
|
||||
the `Drop` trait may only be implemented for local structs, enums, and unions
|
||||
|
|
@ -113,3 +115,6 @@ hir_analysis_const_bound_for_non_const_trait =
|
|||
hir_analysis_self_in_impl_self =
|
||||
`Self` is not valid in the self type of an impl block
|
||||
.note = replace `Self` with a different type
|
||||
|
||||
hir_analysis_linkage_type =
|
||||
invalid type for variable with `#[linkage]` attribute
|
||||
|
|
|
|||
|
|
@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
|
|||
|
||||
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
|
||||
.label = identifiers cannot start with a number
|
||||
|
||||
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
|
||||
.suggestion = replace `fn` with `impl` here
|
||||
|
|
|
|||
|
|
@ -960,7 +960,7 @@ pub trait LintStoreExpand {
|
|||
node_id: NodeId,
|
||||
attrs: &[Attribute],
|
||||
items: &[P<Item>],
|
||||
name: &str,
|
||||
name: Symbol,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1122,7 +1122,7 @@ impl InvocationCollectorNode for P<ast::Item> {
|
|||
ecx.current_expansion.lint_node_id,
|
||||
&attrs,
|
||||
&items,
|
||||
ident.name.as_str(),
|
||||
ident.name,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> {
|
|||
pub struct OwnerNodes<'tcx> {
|
||||
/// Pre-computed hash of the full HIR.
|
||||
pub hash_including_bodies: Fingerprint,
|
||||
/// Pre-computed hash of the item signature, sithout recursing into the body.
|
||||
/// Pre-computed hash of the item signature, without recursing into the body.
|
||||
pub hash_without_bodies: Fingerprint,
|
||||
/// Full HIR for the current owner.
|
||||
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
|
||||
use rustc_span::{def_id::DefPathHash, HashStableContext};
|
||||
use std::fmt;
|
||||
|
||||
|
|
@ -146,6 +146,10 @@ impl ItemLocalId {
|
|||
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
|
||||
}
|
||||
|
||||
// Safety: Ord is implement as just comparing the LocalItemId's numerical
|
||||
// values and these are not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for ItemLocalId {}
|
||||
|
||||
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
|
||||
pub const CRATE_HIR_ID: HirId =
|
||||
HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
|
||||
|
|
|
|||
|
|
@ -286,10 +286,9 @@ language_item_table! {
|
|||
|
||||
// FIXME(swatinem): the following lang items are used for async lowering and
|
||||
// should become obsolete eventually.
|
||||
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
|
||||
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
|
||||
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
|
||||
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
||||
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
|
||||
use rustc_span::def_id::{DefPathHash, StableCrateId};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{create_session_if_not_set_then, Symbol};
|
||||
|
||||
#[test]
|
||||
fn def_path_hash_depends_on_crate_id() {
|
||||
|
|
@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
|
|||
// the crate by changing the crate disambiguator (e.g. via bumping the
|
||||
// crate's version number).
|
||||
|
||||
let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
|
||||
let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
|
||||
create_session_if_not_set_then(Edition::Edition2024, |_| {
|
||||
let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
|
||||
let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
|
||||
|
||||
let h0 = mk_test_hash(id0);
|
||||
let h1 = mk_test_hash(id1);
|
||||
let h0 = mk_test_hash(id0);
|
||||
let h1 = mk_test_hash(id1);
|
||||
|
||||
assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
|
||||
assert_ne!(h0.local_hash(), h1.local_hash());
|
||||
assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
|
||||
assert_ne!(h0.local_hash(), h1.local_hash());
|
||||
|
||||
fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
|
||||
let parent_hash = DefPathHash::new(stable_crate_id, 0);
|
||||
fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
|
||||
let parent_hash = DefPathHash::new(stable_crate_id, 0);
|
||||
|
||||
let key = DefKey {
|
||||
parent: None,
|
||||
disambiguated_data: DisambiguatedDefPathData {
|
||||
data: DefPathData::CrateRoot,
|
||||
disambiguator: 0,
|
||||
},
|
||||
};
|
||||
let key = DefKey {
|
||||
parent: None,
|
||||
disambiguated_data: DisambiguatedDefPathData {
|
||||
data: DefPathData::CrateRoot,
|
||||
disambiguator: 0,
|
||||
},
|
||||
};
|
||||
|
||||
key.compute_stable_hash(parent_hash)
|
||||
}
|
||||
key.compute_stable_hash(parent_hash)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1930,6 +1930,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
adt_substs,
|
||||
);
|
||||
let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
|
||||
let ty = self.normalize_ty(span, ty);
|
||||
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
use crate::errors::LinkageType;
|
||||
|
||||
use super::compare_method::check_type_bounds;
|
||||
use super::compare_method::{compare_impl_method, compare_ty_impl};
|
||||
|
|
@ -20,7 +21,7 @@ use rustc_middle::middle::stability::EvalResult;
|
|||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
||||
use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
||||
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{self, Span};
|
||||
|
|
@ -478,6 +479,36 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
}
|
||||
|
||||
fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
adt_def: AdtDef<'tcx>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> bool {
|
||||
if adt_def.repr().inhibit_enum_layout_opt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let [var_one, var_two] = &adt_def.variants().raw[..] else {
|
||||
return false;
|
||||
};
|
||||
let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
|
||||
return false;
|
||||
};
|
||||
matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
|
||||
}
|
||||
|
||||
fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
||||
if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
|
||||
if match tcx.type_of(def_id).kind() {
|
||||
ty::RawPtr(_) => false,
|
||||
ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
|
||||
_ => true,
|
||||
} {
|
||||
tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
||||
debug!(
|
||||
"check_item_type(it.def_id={:?}, it.name={})",
|
||||
|
|
@ -490,6 +521,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
|||
tcx.ensure().typeck(id.owner_id.def_id);
|
||||
maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
|
||||
check_static_inhabited(tcx, id.owner_id.def_id);
|
||||
check_static_linkage(tcx, id.owner_id.def_id);
|
||||
}
|
||||
DefKind::Const => {
|
||||
tcx.ensure().typeck(id.owner_id.def_id);
|
||||
|
|
@ -627,6 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
|
|||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -751,17 +751,45 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||
.get_generics(impl_m.def_id.expect_local())
|
||||
.expect("expected impl item to have generics or else we can't compare them")
|
||||
.span;
|
||||
let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
|
||||
Some(
|
||||
tcx.hir()
|
||||
.get_generics(local_def_id)
|
||||
.expect("expected trait item to have generics or else we can't compare them")
|
||||
.span,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut generics_span = None;
|
||||
let mut bounds_span = vec![];
|
||||
let mut where_span = None;
|
||||
if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
|
||||
&& let Some(trait_generics) = trait_node.generics()
|
||||
{
|
||||
generics_span = Some(trait_generics.span);
|
||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||
// *are* present in the impl.
|
||||
for p in trait_generics.predicates {
|
||||
if let hir::WherePredicate::BoundPredicate(pred) = p {
|
||||
for b in pred.bounds {
|
||||
if let hir::GenericBound::Outlives(lt) = b {
|
||||
bounds_span.push(lt.ident.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
|
||||
&& let Some(impl_generics) = impl_node.generics()
|
||||
{
|
||||
let mut impl_bounds = 0;
|
||||
for p in impl_generics.predicates {
|
||||
if let hir::WherePredicate::BoundPredicate(pred) = p {
|
||||
for b in pred.bounds {
|
||||
if let hir::GenericBound::Outlives(_) = b {
|
||||
impl_bounds += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if impl_bounds == bounds_span.len() {
|
||||
bounds_span = vec![];
|
||||
} else if impl_generics.has_where_clause_predicates {
|
||||
where_span = Some(impl_generics.where_clause_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
let reported = tcx
|
||||
.sess
|
||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||
|
|
@ -769,9 +797,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||
item_kind: assoc_item_kind_str(impl_m),
|
||||
ident: impl_m.ident(tcx),
|
||||
generics_span,
|
||||
bounds_span,
|
||||
where_span,
|
||||
})
|
||||
.emit_unless(delay);
|
||||
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1814,7 +1814,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
|||
);
|
||||
} else if attr.has_name(sym::linkage) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str()));
|
||||
let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.import_linkage = linkage;
|
||||
} else {
|
||||
codegen_fn_attrs.linkage = linkage;
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::link_section) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use hir::{
|
|||
GenericParamKind, HirId, Node,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||
Some(tcx.typeck_root_def_id(def_id))
|
||||
}
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin:
|
||||
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
in_trait,
|
||||
..
|
||||
}) => {
|
||||
if in_trait {
|
||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
|
||||
} else {
|
||||
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
|
||||
}
|
||||
Some(fn_def_id.to_def_id())
|
||||
}
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
|
||||
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
|||
pub span: Span,
|
||||
#[label(generics_label)]
|
||||
pub generics_span: Option<Span>,
|
||||
#[label(where_label)]
|
||||
pub where_span: Option<Span>,
|
||||
#[label(bounds_label)]
|
||||
pub bounds_span: Vec<Span>,
|
||||
pub item_kind: &'static str,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
|
@ -285,3 +289,10 @@ pub struct SelfInImplSelf {
|
|||
#[note]
|
||||
pub note: (),
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_linkage_type, code = "E0791")]
|
||||
pub(crate) struct LinkageType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use rustc_arena::DroplessArena;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt, TypeSuperVisitable, TypeVisitable};
|
||||
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// Defines the `TermsContext` basically houses an arena where we can
|
||||
|
|
@ -75,11 +76,30 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
|
||||
// ```
|
||||
// we may not use `'c` in the hidden type.
|
||||
struct OpaqueTypeLifetimeCollector {
|
||||
struct OpaqueTypeLifetimeCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_def_id: DefId,
|
||||
variances: Vec<ty::Variance>,
|
||||
}
|
||||
|
||||
impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector {
|
||||
impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
|
||||
if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
|
||||
let child_variances = self.tcx.variances_of(def_id);
|
||||
for (a, v) in substs.iter().zip(child_variances) {
|
||||
if *v != ty::Bivariant {
|
||||
a.visit_with(self)?;
|
||||
}
|
||||
}
|
||||
ControlFlow::CONTINUE
|
||||
} else {
|
||||
substs.visit_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
|
||||
|
|
@ -87,6 +107,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
}
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
|
||||
ty::Projection(proj)
|
||||
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
|
||||
{
|
||||
self.visit_opaque(proj.item_def_id, proj.substs)
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
|
||||
|
|
@ -111,7 +144,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
}
|
||||
}
|
||||
|
||||
let mut collector = OpaqueTypeLifetimeCollector { variances };
|
||||
let mut collector =
|
||||
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
|
||||
let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id());
|
||||
for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() {
|
||||
let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
|
||||
|
|
|
|||
|
|
@ -695,19 +695,8 @@ impl<'a> State<'a> {
|
|||
self.head("trait");
|
||||
self.print_ident(item.ident);
|
||||
self.print_generic_params(generics.params);
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
// FIXME(durka) this seems to be some quite outdated syntax
|
||||
for b in bounds {
|
||||
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
|
||||
self.space();
|
||||
self.word_space("for ?");
|
||||
self.print_trait_ref(&ptr.trait_ref);
|
||||
} else {
|
||||
real_bounds.push(b);
|
||||
}
|
||||
}
|
||||
self.nbsp();
|
||||
self.print_bounds("=", real_bounds);
|
||||
self.print_bounds("=", bounds);
|
||||
self.print_where_clause(generics);
|
||||
self.word(";");
|
||||
self.end(); // end inner head-block
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::coercion::CoerceMany;
|
||||
use crate::gather_locals::GatherLocalsVisitor;
|
||||
use crate::FnCtxt;
|
||||
use crate::{GeneratorTypes, UnsafetyState};
|
||||
use crate::GeneratorTypes;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
can_be_generator: Option<hir::Movability>,
|
||||
) -> Option<GeneratorTypes<'tcx>> {
|
||||
let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
|
||||
fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
|
||||
|
||||
let tcx = fcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
|
|
|||
|
|
@ -1647,6 +1647,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// the fields with the base_expr. This could cause us to hit errors later
|
||||
// when certain fields are assumed to exist that in fact do not.
|
||||
if error_happened {
|
||||
if let Some(base_expr) = base_expr {
|
||||
self.check_expr(base_expr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -523,6 +523,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||
// Consume the expressions supplying values for each field.
|
||||
for field in fields {
|
||||
self.consume_expr(field.expr);
|
||||
|
||||
// The struct path probably didn't resolve
|
||||
if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
|
||||
self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
|
||||
}
|
||||
}
|
||||
|
||||
let with_expr = match *opt_with {
|
||||
|
|
@ -540,9 +545,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||
ty::Adt(adt, substs) if adt.is_struct() => {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
|
||||
let is_mentioned = fields.iter().any(|f| {
|
||||
self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index
|
||||
});
|
||||
let is_mentioned = fields
|
||||
.iter()
|
||||
.any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
|
||||
if !is_mentioned {
|
||||
let field_place = self.mc.cat_projection(
|
||||
&*with_expr,
|
||||
|
|
|
|||
|
|
@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
blk: &'tcx hir::Block<'tcx>,
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let prev = self.ps.replace(self.ps.get().recurse(blk));
|
||||
|
||||
// In some cases, blocks have just one exit, but other blocks
|
||||
// can be targeted by multiple breaks. This can happen both
|
||||
// with labeled blocks as well as when we desugar
|
||||
|
|
@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.write_ty(blk.hir_id, ty);
|
||||
|
||||
self.ps.set(prev);
|
||||
ty
|
||||
}
|
||||
|
||||
|
|
@ -1918,15 +1915,11 @@ 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(..)
|
||||
) {
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
if !ty.is_fn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sig = self.tcx.fn_sig(def_id).skip_binder();
|
||||
let sig = ty.fn_sig(self.tcx).skip_binder();
|
||||
let args_referencing_param: Vec<_> = sig
|
||||
.inputs()
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
|
|||
pub use suggestions::*;
|
||||
|
||||
use crate::coercion::DynamicCoerceMany;
|
||||
use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
|
||||
use crate::{Diverges, EnclosingBreakables, Inherited};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
|
|
@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||
|
||||
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
|
||||
|
||||
pub(super) ps: Cell<UnsafetyState>,
|
||||
|
||||
/// Whether the last checked node generates a divergence (e.g.,
|
||||
/// `return` will set this to `Always`). In general, when entering
|
||||
/// an expression or other node in the tree, the initial value
|
||||
|
|
@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ret_coercion: None,
|
||||
ret_coercion_span: Cell::new(None),
|
||||
resume_yield_tys: None,
|
||||
ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
|
||||
diverges: Cell::new(Diverges::Maybe),
|
||||
enclosing_breakables: RefCell::new(EnclosingBreakables {
|
||||
stack: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
|
||||
// This suggestion is incorrect for
|
||||
// fn foo() -> bool { match () { () => true } || match () { () => true } }
|
||||
err.span_suggestion_short(
|
||||
span.shrink_to_hi(),
|
||||
"consider using a semicolon here",
|
||||
";",
|
||||
Applicability::MachineApplicable,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> {
|
|||
revealed_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct UnsafetyState {
|
||||
pub def: hir::HirId,
|
||||
pub unsafety: hir::Unsafety,
|
||||
from_fn: bool,
|
||||
}
|
||||
|
||||
impl UnsafetyState {
|
||||
pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
|
||||
UnsafetyState { def, unsafety, from_fn: true }
|
||||
}
|
||||
|
||||
pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
|
||||
use hir::BlockCheckMode;
|
||||
match self.unsafety {
|
||||
// If this unsafe, then if the outer function was already marked as
|
||||
// unsafe we shouldn't attribute the unsafe'ness to the block. This
|
||||
// way the block can be warned about instead of ignoring this
|
||||
// extraneous block (functions are never warned about).
|
||||
hir::Unsafety::Unsafe if self.from_fn => self,
|
||||
|
||||
unsafety => {
|
||||
let (unsafety, def) = match blk.rules {
|
||||
BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
|
||||
BlockCheckMode::DefaultBlock => (unsafety, self.def),
|
||||
};
|
||||
UnsafetyState { def, unsafety, from_fn: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If this `DefId` is a "primary tables entry", returns
|
||||
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1482,15 +1482,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ident_name: Symbol,
|
||||
}
|
||||
|
||||
// FIXME: This really should be taking scoping, etc into account.
|
||||
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;
|
||||
}
|
||||
if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
|
||||
&& let Binding(_, _, ident, ..) = pat.kind
|
||||
&& ident.name == self.ident_name
|
||||
{
|
||||
self.result = *init;
|
||||
} else {
|
||||
hir::intravisit::walk_stmt(self, ex);
|
||||
}
|
||||
hir::intravisit::walk_stmt(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1498,9 +1500,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
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);
|
||||
if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
|
||||
&& let Some(expr) = visitor.result
|
||||
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
|
||||
{
|
||||
let probe = self.lookup_probe(
|
||||
seg2.ident,
|
||||
self_ty,
|
||||
|
|
@ -1513,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
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
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock};
|
|||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_fs_util::{link_or_copy, LinkOrCopy};
|
||||
use rustc_session::{Session, StableCrateId};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use std::fs as std_fs;
|
||||
use std::io::{self, ErrorKind};
|
||||
|
|
@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
|
|||
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
|
||||
pub fn prepare_session_directory(
|
||||
sess: &Session,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
stable_crate_id: StableCrateId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if sess.opts.incremental.is_none() {
|
||||
|
|
@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
|
|||
Ok(UNIX_EPOCH + duration)
|
||||
}
|
||||
|
||||
fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
|
||||
fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
|
||||
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
|
||||
|
||||
let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ use rustc_middle::ty::{
|
|||
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
use std::path::PathBuf;
|
||||
use std::{cmp, fmt, iter};
|
||||
|
||||
mod note;
|
||||
|
|
@ -341,7 +342,15 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
let ty::Opaque(def_id, substs) = *ty.kind() else { return None; };
|
||||
let (def_id, substs) = match *ty.kind() {
|
||||
ty::Opaque(def_id, substs) => (def_id, substs),
|
||||
ty::Projection(data)
|
||||
if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
|
||||
{
|
||||
(data.item_def_id, data.substs)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
|
||||
|
|
@ -1344,10 +1353,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.map(|(mod_str, _)| mod_str.len() + separator_len)
|
||||
.sum();
|
||||
|
||||
debug!(
|
||||
"cmp: separator_len={}, split_idx={}, min_len={}",
|
||||
separator_len, split_idx, min_len
|
||||
);
|
||||
debug!(?separator_len, ?split_idx, ?min_len, "cmp");
|
||||
|
||||
if split_idx >= min_len {
|
||||
// paths are identical, highlight everything
|
||||
|
|
@ -1358,7 +1364,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
} else {
|
||||
let (common, uniq1) = t1_str.split_at(split_idx);
|
||||
let (_, uniq2) = t2_str.split_at(split_idx);
|
||||
debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
|
||||
debug!(?common, ?uniq1, ?uniq2, "cmp");
|
||||
|
||||
values.0.push_normal(common);
|
||||
values.0.push_highlighted(uniq1);
|
||||
|
|
@ -1651,17 +1657,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
|
||||
};
|
||||
let vals = match self.values_str(values) {
|
||||
Some((expected, found)) => Some((expected, found)),
|
||||
None => {
|
||||
// Derived error. Cancel the emitter.
|
||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||
// is borrowed, so we can't fully defuse it.
|
||||
diag.downgrade_to_delayed_bug();
|
||||
return;
|
||||
}
|
||||
let Some(vals) = self.values_str(values) else {
|
||||
// Derived error. Cancel the emitter.
|
||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||
// is borrowed, so we can't fully defuse it.
|
||||
diag.downgrade_to_delayed_bug();
|
||||
return;
|
||||
};
|
||||
(vals, exp_found, is_simple_error, Some(values))
|
||||
(Some(vals), exp_found, is_simple_error, Some(values))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1693,7 +1696,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
label_or_note(span, &terr.to_string());
|
||||
}
|
||||
|
||||
if let Some((expected, found)) = expected_found {
|
||||
if let Some((expected, found, exp_p, found_p)) = expected_found {
|
||||
let (expected_label, found_label, exp_found) = match exp_found {
|
||||
Mismatch::Variable(ef) => (
|
||||
ef.expected.prefix_string(self.tcx),
|
||||
|
|
@ -1810,32 +1813,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
TypeError::Sorts(values) => {
|
||||
let extra = expected == found;
|
||||
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
|
||||
(true, ty::Opaque(def_id, _)) => {
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
|
||||
format!(
|
||||
" (opaque type at <{}:{}:{}>)",
|
||||
sm.filename_for_diagnostics(&pos.file.name),
|
||||
pos.line,
|
||||
pos.col.to_usize() + 1,
|
||||
)
|
||||
let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
|
||||
let mut s = match (extra, ty.kind()) {
|
||||
(true, ty::Opaque(def_id, _)) => {
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
|
||||
format!(
|
||||
" (opaque type at <{}:{}:{}>)",
|
||||
sm.filename_for_diagnostics(&pos.file.name),
|
||||
pos.line,
|
||||
pos.col.to_usize() + 1,
|
||||
)
|
||||
}
|
||||
(true, ty::Projection(proj))
|
||||
if self.tcx.def_kind(proj.item_def_id)
|
||||
== DefKind::ImplTraitPlaceholder =>
|
||||
{
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
|
||||
format!(
|
||||
" (trait associated opaque type at <{}:{}:{}>)",
|
||||
sm.filename_for_diagnostics(&pos.file.name),
|
||||
pos.line,
|
||||
pos.col.to_usize() + 1,
|
||||
)
|
||||
}
|
||||
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
|
||||
(false, _) => "".to_string(),
|
||||
};
|
||||
if let Some(path) = path {
|
||||
s.push_str(&format!(
|
||||
"\nthe full type name has been written to '{}'",
|
||||
path.display(),
|
||||
));
|
||||
}
|
||||
(true, ty::Projection(proj))
|
||||
if self.tcx.def_kind(proj.item_def_id)
|
||||
== DefKind::ImplTraitPlaceholder =>
|
||||
{
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
|
||||
format!(
|
||||
" (trait associated opaque type at <{}:{}:{}>)",
|
||||
sm.filename_for_diagnostics(&pos.file.name),
|
||||
pos.line,
|
||||
pos.col.to_usize() + 1,
|
||||
)
|
||||
}
|
||||
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
|
||||
(false, _) => "".to_string(),
|
||||
s
|
||||
};
|
||||
if !(values.expected.is_simple_text() && values.found.is_simple_text())
|
||||
|| (exp_found.map_or(false, |ef| {
|
||||
|
|
@ -1857,8 +1869,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
expected,
|
||||
&found_label,
|
||||
found,
|
||||
&sort_string(values.expected),
|
||||
&sort_string(values.found),
|
||||
&sort_string(values.expected, exp_p),
|
||||
&sort_string(values.found, found_p),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2331,7 +2343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let code = trace.cause.code();
|
||||
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
|
||||
&& let hir::MatchSource::TryDesugar = source
|
||||
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values)
|
||||
&& let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
|
||||
{
|
||||
err.note(&format!(
|
||||
"`?` operator cannot convert from `{}` to `{}`",
|
||||
|
|
@ -2447,7 +2459,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
fn values_str(
|
||||
&self,
|
||||
values: ValuePairs<'tcx>,
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||
{
|
||||
match values {
|
||||
infer::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
||||
|
|
@ -2457,7 +2470,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
found: exp_found.found.print_only_trait_path(),
|
||||
};
|
||||
match self.expected_found_str(pretty_exp_found) {
|
||||
Some((expected, found)) if expected == found => {
|
||||
Some((expected, found, _, _)) if expected == found => {
|
||||
self.expected_found_str(exp_found)
|
||||
}
|
||||
ret => ret,
|
||||
|
|
@ -2469,7 +2482,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
found: exp_found.found.print_only_trait_path(),
|
||||
};
|
||||
match self.expected_found_str(pretty_exp_found) {
|
||||
Some((expected, found)) if expected == found => {
|
||||
Some((expected, found, _, _)) if expected == found => {
|
||||
self.expected_found_str(exp_found)
|
||||
}
|
||||
ret => ret,
|
||||
|
|
@ -2481,17 +2494,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
fn expected_found_str_term(
|
||||
&self,
|
||||
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||
{
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
|
||||
(ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
|
||||
(ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
|
||||
let (mut exp, mut fnd) = self.cmp(expected, found);
|
||||
// Use the terminal width as the basis to determine when to compress the printed
|
||||
// out type, but give ourselves some leeway to avoid ending up creating a file for
|
||||
// a type that is somewhat shorter than the path we'd write to.
|
||||
let len = self.tcx.sess().diagnostic_width() + 40;
|
||||
let exp_s = exp.content();
|
||||
let fnd_s = fnd.content();
|
||||
let mut exp_p = None;
|
||||
let mut fnd_p = None;
|
||||
if exp_s.len() > len {
|
||||
let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
|
||||
exp = DiagnosticStyledString::highlighted(exp_s);
|
||||
exp_p = exp_path;
|
||||
}
|
||||
if fnd_s.len() > len {
|
||||
let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
|
||||
fnd = DiagnosticStyledString::highlighted(fnd_s);
|
||||
fnd_p = fnd_path;
|
||||
}
|
||||
(exp, fnd, exp_p, fnd_p)
|
||||
}
|
||||
_ => (
|
||||
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
||||
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
||||
None,
|
||||
None,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
|
@ -2500,7 +2537,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
|
||||
&self,
|
||||
exp_found: ty::error::ExpectedFound<T>,
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
|
||||
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
|
||||
{
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
|
@ -2509,6 +2547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
Some((
|
||||
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
|
||||
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
|
||||
None,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
@ -2842,36 +2882,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
|
||||
debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
|
||||
|
||||
if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
|
||||
(&sup_origin, &sub_origin)
|
||||
if let infer::Subtype(ref sup_trace) = sup_origin
|
||||
&& let infer::Subtype(ref sub_trace) = sub_origin
|
||||
&& let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
|
||||
&& let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
|
||||
&& sub_expected == sup_expected
|
||||
&& sub_found == sup_found
|
||||
{
|
||||
debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
|
||||
debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
|
||||
debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
|
||||
debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
"...but the lifetime must also be valid for ",
|
||||
sub_region,
|
||||
"...",
|
||||
None,
|
||||
);
|
||||
err.span_note(
|
||||
sup_trace.cause.span,
|
||||
&format!("...so that the {}", sup_trace.cause.as_requirement_str()),
|
||||
);
|
||||
|
||||
if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
|
||||
(self.values_str(sup_trace.values), self.values_str(sub_trace.values))
|
||||
{
|
||||
if sub_expected == sup_expected && sub_found == sup_found {
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
"...but the lifetime must also be valid for ",
|
||||
sub_region,
|
||||
"...",
|
||||
None,
|
||||
);
|
||||
err.span_note(
|
||||
sup_trace.cause.span,
|
||||
&format!("...so that the {}", sup_trace.cause.as_requirement_str()),
|
||||
);
|
||||
|
||||
err.note_expected_found(&"", sup_expected, &"", sup_found);
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
err.note_expected_found(&"", sup_expected, &"", sup_found);
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
self.note_region_origin(&mut err, &sup_origin);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||
span: trace.cause.span,
|
||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
||||
expected_found: self.values_str(trace.values),
|
||||
expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
|
||||
}
|
||||
.add_to_diagnostic(err),
|
||||
infer::Reborrow(span) => {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_ast::{self as ast, visit};
|
|||
use rustc_borrowck as mir_borrowck;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
|
||||
|
|
@ -157,7 +158,7 @@ pub fn create_resolver(
|
|||
sess: Lrc<Session>,
|
||||
metadata_loader: Box<MetadataLoaderDyn>,
|
||||
krate: &ast::Crate,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
) -> BoxedResolver {
|
||||
trace!("create_resolver");
|
||||
BoxedResolver::new(sess, move |sess, resolver_arenas| {
|
||||
|
|
@ -170,7 +171,7 @@ pub fn register_plugins<'a>(
|
|||
metadata_loader: &'a dyn MetadataLoader,
|
||||
register_lints: impl Fn(&Session, &mut LintStore),
|
||||
mut krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
) -> Result<(ast::Crate, LintStore)> {
|
||||
krate = sess.time("attributes_injection", || {
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
|
|
@ -227,19 +228,21 @@ fn pre_expansion_lint<'a>(
|
|||
lint_store: &LintStore,
|
||||
registered_tools: &RegisteredTools,
|
||||
check_node: impl EarlyCheckNode<'a>,
|
||||
node_name: &str,
|
||||
node_name: Symbol,
|
||||
) {
|
||||
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
|
||||
rustc_lint::check_ast_node(
|
||||
sess,
|
||||
true,
|
||||
lint_store,
|
||||
registered_tools,
|
||||
None,
|
||||
rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
|
||||
check_node,
|
||||
);
|
||||
});
|
||||
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
|
||||
|| {
|
||||
rustc_lint::check_ast_node(
|
||||
sess,
|
||||
true,
|
||||
lint_store,
|
||||
registered_tools,
|
||||
None,
|
||||
rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
|
||||
check_node,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Cannot implement directly for `LintStore` due to trait coherence.
|
||||
|
|
@ -253,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
|||
node_id: ast::NodeId,
|
||||
attrs: &[ast::Attribute],
|
||||
items: &[rustc_ast::ptr::P<ast::Item>],
|
||||
name: &str,
|
||||
name: Symbol,
|
||||
) {
|
||||
pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
|
||||
}
|
||||
|
|
@ -267,7 +270,7 @@ pub fn configure_and_expand(
|
|||
sess: &Session,
|
||||
lint_store: &LintStore,
|
||||
mut krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
resolver: &mut Resolver<'_>,
|
||||
) -> Result<ast::Crate> {
|
||||
trace!("configure_and_expand");
|
||||
|
|
@ -461,7 +464,7 @@ fn generated_output_paths(
|
|||
sess: &Session,
|
||||
outputs: &OutputFilenames,
|
||||
exact_name: bool,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
) -> Vec<PathBuf> {
|
||||
let mut out_filenames = Vec::new();
|
||||
for output_type in sess.opts.output_types.keys() {
|
||||
|
|
@ -660,7 +663,7 @@ pub fn prepare_outputs(
|
|||
compiler: &Compiler,
|
||||
krate: &ast::Crate,
|
||||
boxed_resolver: &RefCell<BoxedResolver>,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
) -> Result<OutputFilenames> {
|
||||
let _timer = sess.timer("prepare_outputs");
|
||||
|
||||
|
|
@ -770,7 +773,7 @@ pub fn create_global_ctxt<'tcx>(
|
|||
dep_graph: DepGraph,
|
||||
resolver: Rc<RefCell<BoxedResolver>>,
|
||||
outputs: OutputFilenames,
|
||||
crate_name: &str,
|
||||
crate_name: Symbol,
|
||||
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
|
||||
global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
|
|
@ -801,6 +804,12 @@ pub fn create_global_ctxt<'tcx>(
|
|||
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
|
||||
});
|
||||
|
||||
let ty::ResolverOutputs {
|
||||
definitions,
|
||||
global_ctxt: untracked_resolutions,
|
||||
ast_lowering: untracked_resolver_for_lowering,
|
||||
} = resolver_outputs;
|
||||
|
||||
let gcx = sess.time("setup_global_ctxt", || {
|
||||
global_ctxt.get_or_init(move || {
|
||||
TyCtxt::create_global_ctxt(
|
||||
|
|
@ -808,7 +817,8 @@ pub fn create_global_ctxt<'tcx>(
|
|||
lint_store,
|
||||
arena,
|
||||
hir_arena,
|
||||
resolver_outputs,
|
||||
definitions,
|
||||
untracked_resolutions,
|
||||
krate,
|
||||
dep_graph,
|
||||
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
|
||||
|
|
@ -820,7 +830,12 @@ pub fn create_global_ctxt<'tcx>(
|
|||
})
|
||||
});
|
||||
|
||||
QueryContext { gcx }
|
||||
let mut qcx = QueryContext { gcx };
|
||||
qcx.enter(|tcx| {
|
||||
tcx.feed_unit_query()
|
||||
.resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering)))
|
||||
});
|
||||
qcx
|
||||
}
|
||||
|
||||
/// Runs the resolution, type-checking, region checking and other
|
||||
|
|
@ -965,12 +980,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
|||
pub fn start_codegen<'tcx>(
|
||||
codegen_backend: &dyn CodegenBackend,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
outputs: &OutputFilenames,
|
||||
) -> Box<dyn Any> {
|
||||
info!("Pre-codegen\n{:?}", tcx.debug_stats());
|
||||
|
||||
let (metadata, need_metadata_module) =
|
||||
rustc_metadata::fs::encode_and_write_metadata(tcx, outputs);
|
||||
let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
|
||||
|
||||
let codegen = tcx.sess.time("codegen_crate", move || {
|
||||
codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
|
||||
|
|
@ -986,7 +999,7 @@ pub fn start_codegen<'tcx>(
|
|||
info!("Post-codegen\n{:?}", tcx.debug_stats());
|
||||
|
||||
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
|
||||
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) {
|
||||
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
|
||||
tcx.sess.emit_err(CantEmitMIR { error });
|
||||
tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@ use rustc_query_impl::Queries as TcxQueries;
|
|||
use rustc_session::config::{self, OutputFilenames, OutputType};
|
||||
use rustc_session::{output::find_crate_name, Session};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Symbol;
|
||||
use std::any::Any;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Represent the result of a query.
|
||||
///
|
||||
|
|
@ -73,7 +75,7 @@ pub struct Queries<'tcx> {
|
|||
|
||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||
parse: Query<ast::Crate>,
|
||||
crate_name: Query<String>,
|
||||
crate_name: Query<Symbol>,
|
||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
||||
expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
|
||||
dep_graph: Query<DepGraph>,
|
||||
|
|
@ -134,7 +136,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
&*self.codegen_backend().metadata_loader(),
|
||||
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
||||
krate,
|
||||
&crate_name,
|
||||
crate_name,
|
||||
)?;
|
||||
|
||||
// Compute the dependency graph (in the background). We want to do
|
||||
|
|
@ -148,7 +150,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn crate_name(&self) -> Result<&Query<String>> {
|
||||
pub fn crate_name(&self) -> Result<&Query<Symbol>> {
|
||||
self.crate_name.compute(|| {
|
||||
Ok({
|
||||
let parse_result = self.parse()?;
|
||||
|
|
@ -164,7 +166,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
|
||||
trace!("expansion");
|
||||
self.expansion.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let crate_name = *self.crate_name()?.peek();
|
||||
let (krate, lint_store) = self.register_plugins()?.take();
|
||||
let _timer = self.session().timer("configure_and_expand");
|
||||
let sess = self.session();
|
||||
|
|
@ -172,10 +174,10 @@ impl<'tcx> Queries<'tcx> {
|
|||
sess.clone(),
|
||||
self.codegen_backend().metadata_loader(),
|
||||
&krate,
|
||||
&crate_name,
|
||||
crate_name,
|
||||
);
|
||||
let krate = resolver.access(|resolver| {
|
||||
passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
|
||||
passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
|
||||
})?;
|
||||
Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
|
||||
})
|
||||
|
|
@ -200,21 +202,21 @@ impl<'tcx> Queries<'tcx> {
|
|||
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
|
||||
self.prepare_outputs.compute(|| {
|
||||
let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
|
||||
let crate_name = self.crate_name()?.peek();
|
||||
let crate_name = *self.crate_name()?.peek();
|
||||
passes::prepare_outputs(
|
||||
self.session(),
|
||||
self.compiler,
|
||||
krate,
|
||||
&*boxed_resolver,
|
||||
&crate_name,
|
||||
crate_name,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
|
||||
self.global_ctxt.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let outputs = self.prepare_outputs()?.peek().clone();
|
||||
let crate_name = *self.crate_name()?.peek();
|
||||
let outputs = self.prepare_outputs()?.take();
|
||||
let dep_graph = self.dep_graph()?.peek().clone();
|
||||
let (krate, resolver, lint_store) = self.expansion()?.take();
|
||||
Ok(passes::create_global_ctxt(
|
||||
|
|
@ -224,7 +226,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
dep_graph,
|
||||
resolver,
|
||||
outputs,
|
||||
&crate_name,
|
||||
crate_name,
|
||||
&self.queries,
|
||||
&self.gcx,
|
||||
&self.arena,
|
||||
|
|
@ -235,7 +237,6 @@ impl<'tcx> Queries<'tcx> {
|
|||
|
||||
pub fn ongoing_codegen(&'tcx self) -> Result<&Query<Box<dyn Any>>> {
|
||||
self.ongoing_codegen.compute(|| {
|
||||
let outputs = self.prepare_outputs()?;
|
||||
self.global_ctxt()?.peek_mut().enter(|tcx| {
|
||||
tcx.analysis(()).ok();
|
||||
|
||||
|
|
@ -249,7 +250,7 @@ impl<'tcx> Queries<'tcx> {
|
|||
// Hook for UI tests.
|
||||
Self::check_for_rustc_errors_attr(tcx);
|
||||
|
||||
Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek()))
|
||||
Ok(passes::start_codegen(&***self.codegen_backend(), tcx))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -293,8 +294,10 @@ impl<'tcx> Queries<'tcx> {
|
|||
let codegen_backend = self.codegen_backend().clone();
|
||||
|
||||
let dep_graph = self.dep_graph()?.peek().clone();
|
||||
let prepare_outputs = self.prepare_outputs()?.take();
|
||||
let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
|
||||
let (crate_hash, prepare_outputs) = self
|
||||
.global_ctxt()?
|
||||
.peek_mut()
|
||||
.enter(|tcx| (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone()));
|
||||
let ongoing_codegen = self.ongoing_codegen()?.take();
|
||||
|
||||
Ok(Linker {
|
||||
|
|
@ -316,7 +319,7 @@ pub struct Linker {
|
|||
|
||||
// compilation outputs
|
||||
dep_graph: DepGraph,
|
||||
prepare_outputs: OutputFilenames,
|
||||
prepare_outputs: Arc<OutputFilenames>,
|
||||
crate_hash: Svh,
|
||||
ongoing_codegen: Box<dyn Any>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -747,6 +747,7 @@ fn test_unstable_options_tracking_hash() {
|
|||
tracked!(link_only, true);
|
||||
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
|
||||
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
|
||||
tracked!(maximal_hir_to_mir_coverage, true);
|
||||
tracked!(merge_functions, Some(MergeFunctions::Disabled));
|
||||
tracked!(mir_emit_retag, true);
|
||||
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
|
|||
}
|
||||
if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
|
||||
if cx.tcx.find_field_index(ident, &variant)
|
||||
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
|
||||
== Some(cx.typeck_results().field_index(fieldpat.hir_id))
|
||||
{
|
||||
cx.struct_span_lint(
|
||||
NON_SHORTHAND_FIELD_PATTERNS,
|
||||
|
|
|
|||
|
|
@ -20,21 +20,23 @@ use rustc_ast::ptr::P;
|
|||
use rustc_ast::visit::{self as ast_visit, Visitor};
|
||||
use rustc_ast::{self as ast, walk_list, HasAttrs};
|
||||
use rustc_middle::ty::RegisteredTools;
|
||||
use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
|
||||
use rustc_session::lint::{BufferedEarlyLint, LintBuffer};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
$cx.pass.$f(&$cx.context, $($args),*);
|
||||
macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
for pass in $cx.passes.iter_mut() {
|
||||
pass.$f(&$cx.context, $($args),*);
|
||||
}
|
||||
}) }
|
||||
|
||||
pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
|
||||
pub struct EarlyContextAndPasses<'a> {
|
||||
context: EarlyContext<'a>,
|
||||
pass: T,
|
||||
passes: Vec<EarlyLintPassObject>,
|
||||
}
|
||||
|
||||
impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
||||
impl<'a> EarlyContextAndPasses<'a> {
|
||||
fn check_id(&mut self, id: ast::NodeId) {
|
||||
for early_lint in self.context.buffered.take(id) {
|
||||
let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
|
||||
|
|
@ -61,27 +63,27 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||
|
||||
self.check_id(id);
|
||||
debug!("early context: enter_attrs({:?})", attrs);
|
||||
run_early_pass!(self, enter_lint_attrs, attrs);
|
||||
run_early_passes!(self, enter_lint_attrs, attrs);
|
||||
f(self);
|
||||
debug!("early context: exit_attrs({:?})", attrs);
|
||||
run_early_pass!(self, exit_lint_attrs, attrs);
|
||||
run_early_passes!(self, exit_lint_attrs, attrs);
|
||||
self.context.builder.pop(push);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
|
||||
impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
|
||||
fn visit_param(&mut self, param: &'a ast::Param) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
run_early_pass!(cx, check_param, param);
|
||||
run_early_passes!(cx, check_param, param);
|
||||
ast_visit::walk_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, it: &'a ast::Item) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
run_early_pass!(cx, check_item, it);
|
||||
run_early_passes!(cx, check_item, it);
|
||||
ast_visit::walk_item(cx, it);
|
||||
run_early_pass!(cx, check_item_post, it);
|
||||
run_early_passes!(cx, check_item_post, it);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -92,10 +94,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_pat(&mut self, p: &'a ast::Pat) {
|
||||
run_early_pass!(self, check_pat, p);
|
||||
run_early_passes!(self, check_pat, p);
|
||||
self.check_id(p.id);
|
||||
ast_visit::walk_pat(self, p);
|
||||
run_early_pass!(self, check_pat_post, p);
|
||||
run_early_passes!(self, check_pat_post, p);
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'a ast::PatField) {
|
||||
|
|
@ -111,7 +113,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
self.with_lint_attrs(e.id, &e.attrs, |cx| {
|
||||
run_early_pass!(cx, check_expr, e);
|
||||
run_early_passes!(cx, check_expr, e);
|
||||
ast_visit::walk_expr(cx, e);
|
||||
})
|
||||
}
|
||||
|
|
@ -132,7 +134,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
// Note that statements get their attributes from
|
||||
// the AST struct that they wrap (e.g. an item)
|
||||
self.with_lint_attrs(s.id, s.attrs(), |cx| {
|
||||
run_early_pass!(cx, check_stmt, s);
|
||||
run_early_passes!(cx, check_stmt, s);
|
||||
cx.check_id(s.id);
|
||||
});
|
||||
// The visitor for the AST struct wrapped
|
||||
|
|
@ -143,7 +145,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
|
||||
run_early_pass!(self, check_fn, fk, span, id);
|
||||
run_early_passes!(self, check_fn, fk, span, id);
|
||||
self.check_id(id);
|
||||
ast_visit::walk_fn(self, fk);
|
||||
|
||||
|
|
@ -171,37 +173,37 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
|
||||
fn visit_variant(&mut self, v: &'a ast::Variant) {
|
||||
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
||||
run_early_pass!(cx, check_variant, v);
|
||||
run_early_passes!(cx, check_variant, v);
|
||||
ast_visit::walk_variant(cx, v);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'a ast::Ty) {
|
||||
run_early_pass!(self, check_ty, t);
|
||||
run_early_passes!(self, check_ty, t);
|
||||
self.check_id(t.id);
|
||||
ast_visit::walk_ty(self, t);
|
||||
}
|
||||
|
||||
fn visit_ident(&mut self, ident: Ident) {
|
||||
run_early_pass!(self, check_ident, ident);
|
||||
run_early_passes!(self, check_ident, ident);
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &'a ast::Local) {
|
||||
self.with_lint_attrs(l.id, &l.attrs, |cx| {
|
||||
run_early_pass!(cx, check_local, l);
|
||||
run_early_passes!(cx, check_local, l);
|
||||
ast_visit::walk_local(cx, l);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, b: &'a ast::Block) {
|
||||
run_early_pass!(self, check_block, b);
|
||||
run_early_passes!(self, check_block, b);
|
||||
self.check_id(b.id);
|
||||
ast_visit::walk_block(self, b);
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'a ast::Arm) {
|
||||
self.with_lint_attrs(a.id, &a.attrs, |cx| {
|
||||
run_early_pass!(cx, check_arm, a);
|
||||
run_early_passes!(cx, check_arm, a);
|
||||
ast_visit::walk_arm(cx, a);
|
||||
})
|
||||
}
|
||||
|
|
@ -220,19 +222,19 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
|
||||
run_early_pass!(self, check_generic_arg, arg);
|
||||
run_early_passes!(self, check_generic_arg, arg);
|
||||
ast_visit::walk_generic_arg(self, arg);
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
run_early_pass!(cx, check_generic_param, param);
|
||||
run_early_passes!(cx, check_generic_param, param);
|
||||
ast_visit::walk_generic_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, g: &'a ast::Generics) {
|
||||
run_early_pass!(self, check_generics, g);
|
||||
run_early_passes!(self, check_generics, g);
|
||||
ast_visit::walk_generics(self, g);
|
||||
}
|
||||
|
||||
|
|
@ -241,18 +243,18 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
|
||||
run_early_pass!(self, check_poly_trait_ref, t);
|
||||
run_early_passes!(self, check_poly_trait_ref, t);
|
||||
ast_visit::walk_poly_trait_ref(self, t);
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
run_early_pass!(cx, check_trait_item, item);
|
||||
run_early_passes!(cx, check_trait_item, item);
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl => {
|
||||
run_early_pass!(cx, check_impl_item, item);
|
||||
run_early_passes!(cx, check_impl_item, item);
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
}
|
||||
});
|
||||
|
|
@ -273,45 +275,20 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
|
||||
run_early_pass!(self, check_attribute, attr);
|
||||
run_early_passes!(self, check_attribute, attr);
|
||||
}
|
||||
|
||||
fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
|
||||
run_early_pass!(self, check_mac_def, mac);
|
||||
run_early_passes!(self, check_mac_def, mac);
|
||||
self.check_id(id);
|
||||
}
|
||||
|
||||
fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
|
||||
run_early_pass!(self, check_mac, mac);
|
||||
run_early_passes!(self, check_mac, mac);
|
||||
ast_visit::walk_mac(self, mac);
|
||||
}
|
||||
}
|
||||
|
||||
struct EarlyLintPassObjects<'a> {
|
||||
lints: &'a mut [EarlyLintPassObject],
|
||||
}
|
||||
|
||||
#[allow(rustc::lint_pass_impl_without_macro)]
|
||||
impl LintPass for EarlyLintPassObjects<'_> {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! early_lint_pass_impl {
|
||||
([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
|
||||
impl EarlyLintPass for EarlyLintPassObjects<'_> {
|
||||
$(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
|
||||
for obj in self.lints.iter_mut() {
|
||||
obj.$name(context, $($param),*);
|
||||
}
|
||||
})*
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
crate::early_lint_methods!(early_lint_pass_impl, []);
|
||||
|
||||
/// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
|
||||
/// This trait generalizes over those nodes.
|
||||
pub trait EarlyCheckNode<'a>: Copy {
|
||||
|
|
@ -319,7 +296,7 @@ pub trait EarlyCheckNode<'a>: Copy {
|
|||
fn attrs<'b>(self) -> &'b [ast::Attribute]
|
||||
where
|
||||
'a: 'b;
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
|
||||
where
|
||||
'a: 'b;
|
||||
}
|
||||
|
|
@ -334,13 +311,13 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
|
|||
{
|
||||
&self.attrs
|
||||
}
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
run_early_pass!(cx, check_crate, self);
|
||||
run_early_passes!(cx, check_crate, self);
|
||||
ast_visit::walk_crate(cx, self);
|
||||
run_early_pass!(cx, check_crate_post, self);
|
||||
run_early_passes!(cx, check_crate_post, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,7 +331,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
|
|||
{
|
||||
self.1
|
||||
}
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
|
||||
fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
|
|
@ -374,10 +351,10 @@ pub fn check_ast_node<'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 passes: Vec<EarlyLintPassObject> = passes.iter().map(|p| (p)()).collect();
|
||||
passes.push(Box::new(builtin_lints));
|
||||
|
||||
let mut cx = EarlyContextAndPass {
|
||||
let mut cx = EarlyContextAndPasses {
|
||||
context: EarlyContext::new(
|
||||
sess,
|
||||
!pre_expansion,
|
||||
|
|
@ -385,7 +362,7 @@ pub fn check_ast_node<'a>(
|
|||
registered_tools,
|
||||
lint_buffer.unwrap_or_default(),
|
||||
),
|
||||
pass: EarlyLintPassObjects { lints: &mut passes[..] },
|
||||
passes,
|
||||
};
|
||||
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ use rustc_hir::intravisit as hir_visit;
|
|||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint::LintPass;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::any::Any;
|
||||
|
|
@ -37,15 +36,17 @@ pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
|
|||
}
|
||||
|
||||
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
$cx.pass.$f(&$cx.context, $($args),*);
|
||||
for pass in $cx.passes.iter_mut() {
|
||||
pass.$f(&$cx.context, $($args),*);
|
||||
}
|
||||
}) }
|
||||
|
||||
struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
|
||||
struct LateContextAndPasses<'tcx> {
|
||||
context: LateContext<'tcx>,
|
||||
pass: T,
|
||||
passes: Vec<LateLintPassObject<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
|
||||
impl<'tcx> LateContextAndPasses<'tcx> {
|
||||
/// Merge the lints specified by any lint attributes into the
|
||||
/// current lint context, call the provided function, then reset the
|
||||
/// lints in effect to their previous state.
|
||||
|
|
@ -81,7 +82,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
|
||||
impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
|
||||
type NestedFilter = nested_filter::All;
|
||||
|
||||
/// Because lints are scoped lexically, we want to walk nested
|
||||
|
|
@ -301,31 +302,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
}
|
||||
}
|
||||
|
||||
struct LateLintPassObjects<'a, 'tcx> {
|
||||
lints: &'a mut [LateLintPassObject<'tcx>],
|
||||
}
|
||||
|
||||
#[allow(rustc::lint_pass_impl_without_macro)]
|
||||
impl LintPass for LateLintPassObjects<'_, '_> {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! late_lint_pass_impl {
|
||||
([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => {
|
||||
impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> {
|
||||
$(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]);
|
||||
|
||||
pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module_def_id: LocalDefId,
|
||||
|
|
@ -346,9 +322,8 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
|||
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 mut cx = LateContextAndPasses { context, passes };
|
||||
|
||||
let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
cx.process_mod(module, hir_id);
|
||||
|
|
@ -377,9 +352,8 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
|
|||
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 };
|
||||
let mut cx = LateContextAndPasses { context, passes };
|
||||
|
||||
// Visit the whole crate.
|
||||
cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ declare_tool_lint! {
|
|||
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to
|
||||
/// always be passed by value. This is usually used for types that are thin wrappers around
|
||||
/// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which
|
||||
/// is a reference to an `Interned<TyS>`)
|
||||
/// is a reference to an `Interned<TyKind>`)
|
||||
pub rustc::PASS_BY_VALUE,
|
||||
Warn,
|
||||
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
|
||||
|
|
|
|||
|
|
@ -633,13 +633,34 @@ trait UnusedDelimLint {
|
|||
left_pos: Option<BytePos>,
|
||||
right_pos: Option<BytePos>,
|
||||
) {
|
||||
// If `value` has `ExprKind::Err`, unused delim lint can be broken.
|
||||
// For example, the following code caused ICE.
|
||||
// This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
|
||||
// and this leads to wrong spans. #104897
|
||||
//
|
||||
// ```
|
||||
// fn f(){(print!(á
|
||||
// ```
|
||||
use rustc_ast::visit::{walk_expr, Visitor};
|
||||
struct ErrExprVisitor {
|
||||
has_error: bool,
|
||||
}
|
||||
impl<'ast> Visitor<'ast> for ErrExprVisitor {
|
||||
fn visit_expr(&mut self, expr: &'ast ast::Expr) {
|
||||
if let ExprKind::Err = expr.kind {
|
||||
self.has_error = true;
|
||||
return;
|
||||
}
|
||||
walk_expr(self, expr)
|
||||
}
|
||||
}
|
||||
let mut visitor = ErrExprVisitor { has_error: false };
|
||||
visitor.visit_expr(value);
|
||||
if visitor.has_error {
|
||||
return;
|
||||
}
|
||||
let spans = match value.kind {
|
||||
ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
|
||||
if let StmtKind::Expr(expr) = &block.stmts[0].kind
|
||||
&& let ExprKind::Err = expr.kind
|
||||
{
|
||||
return
|
||||
}
|
||||
if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
|
||||
Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -205,7 +205,12 @@ enum class LLVMRustCodeModel {
|
|||
None,
|
||||
};
|
||||
|
||||
static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
static Optional<CodeModel::Model>
|
||||
#else
|
||||
static std::optional<CodeModel::Model>
|
||||
#endif
|
||||
fromRust(LLVMRustCodeModel Model) {
|
||||
switch (Model) {
|
||||
case LLVMRustCodeModel::Tiny:
|
||||
return CodeModel::Tiny;
|
||||
|
|
@ -638,7 +643,11 @@ LLVMRustOptimize(
|
|||
LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
Optional<PGOOptions> PGOOpt;
|
||||
#else
|
||||
std::optional<PGOOptions> PGOOpt;
|
||||
#endif
|
||||
if (PGOGenPath) {
|
||||
assert(!PGOUsePath && !PGOSampleUsePath);
|
||||
PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
#include "llvm/Pass.h"
|
||||
#include "llvm/Bitcode/BitcodeWriter.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
|
@ -708,7 +710,11 @@ enum class LLVMRustChecksumKind {
|
|||
SHA256,
|
||||
};
|
||||
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
|
||||
#else
|
||||
static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
|
||||
#endif
|
||||
switch (Kind) {
|
||||
case LLVMRustChecksumKind::None:
|
||||
return None;
|
||||
|
|
@ -787,8 +793,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
|
|||
const char *Filename, size_t FilenameLen,
|
||||
const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
|
||||
const char *Checksum, size_t ChecksumLen) {
|
||||
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
|
||||
#else
|
||||
std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_LT(16, 0)
|
||||
Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
|
||||
#else
|
||||
std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
|
||||
#endif
|
||||
if (llvmCSKind)
|
||||
CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
|
||||
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
|
||||
|
|
|
|||
|
|
@ -364,10 +364,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
|||
modifiers.eval_always.is_none(),
|
||||
"Query {name} cannot be both `feedable` and `eval_always`."
|
||||
);
|
||||
assert!(
|
||||
modifiers.no_hash.is_none(),
|
||||
"Query {name} cannot be both `feedable` and `no_hash`."
|
||||
);
|
||||
feedable_queries.extend(quote! {
|
||||
#(#doc_comments)*
|
||||
[#attribute_stream] fn #name(#arg) #result,
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ impl<'a> CrateLoader<'a> {
|
|||
pub fn new(
|
||||
sess: &'a Session,
|
||||
metadata_loader: Box<MetadataLoaderDyn>,
|
||||
local_crate_name: &str,
|
||||
local_crate_name: Symbol,
|
||||
) -> Self {
|
||||
let mut stable_crate_ids = FxHashMap::default();
|
||||
stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
|
||||
|
|
@ -253,7 +253,7 @@ impl<'a> CrateLoader<'a> {
|
|||
CrateLoader {
|
||||
sess,
|
||||
metadata_loader,
|
||||
local_crate_name: Symbol::intern(local_crate_name),
|
||||
local_crate_name,
|
||||
cstore: CStore {
|
||||
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
|
||||
// order to make array indices in `metas` match with the
|
||||
|
|
@ -1000,7 +1000,7 @@ impl<'a> CrateLoader<'a> {
|
|||
);
|
||||
let name = match orig_name {
|
||||
Some(orig_name) => {
|
||||
validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
|
||||
validate_crate_name(self.sess, orig_name, Some(item.span));
|
||||
orig_name
|
||||
}
|
||||
None => item.ident.name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::{encode_metadata, EncodedMetadata};
|
|||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{CrateType, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{CrateType, OutputType};
|
||||
use rustc_session::output::filename_for_metadata;
|
||||
use rustc_session::Session;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
|
@ -38,10 +38,7 @@ pub fn emit_wrapper_file(
|
|||
out_filename
|
||||
}
|
||||
|
||||
pub fn encode_and_write_metadata(
|
||||
tcx: TyCtxt<'_>,
|
||||
outputs: &OutputFilenames,
|
||||
) -> (EncodedMetadata, bool) {
|
||||
pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MetadataKind {
|
||||
None,
|
||||
|
|
@ -64,7 +61,7 @@ pub fn encode_and_write_metadata(
|
|||
.unwrap_or(MetadataKind::None);
|
||||
|
||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||
let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs);
|
||||
let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
|
||||
// To avoid races with another rustc process scanning the output directory,
|
||||
// we need to write the file somewhere else and atomically move it to its
|
||||
// final destination, with an `fs::rename` call. In order for the rename to
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(rustc::usage_of_ty_tykind)]
|
||||
|
||||
/// This higher-order macro declares a list of types which can be allocated by `Arena`.
|
||||
///
|
||||
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type
|
||||
|
|
@ -28,6 +30,7 @@ macro_rules! arena_types {
|
|||
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
|
||||
[decode] borrowck_result:
|
||||
rustc_middle::mir::BorrowCheckResult<'tcx>,
|
||||
[] resolver: rustc_data_structures::steal::Steal<rustc_middle::ty::ResolverAstLowering>,
|
||||
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
|
||||
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
|
||||
[] const_allocs: rustc_middle::mir::interpret::Allocation,
|
||||
|
|
@ -88,8 +91,8 @@ macro_rules! arena_types {
|
|||
[] hir_id_set: rustc_hir::HirIdSet,
|
||||
|
||||
// Interned types
|
||||
[] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,
|
||||
[] predicates: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::PredicateS<'tcx>>,
|
||||
[] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
|
||||
[] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
|
||||
[] consts: rustc_middle::ty::ConstS<'tcx>,
|
||||
|
||||
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue