mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 18:23:49 +00:00
Auto merge of #73751 - eddyb:no-empty-tables, r=nikomatsakis
Remove `TypeckTables::empty(None)` and make hir_owner non-optional. Each commit before the last one removes uses of `TypeckTables::empty(None)`, replacing the empty tables with having `Option` around the `&'tcx TypeckTables<'tcx>` that HIR visitors kept track of. The last commit removes the concept of "empty `TypeckTables`" altogether, guaranteeing that every `TypeckTables` corresponds to a HIR body owner. r? @nikomatsakis
This commit is contained in:
commit
3503f565e1
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
#![cfg_attr(bootstrap, feature(track_caller))]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -80,8 +80,7 @@ where
|
|||||||
PpmTyped => {
|
PpmTyped => {
|
||||||
abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
|
abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
|
||||||
|
|
||||||
let empty_tables = ty::TypeckTables::empty(None);
|
let annotation = TypedAnnotation { tcx, maybe_typeck_tables: Cell::new(None) };
|
||||||
let annotation = TypedAnnotation { tcx, tables: Cell::new(&empty_tables) };
|
|
||||||
tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate()))
|
tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate()))
|
||||||
}
|
}
|
||||||
_ => panic!("Should use call_with_pp_support"),
|
_ => panic!("Should use call_with_pp_support"),
|
||||||
@ -304,12 +303,22 @@ impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypedAnnotation<'a, 'tcx> {
|
struct TypedAnnotation<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: Cell<&'a ty::TypeckTables<'tcx>>,
|
maybe_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
|
impl<'tcx> TypedAnnotation<'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.get().expect("`TypedAnnotation::tables` called outside of body")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
|
||||||
fn sess(&self) -> &Session {
|
fn sess(&self) -> &Session {
|
||||||
&self.tcx.sess
|
&self.tcx.sess
|
||||||
}
|
}
|
||||||
@ -327,15 +336,15 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
|
impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
|
||||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
|
||||||
let old_tables = self.tables.get();
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.get();
|
||||||
if let pprust_hir::Nested::Body(id) = nested {
|
if let pprust_hir::Nested::Body(id) = nested {
|
||||||
self.tables.set(self.tcx.body_tables(id));
|
self.maybe_typeck_tables.set(Some(self.tcx.body_tables(id)));
|
||||||
}
|
}
|
||||||
let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
|
let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
|
||||||
pprust_hir::PpAnn::nested(pp_ann, state, nested);
|
pprust_hir::PpAnn::nested(pp_ann, state, nested);
|
||||||
self.tables.set(old_tables);
|
self.maybe_typeck_tables.set(old_maybe_typeck_tables);
|
||||||
}
|
}
|
||||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
|
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
|
||||||
if let pprust_hir::AnnNode::Expr(_) = node {
|
if let pprust_hir::AnnNode::Expr(_) = node {
|
||||||
@ -347,7 +356,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
|
|||||||
s.s.space();
|
s.s.space();
|
||||||
s.s.word("as");
|
s.s.word("as");
|
||||||
s.s.space();
|
s.s.space();
|
||||||
s.s.word(self.tables.get().expr_ty(expr).to_string());
|
s.s.word(self.tables().expr_ty(expr).to_string());
|
||||||
s.pclose();
|
s.pclose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1684,7 +1684,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// Attempt to obtain the span of the parameter so we can
|
// Attempt to obtain the span of the parameter so we can
|
||||||
// suggest adding an explicit lifetime bound to it.
|
// suggest adding an explicit lifetime bound to it.
|
||||||
let generics =
|
let generics =
|
||||||
self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
|
self.in_progress_tables.map(|table| table.borrow().hir_owner).map(|table_owner| {
|
||||||
let hir_id = hir.as_local_hir_id(table_owner);
|
let hir_id = hir.as_local_hir_id(table_owner);
|
||||||
let parent_id = hir.get_parent_item(hir_id);
|
let parent_id = hir.get_parent_item(hir_id);
|
||||||
(
|
(
|
||||||
|
@ -588,7 +588,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||||||
/// Used only by `rustc_typeck` during body type-checking/inference,
|
/// Used only by `rustc_typeck` during body type-checking/inference,
|
||||||
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
|
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
|
||||||
pub fn with_fresh_in_progress_tables(mut self, table_owner: LocalDefId) -> Self {
|
pub fn with_fresh_in_progress_tables(mut self, table_owner: LocalDefId) -> Self {
|
||||||
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner))));
|
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::new(table_owner)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
|
|||||||
.pat_ty(pat)
|
.pat_ty(pat)
|
||||||
.ty_adt_def()
|
.ty_adt_def()
|
||||||
.expect("struct pattern type is not an ADT")
|
.expect("struct pattern type is not an ADT")
|
||||||
.variant_of_res(cx.tables().qpath_res(qpath, pat.hir_id));
|
.variant_of_res(cx.qpath_res(qpath, pat.hir_id));
|
||||||
for fieldpat in field_pats {
|
for fieldpat in field_pats {
|
||||||
if fieldpat.is_shorthand {
|
if fieldpat.is_shorthand {
|
||||||
continue;
|
continue;
|
||||||
@ -901,7 +901,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
|
|||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
|
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
|
||||||
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
|
||||||
cx.tables().qpath_res(qpath, expr.hir_id)
|
cx.qpath_res(qpath, expr.hir_id)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
@ -1891,7 +1891,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
|
|||||||
if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
|
if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
|
||||||
// Find calls to `mem::{uninitialized,zeroed}` methods.
|
// Find calls to `mem::{uninitialized,zeroed}` methods.
|
||||||
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
||||||
let def_id = cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||||
|
|
||||||
if cx.tcx.is_diagnostic_item(sym::mem_zeroed, def_id) {
|
if cx.tcx.is_diagnostic_item(sym::mem_zeroed, def_id) {
|
||||||
return Some(InitKind::Zeroed);
|
return Some(InitKind::Zeroed);
|
||||||
@ -1911,8 +1911,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
|
|||||||
// See if the `self` parameter is one of the dangerous constructors.
|
// See if the `self` parameter is one of the dangerous constructors.
|
||||||
if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
|
if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
|
||||||
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
||||||
let def_id =
|
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||||
cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
|
||||||
|
|
||||||
if cx.tcx.is_diagnostic_item(sym::maybe_uninit_zeroed, def_id) {
|
if cx.tcx.is_diagnostic_item(sym::maybe_uninit_zeroed, def_id) {
|
||||||
return Some(InitKind::Zeroed);
|
return Some(InitKind::Zeroed);
|
||||||
|
@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxHashMap;
|
|||||||
use rustc_data_structures::sync;
|
use rustc_data_structures::sync;
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||||
@ -427,15 +428,12 @@ pub struct LateContext<'a, 'tcx> {
|
|||||||
/// Current body, or `None` if outside a body.
|
/// Current body, or `None` if outside a body.
|
||||||
pub enclosing_body: Option<hir::BodyId>,
|
pub enclosing_body: Option<hir::BodyId>,
|
||||||
|
|
||||||
/// Type-checking side-tables for the current body. Access using the
|
/// Type-checking side-tables for the current body. Access using the `tables`
|
||||||
/// `tables` method, which handles querying the tables on demand.
|
/// and `maybe_tables` methods, which handle querying the tables on demand.
|
||||||
// FIXME(eddyb) move all the code accessing internal fields like this,
|
// FIXME(eddyb) move all the code accessing internal fields like this,
|
||||||
// to this module, to avoid exposing it to lint logic.
|
// to this module, to avoid exposing it to lint logic.
|
||||||
pub(super) cached_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>,
|
pub(super) cached_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>,
|
||||||
|
|
||||||
// HACK(eddyb) replace this with having `Option` around `&TypeckTables`.
|
|
||||||
pub(super) empty_typeck_tables: &'a ty::TypeckTables<'tcx>,
|
|
||||||
|
|
||||||
/// Parameter environment for the item we are in.
|
/// Parameter environment for the item we are in.
|
||||||
pub param_env: ty::ParamEnv<'tcx>,
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
@ -677,18 +675,35 @@ impl LintContext for EarlyContext<'_> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
||||||
/// Gets the type-checking side-tables for the current body,
|
/// Gets the type-checking side-tables for the current body,
|
||||||
/// or empty `TypeckTables` if outside a body.
|
/// or `None` if outside a body.
|
||||||
// FIXME(eddyb) return `Option<&'tcx ty::TypeckTables<'tcx>>`,
|
pub fn maybe_typeck_tables(&self) -> Option<&'tcx ty::TypeckTables<'tcx>> {
|
||||||
// where `None` indicates we're outside a body.
|
self.cached_typeck_tables.get().or_else(|| {
|
||||||
pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
|
self.enclosing_body.map(|body| {
|
||||||
if let Some(body) = self.enclosing_body {
|
|
||||||
self.cached_typeck_tables.get().unwrap_or_else(|| {
|
|
||||||
let tables = self.tcx.body_tables(body);
|
let tables = self.tcx.body_tables(body);
|
||||||
self.cached_typeck_tables.set(Some(tables));
|
self.cached_typeck_tables.set(Some(tables));
|
||||||
tables
|
tables
|
||||||
})
|
})
|
||||||
} else {
|
})
|
||||||
self.empty_typeck_tables
|
}
|
||||||
|
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
pub fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables().expect("`LateContext::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the final resolution of a `QPath`, or `Res::Err` if unavailable.
|
||||||
|
/// Unlike `.tables().qpath_res(qpath, id)`, this can be used even outside
|
||||||
|
/// bodies (e.g. for paths in `hir::Ty`), without any risk of ICE-ing.
|
||||||
|
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||||
|
match *qpath {
|
||||||
|
hir::QPath::Resolved(_, ref path) => path.res,
|
||||||
|
hir::QPath::TypeRelative(..) => self
|
||||||
|
.maybe_typeck_tables()
|
||||||
|
.and_then(|tables| tables.type_dependent_def(id))
|
||||||
|
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +378,6 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
|||||||
tcx,
|
tcx,
|
||||||
enclosing_body: None,
|
enclosing_body: None,
|
||||||
cached_typeck_tables: Cell::new(None),
|
cached_typeck_tables: Cell::new(None),
|
||||||
empty_typeck_tables: &ty::TypeckTables::empty(None),
|
|
||||||
param_env: ty::ParamEnv::empty(),
|
param_env: ty::ParamEnv::empty(),
|
||||||
access_levels,
|
access_levels,
|
||||||
lint_store: unerased_lint_store(tcx),
|
lint_store: unerased_lint_store(tcx),
|
||||||
@ -427,7 +426,6 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
|
|||||||
tcx,
|
tcx,
|
||||||
enclosing_body: None,
|
enclosing_body: None,
|
||||||
cached_typeck_tables: Cell::new(None),
|
cached_typeck_tables: Cell::new(None),
|
||||||
empty_typeck_tables: &ty::TypeckTables::empty(None),
|
|
||||||
param_env: ty::ParamEnv::empty(),
|
param_env: ty::ParamEnv::empty(),
|
||||||
access_levels,
|
access_levels,
|
||||||
lint_store: unerased_lint_store(tcx),
|
lint_store: unerased_lint_store(tcx),
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
#![cfg_attr(bootstrap, feature(track_caller))]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
|||||||
hir::ExprKind::Call(ref callee, _) => {
|
hir::ExprKind::Call(ref callee, _) => {
|
||||||
match callee.kind {
|
match callee.kind {
|
||||||
hir::ExprKind::Path(ref qpath) => {
|
hir::ExprKind::Path(ref qpath) => {
|
||||||
match cx.tables().qpath_res(qpath, callee.hir_id) {
|
match cx.qpath_res(qpath, callee.hir_id) {
|
||||||
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
|
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
|
||||||
// `Res::Local` if it was a closure, for which we
|
// `Res::Local` if it was a closure, for which we
|
||||||
// do not currently support must-use linting
|
// do not currently support must-use linting
|
||||||
|
@ -188,7 +188,7 @@ pub struct CommonConsts<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct LocalTableInContext<'a, V> {
|
pub struct LocalTableInContext<'a, V> {
|
||||||
hir_owner: Option<LocalDefId>,
|
hir_owner: LocalDefId,
|
||||||
data: &'a ItemLocalMap<V>,
|
data: &'a ItemLocalMap<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,12 +199,7 @@ pub struct LocalTableInContext<'a, V> {
|
|||||||
/// would be in a different frame of reference and using its `local_id`
|
/// would be in a different frame of reference and using its `local_id`
|
||||||
/// would result in lookup errors, or worse, in silently wrong data being
|
/// would result in lookup errors, or worse, in silently wrong data being
|
||||||
/// stored/returned.
|
/// stored/returned.
|
||||||
fn validate_hir_id_for_typeck_tables(
|
fn validate_hir_id_for_typeck_tables(hir_owner: LocalDefId, hir_id: hir::HirId) {
|
||||||
hir_owner: Option<LocalDefId>,
|
|
||||||
hir_id: hir::HirId,
|
|
||||||
mut_access: bool,
|
|
||||||
) {
|
|
||||||
if let Some(hir_owner) = hir_owner {
|
|
||||||
if hir_id.owner != hir_owner {
|
if hir_id.owner != hir_owner {
|
||||||
ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
bug!(
|
bug!(
|
||||||
@ -215,26 +210,16 @@ fn validate_hir_id_for_typeck_tables(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// We use "Null Object" TypeckTables in some of the analysis passes.
|
|
||||||
// These are just expected to be empty and their `hir_owner` is
|
|
||||||
// `None`. Therefore we cannot verify whether a given `HirId` would
|
|
||||||
// be a valid key for the given table. Instead we make sure that
|
|
||||||
// nobody tries to write to such a Null Object table.
|
|
||||||
if mut_access {
|
|
||||||
bug!("access to invalid TypeckTables")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V> LocalTableInContext<'a, V> {
|
impl<'a, V> LocalTableInContext<'a, V> {
|
||||||
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.contains_key(&id.local_id)
|
self.data.contains_key(&id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.get(&id.local_id)
|
self.data.get(&id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,28 +237,28 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct LocalTableInContextMut<'a, V> {
|
pub struct LocalTableInContextMut<'a, V> {
|
||||||
hir_owner: Option<LocalDefId>,
|
hir_owner: LocalDefId,
|
||||||
data: &'a mut ItemLocalMap<V>,
|
data: &'a mut ItemLocalMap<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, V> LocalTableInContextMut<'a, V> {
|
impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||||
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.get_mut(&id.local_id)
|
self.data.get_mut(&id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.entry(id.local_id)
|
self.data.entry(id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.insert(id.local_id, val)
|
self.data.insert(id.local_id, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.data.remove(&id.local_id)
|
self.data.remove(&id.local_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +309,7 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
|
|||||||
#[derive(RustcEncodable, RustcDecodable, Debug)]
|
#[derive(RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct TypeckTables<'tcx> {
|
pub struct TypeckTables<'tcx> {
|
||||||
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
||||||
pub hir_owner: Option<LocalDefId>,
|
pub hir_owner: LocalDefId,
|
||||||
|
|
||||||
/// Resolved definitions for `<T>::X` associated paths and
|
/// Resolved definitions for `<T>::X` associated paths and
|
||||||
/// method calls, including those of overloaded operators.
|
/// method calls, including those of overloaded operators.
|
||||||
@ -432,7 +417,7 @@ pub struct TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeckTables<'tcx> {
|
impl<'tcx> TypeckTables<'tcx> {
|
||||||
pub fn empty(hir_owner: Option<LocalDefId>) -> TypeckTables<'tcx> {
|
pub fn new(hir_owner: LocalDefId) -> TypeckTables<'tcx> {
|
||||||
TypeckTables {
|
TypeckTables {
|
||||||
hir_owner,
|
hir_owner,
|
||||||
type_dependent_defs: Default::default(),
|
type_dependent_defs: Default::default(),
|
||||||
@ -474,7 +459,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +506,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.node_types.get(&id.local_id).cloned()
|
self.node_types.get(&id.local_id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,12 +515,12 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, id);
|
||||||
self.node_substs.get(&id.local_id).cloned()
|
self.node_substs.get(&id.local_id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +563,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id, false);
|
validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id);
|
||||||
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,7 +642,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
||||||
validate_hir_id_for_typeck_tables(self.hir_owner, hir_id, true);
|
validate_hir_id_for_typeck_tables(self.hir_owner, hir_id);
|
||||||
self.coercion_casts.contains(&hir_id.local_id)
|
self.coercion_casts.contains(&hir_id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +695,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
|
|||||||
hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
|
hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
|
||||||
let ty::UpvarId { var_path, closure_expr_id } = *up_var_id;
|
let ty::UpvarId { var_path, closure_expr_id } = *up_var_id;
|
||||||
|
|
||||||
assert_eq!(Some(var_path.hir_id.owner), hir_owner);
|
assert_eq!(var_path.hir_id.owner, hir_owner);
|
||||||
|
|
||||||
(
|
(
|
||||||
hcx.local_def_path_hash(var_path.hir_id.owner),
|
hcx.local_def_path_hash(var_path.hir_id.owner),
|
||||||
|
@ -37,10 +37,10 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MarkSymbolVisitor<'a, 'tcx> {
|
struct MarkSymbolVisitor<'tcx> {
|
||||||
worklist: Vec<hir::HirId>,
|
worklist: Vec<hir::HirId>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: &'a ty::TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>,
|
||||||
live_symbols: FxHashSet<hir::HirId>,
|
live_symbols: FxHashSet<hir::HirId>,
|
||||||
repr_has_repr_c: bool,
|
repr_has_repr_c: bool,
|
||||||
in_pat: bool,
|
in_pat: bool,
|
||||||
@ -50,7 +50,15 @@ struct MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
|
struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.expect("`MarkSymbolVisitor::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
fn check_def_id(&mut self, def_id: DefId) {
|
fn check_def_id(&mut self, def_id: DefId) {
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
let hir_id = self.tcx.hir().as_local_hir_id(def_id);
|
let hir_id = self.tcx.hir().as_local_hir_id(def_id);
|
||||||
@ -107,7 +115,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_and_handle_method(&mut self, id: hir::HirId) {
|
fn lookup_and_handle_method(&mut self, id: hir::HirId) {
|
||||||
if let Some(def_id) = self.tables.type_dependent_def_id(id) {
|
if let Some(def_id) = self.tables().type_dependent_def_id(id) {
|
||||||
self.check_def_id(def_id);
|
self.check_def_id(def_id);
|
||||||
} else {
|
} else {
|
||||||
bug!("no type-dependent def for method");
|
bug!("no type-dependent def for method");
|
||||||
@ -115,9 +123,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
|
fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
|
||||||
match self.tables.expr_ty_adjusted(lhs).kind {
|
match self.tables().expr_ty_adjusted(lhs).kind {
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
let index = self.tcx.field_index(hir_id, self.tables);
|
let index = self.tcx.field_index(hir_id, self.tables());
|
||||||
self.insert_def_id(def.non_enum_variant().fields[index].did);
|
self.insert_def_id(def.non_enum_variant().fields[index].did);
|
||||||
}
|
}
|
||||||
ty::Tuple(..) => {}
|
ty::Tuple(..) => {}
|
||||||
@ -131,7 +139,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
res: Res,
|
res: Res,
|
||||||
pats: &[hir::FieldPat<'_>],
|
pats: &[hir::FieldPat<'_>],
|
||||||
) {
|
) {
|
||||||
let variant = match self.tables.node_type(lhs.hir_id).kind {
|
let variant = match self.tables().node_type(lhs.hir_id).kind {
|
||||||
ty::Adt(adt, _) => adt.variant_of_res(res),
|
ty::Adt(adt, _) => adt.variant_of_res(res),
|
||||||
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
|
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
|
||||||
};
|
};
|
||||||
@ -139,7 +147,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
if let PatKind::Wild = pat.pat.kind {
|
if let PatKind::Wild = pat.pat.kind {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let index = self.tcx.field_index(pat.hir_id, self.tables);
|
let index = self.tcx.field_index(pat.hir_id, self.tables());
|
||||||
self.insert_def_id(variant.fields[index].did);
|
self.insert_def_id(variant.fields[index].did);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,14 +212,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::Field<'_>]) {
|
fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::Field<'_>]) {
|
||||||
if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() {
|
if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let index = self.tcx.field_index(field.hir_id, self.tables);
|
let index = self.tcx.field_index(field.hir_id, self.tables());
|
||||||
self.insert_def_id(adt.non_enum_variant().fields[index].did);
|
self.insert_def_id(adt.non_enum_variant().fields[index].did);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
|
||||||
type Map = intravisit::ErasedMap<'tcx>;
|
type Map = intravisit::ErasedMap<'tcx>;
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
||||||
@ -219,11 +227,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let old_tables = self.tables;
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body));
|
||||||
self.tables = self.tcx.body_tables(body);
|
|
||||||
let body = self.tcx.hir().body(body);
|
let body = self.tcx.hir().body(body);
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
self.tables = old_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variant_data(
|
fn visit_variant_data(
|
||||||
@ -248,7 +255,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
hir::ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
||||||
let res = self.tables.qpath_res(qpath, expr.hir_id);
|
let res = self.tables().qpath_res(qpath, expr.hir_id);
|
||||||
self.handle_res(res);
|
self.handle_res(res);
|
||||||
}
|
}
|
||||||
hir::ExprKind::MethodCall(..) => {
|
hir::ExprKind::MethodCall(..) => {
|
||||||
@ -258,9 +265,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
self.handle_field_access(&lhs, expr.hir_id);
|
self.handle_field_access(&lhs, expr.hir_id);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Struct(ref qpath, ref fields, _) => {
|
hir::ExprKind::Struct(ref qpath, ref fields, _) => {
|
||||||
let res = self.tables.qpath_res(qpath, expr.hir_id);
|
let res = self.tables().qpath_res(qpath, expr.hir_id);
|
||||||
self.handle_res(res);
|
self.handle_res(res);
|
||||||
if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).kind {
|
if let ty::Adt(ref adt, _) = self.tables().expr_ty(expr).kind {
|
||||||
self.mark_as_used_if_union(adt, fields);
|
self.mark_as_used_if_union(adt, fields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,11 +290,11 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
|||||||
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
|
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
PatKind::Struct(ref path, ref fields, _) => {
|
PatKind::Struct(ref path, ref fields, _) => {
|
||||||
let res = self.tables.qpath_res(path, pat.hir_id);
|
let res = self.tables().qpath_res(path, pat.hir_id);
|
||||||
self.handle_field_pattern_match(pat, res, fields);
|
self.handle_field_pattern_match(pat, res, fields);
|
||||||
}
|
}
|
||||||
PatKind::Path(ref qpath) => {
|
PatKind::Path(ref qpath) => {
|
||||||
let res = self.tables.qpath_res(qpath, pat.hir_id);
|
let res = self.tables().qpath_res(qpath, pat.hir_id);
|
||||||
self.handle_res(res);
|
self.handle_res(res);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@ -473,7 +480,7 @@ fn find_live<'tcx>(
|
|||||||
let mut symbol_visitor = MarkSymbolVisitor {
|
let mut symbol_visitor = MarkSymbolVisitor {
|
||||||
worklist,
|
worklist,
|
||||||
tcx,
|
tcx,
|
||||||
tables: &ty::TypeckTables::empty(None),
|
maybe_typeck_tables: None,
|
||||||
live_symbols: Default::default(),
|
live_symbols: Default::default(),
|
||||||
repr_has_repr_c: false,
|
repr_has_repr_c: false,
|
||||||
in_pat: false,
|
in_pat: false,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
#![cfg_attr(bootstrap, feature(track_caller))]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -60,10 +60,10 @@ fn method_might_be_inlined(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Information needed while computing reachability.
|
// Information needed while computing reachability.
|
||||||
struct ReachableContext<'a, 'tcx> {
|
struct ReachableContext<'tcx> {
|
||||||
// The type context.
|
// The type context.
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: &'a ty::TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>,
|
||||||
// The set of items which must be exported in the linkage sense.
|
// The set of items which must be exported in the linkage sense.
|
||||||
reachable_symbols: HirIdSet,
|
reachable_symbols: HirIdSet,
|
||||||
// A worklist of item IDs. Each item ID in this worklist will be inlined
|
// A worklist of item IDs. Each item ID in this worklist will be inlined
|
||||||
@ -73,7 +73,7 @@ struct ReachableContext<'a, 'tcx> {
|
|||||||
any_library: bool,
|
any_library: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
|
||||||
type Map = intravisit::ErasedMap<'tcx>;
|
type Map = intravisit::ErasedMap<'tcx>;
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||||
@ -81,18 +81,17 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let old_tables = self.tables;
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body));
|
||||||
self.tables = self.tcx.body_tables(body);
|
|
||||||
let body = self.tcx.hir().body(body);
|
let body = self.tcx.hir().body(body);
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
self.tables = old_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||||
let res = match expr.kind {
|
let res = match expr.kind {
|
||||||
hir::ExprKind::Path(ref qpath) => Some(self.tables.qpath_res(qpath, expr.hir_id)),
|
hir::ExprKind::Path(ref qpath) => Some(self.tables().qpath_res(qpath, expr.hir_id)),
|
||||||
hir::ExprKind::MethodCall(..) => self
|
hir::ExprKind::MethodCall(..) => self
|
||||||
.tables
|
.tables()
|
||||||
.type_dependent_def(expr.hir_id)
|
.type_dependent_def(expr.hir_id)
|
||||||
.map(|(kind, def_id)| Res::Def(kind, def_id)),
|
.map(|(kind, def_id)| Res::Def(kind, def_id)),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -133,7 +132,15 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
impl<'tcx> ReachableContext<'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.expect("`ReachableContext::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if the given def ID represents a local item that is
|
// Returns true if the given def ID represents a local item that is
|
||||||
// eligible for inlining and false otherwise.
|
// eligible for inlining and false otherwise.
|
||||||
fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
|
fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
|
||||||
@ -381,7 +388,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
|
|||||||
});
|
});
|
||||||
let mut reachable_context = ReachableContext {
|
let mut reachable_context = ReachableContext {
|
||||||
tcx,
|
tcx,
|
||||||
tables: &ty::TypeckTables::empty(None),
|
maybe_typeck_tables: None,
|
||||||
reachable_symbols: Default::default(),
|
reachable_symbols: Default::default(),
|
||||||
worklist: Vec::new(),
|
worklist: Vec::new(),
|
||||||
any_library,
|
any_library,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
#![cfg_attr(bootstrap, feature(track_caller))]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
@ -345,17 +346,6 @@ fn def_id_visibility<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the correct `TypeckTables` for the given `item_id` (or an empty table if
|
|
||||||
// there is no `TypeckTables` for the item).
|
|
||||||
fn item_tables<'a, 'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
hir_id: hir::HirId,
|
|
||||||
empty_tables: &'a ty::TypeckTables<'tcx>,
|
|
||||||
) -> &'a ty::TypeckTables<'tcx> {
|
|
||||||
let def_id = tcx.hir().local_def_id(hir_id);
|
|
||||||
if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
|
fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
|
||||||
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
|
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
|
||||||
}
|
}
|
||||||
@ -1029,14 +1019,21 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
|||||||
/// This pass performs remaining checks for fields in struct expressions and patterns.
|
/// This pass performs remaining checks for fields in struct expressions and patterns.
|
||||||
//////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct NamePrivacyVisitor<'a, 'tcx> {
|
struct NamePrivacyVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: &'a ty::TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>,
|
||||||
current_item: Option<hir::HirId>,
|
current_item: Option<hir::HirId>,
|
||||||
empty_tables: &'a ty::TypeckTables<'tcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
|
impl<'tcx> NamePrivacyVisitor<'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.expect("`NamePrivacyVisitor::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
// Checks that a field in a struct constructor (expression or pattern) is accessible.
|
// Checks that a field in a struct constructor (expression or pattern) is accessible.
|
||||||
fn check_field(
|
fn check_field(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -1072,7 +1069,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||||
type Map = Map<'tcx>;
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
/// We want to visit items in the context of their containing
|
/// We want to visit items in the context of their containing
|
||||||
@ -1087,39 +1084,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body));
|
||||||
let body = self.tcx.hir().body(body);
|
let body = self.tcx.hir().body(body);
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
self.tables = orig_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||||
let orig_current_item = mem::replace(&mut self.current_item, Some(item.hir_id));
|
let orig_current_item = self.current_item.replace(item.hir_id);
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
self.current_item = orig_current_item;
|
self.current_item = orig_current_item;
|
||||||
self.tables = orig_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
|
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_trait_item(self, ti);
|
|
||||||
self.tables = orig_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
|
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_impl_item(self, ii);
|
|
||||||
self.tables = orig_tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||||
if let hir::ExprKind::Struct(ref qpath, fields, ref base) = expr.kind {
|
if let hir::ExprKind::Struct(ref qpath, fields, ref base) = expr.kind {
|
||||||
let res = self.tables.qpath_res(qpath, expr.hir_id);
|
let res = self.tables().qpath_res(qpath, expr.hir_id);
|
||||||
let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap();
|
let adt = self.tables().expr_ty(expr).ty_adt_def().unwrap();
|
||||||
let variant = adt.variant_of_res(res);
|
let variant = adt.variant_of_res(res);
|
||||||
if let Some(ref base) = *base {
|
if let Some(ref base) = *base {
|
||||||
// If the expression uses FRU we need to make sure all the unmentioned fields
|
// If the expression uses FRU we need to make sure all the unmentioned fields
|
||||||
@ -1128,7 +1108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
for (vf_index, variant_field) in variant.fields.iter().enumerate() {
|
for (vf_index, variant_field) in variant.fields.iter().enumerate() {
|
||||||
let field = fields
|
let field = fields
|
||||||
.iter()
|
.iter()
|
||||||
.find(|f| self.tcx.field_index(f.hir_id, self.tables) == vf_index);
|
.find(|f| self.tcx.field_index(f.hir_id, self.tables()) == vf_index);
|
||||||
let (use_ctxt, span) = match field {
|
let (use_ctxt, span) = match field {
|
||||||
Some(field) => (field.ident.span, field.span),
|
Some(field) => (field.ident.span, field.span),
|
||||||
None => (base.span, base.span),
|
None => (base.span, base.span),
|
||||||
@ -1138,7 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let use_ctxt = field.ident.span;
|
let use_ctxt = field.ident.span;
|
||||||
let index = self.tcx.field_index(field.hir_id, self.tables);
|
let index = self.tcx.field_index(field.hir_id, self.tables());
|
||||||
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1149,12 +1129,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
|
|
||||||
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
|
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
|
||||||
if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
|
if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
|
||||||
let res = self.tables.qpath_res(qpath, pat.hir_id);
|
let res = self.tables().qpath_res(qpath, pat.hir_id);
|
||||||
let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
|
let adt = self.tables().pat_ty(pat).ty_adt_def().unwrap();
|
||||||
let variant = adt.variant_of_res(res);
|
let variant = adt.variant_of_res(res);
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let use_ctxt = field.ident.span;
|
let use_ctxt = field.ident.span;
|
||||||
let index = self.tcx.field_index(field.hir_id, self.tables);
|
let index = self.tcx.field_index(field.hir_id, self.tables());
|
||||||
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1169,16 +1149,22 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
|||||||
/// Checks are performed on "semantic" types regardless of names and their hygiene.
|
/// Checks are performed on "semantic" types regardless of names and their hygiene.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct TypePrivacyVisitor<'a, 'tcx> {
|
struct TypePrivacyVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: &'a ty::TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>,
|
||||||
current_item: LocalDefId,
|
current_item: LocalDefId,
|
||||||
in_body: bool,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
empty_tables: &'a ty::TypeckTables<'tcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
|
impl<'tcx> TypePrivacyVisitor<'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.expect("`TypePrivacyVisitor::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
fn item_is_accessible(&self, did: DefId) -> bool {
|
fn item_is_accessible(&self, did: DefId) -> bool {
|
||||||
def_id_visibility(self.tcx, did)
|
def_id_visibility(self.tcx, did)
|
||||||
.0
|
.0
|
||||||
@ -1188,10 +1174,11 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
// Take node-id of an expression or pattern and check its type for privacy.
|
// Take node-id of an expression or pattern and check its type for privacy.
|
||||||
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
|
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
|
||||||
self.span = span;
|
self.span = span;
|
||||||
if self.visit(self.tables.node_type(id)) || self.visit(self.tables.node_substs(id)) {
|
let tables = self.tables();
|
||||||
|
if self.visit(tables.node_type(id)) || self.visit(tables.node_substs(id)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let Some(adjustments) = self.tables.adjustments().get(id) {
|
if let Some(adjustments) = tables.adjustments().get(id) {
|
||||||
for adjustment in adjustments {
|
for adjustment in adjustments {
|
||||||
if self.visit(adjustment.target) {
|
if self.visit(adjustment.target) {
|
||||||
return true;
|
return true;
|
||||||
@ -1214,7 +1201,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
type Map = Map<'tcx>;
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
/// We want to visit items in the context of their containing
|
/// We want to visit items in the context of their containing
|
||||||
@ -1229,19 +1216,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.tcx.body_tables(body));
|
||||||
let orig_in_body = mem::replace(&mut self.in_body, true);
|
|
||||||
let body = self.tcx.hir().body(body);
|
let body = self.tcx.hir().body(body);
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
self.tables = orig_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
self.in_body = orig_in_body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
|
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
|
||||||
self.span = hir_ty.span;
|
self.span = hir_ty.span;
|
||||||
if self.in_body {
|
if let Some(tables) = self.maybe_typeck_tables {
|
||||||
// Types in bodies.
|
// Types in bodies.
|
||||||
if self.visit(self.tables.node_type(hir_ty.hir_id)) {
|
if self.visit(tables.node_type(hir_ty.hir_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1258,7 +1243,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
|
|
||||||
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
|
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
|
||||||
self.span = trait_ref.path.span;
|
self.span = trait_ref.path.span;
|
||||||
if !self.in_body {
|
if self.maybe_typeck_tables.is_none() {
|
||||||
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
|
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
|
||||||
// The traits' privacy in bodies is already checked as a part of trait object types.
|
// The traits' privacy in bodies is already checked as a part of trait object types.
|
||||||
let bounds = rustc_typeck::hir_trait_to_predicates(
|
let bounds = rustc_typeck::hir_trait_to_predicates(
|
||||||
@ -1304,7 +1289,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
hir::ExprKind::MethodCall(_, span, _, _) => {
|
hir::ExprKind::MethodCall(_, span, _, _) => {
|
||||||
// Method calls have to be checked specially.
|
// Method calls have to be checked specially.
|
||||||
self.span = span;
|
self.span = span;
|
||||||
if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {
|
if let Some(def_id) = self.tables().type_dependent_def_id(expr.hir_id) {
|
||||||
if self.visit(self.tcx.type_of(def_id)) {
|
if self.visit(self.tcx.type_of(def_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1327,9 +1312,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
// more code internal visibility at link time. (Access to private functions
|
// more code internal visibility at link time. (Access to private functions
|
||||||
// is already prohibited by type privacy for function types.)
|
// is already prohibited by type privacy for function types.)
|
||||||
fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
|
fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
|
||||||
let def = match self.tables.qpath_res(qpath, id) {
|
let def = match qpath {
|
||||||
|
hir::QPath::Resolved(_, path) => match path.res {
|
||||||
Res::Def(kind, def_id) => Some((kind, def_id)),
|
Res::Def(kind, def_id) => Some((kind, def_id)),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
},
|
||||||
|
hir::QPath::TypeRelative(..) => {
|
||||||
|
self.maybe_typeck_tables.and_then(|tables| tables.type_dependent_def(id))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let def = def.filter(|(kind, _)| match kind {
|
let def = def.filter(|(kind, _)| match kind {
|
||||||
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true,
|
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true,
|
||||||
@ -1385,31 +1375,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
|||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||||
let orig_current_item =
|
let orig_current_item =
|
||||||
mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.hir_id));
|
mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.hir_id));
|
||||||
let orig_in_body = mem::replace(&mut self.in_body, false);
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.take();
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
self.tables = orig_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
self.in_body = orig_in_body;
|
|
||||||
self.current_item = orig_current_item;
|
self.current_item = orig_current_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
|
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_trait_item(self, ti);
|
|
||||||
self.tables = orig_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
|
|
||||||
let orig_tables =
|
|
||||||
mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
|
|
||||||
intravisit::walk_impl_item(self, ii);
|
|
||||||
self.tables = orig_tables;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
@ -2066,29 +2039,16 @@ pub fn provide(providers: &mut Providers<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||||
let empty_tables = ty::TypeckTables::empty(None);
|
|
||||||
|
|
||||||
// Check privacy of names not checked in previous compilation stages.
|
// Check privacy of names not checked in previous compilation stages.
|
||||||
let mut visitor = NamePrivacyVisitor {
|
let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: None };
|
||||||
tcx,
|
|
||||||
tables: &empty_tables,
|
|
||||||
current_item: None,
|
|
||||||
empty_tables: &empty_tables,
|
|
||||||
};
|
|
||||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||||
|
|
||||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||||
|
|
||||||
// Check privacy of explicitly written types and traits as well as
|
// Check privacy of explicitly written types and traits as well as
|
||||||
// inferred types of expressions and patterns.
|
// inferred types of expressions and patterns.
|
||||||
let mut visitor = TypePrivacyVisitor {
|
let mut visitor =
|
||||||
tcx,
|
TypePrivacyVisitor { tcx, maybe_typeck_tables: None, current_item: module_def_id, span };
|
||||||
tables: &empty_tables,
|
|
||||||
current_item: module_def_id,
|
|
||||||
in_body: false,
|
|
||||||
span,
|
|
||||||
empty_tables: &empty_tables,
|
|
||||||
};
|
|
||||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,15 +109,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||||||
F: FnOnce(&mut Self),
|
F: FnOnce(&mut Self),
|
||||||
{
|
{
|
||||||
let tables = if self.tcx.has_typeck_tables(item_def_id) {
|
let tables = if self.tcx.has_typeck_tables(item_def_id) {
|
||||||
self.tcx.typeck_tables_of(item_def_id)
|
Some(self.tcx.typeck_tables_of(item_def_id))
|
||||||
} else {
|
} else {
|
||||||
self.save_ctxt.empty_tables
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let old_tables = self.save_ctxt.tables;
|
let old_maybe_typeck_tables = self.save_ctxt.maybe_typeck_tables;
|
||||||
self.save_ctxt.tables = tables;
|
self.save_ctxt.maybe_typeck_tables = tables;
|
||||||
f(self);
|
f(self);
|
||||||
self.save_ctxt.tables = old_tables;
|
self.save_ctxt.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_from_span(&self, span: Span) -> SpanData {
|
fn span_from_span(&self, span: Span) -> SpanData {
|
||||||
@ -226,7 +226,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||||||
collector.visit_pat(&arg.pat);
|
collector.visit_pat(&arg.pat);
|
||||||
|
|
||||||
for (hir_id, ident, ..) in collector.collected_idents {
|
for (hir_id, ident, ..) in collector.collected_idents {
|
||||||
let typ = match self.save_ctxt.tables.node_type_opt(hir_id) {
|
let typ = match self.save_ctxt.tables().node_type_opt(hir_id) {
|
||||||
Some(s) => s.to_string(),
|
Some(s) => s.to_string(),
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
@ -859,7 +859,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||||||
match p.kind {
|
match p.kind {
|
||||||
hir::PatKind::Struct(ref _path, fields, _) => {
|
hir::PatKind::Struct(ref _path, fields, _) => {
|
||||||
// FIXME do something with _path?
|
// FIXME do something with _path?
|
||||||
let adt = match self.save_ctxt.tables.node_type_opt(p.hir_id) {
|
let adt = match self.save_ctxt.tables().node_type_opt(p.hir_id) {
|
||||||
Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
|
Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
|
||||||
_ => {
|
_ => {
|
||||||
intravisit::walk_pat(self, p);
|
intravisit::walk_pat(self, p);
|
||||||
@ -900,7 +900,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||||||
Res::Local(hir_id) => {
|
Res::Local(hir_id) => {
|
||||||
let typ = self
|
let typ = self
|
||||||
.save_ctxt
|
.save_ctxt
|
||||||
.tables
|
.tables()
|
||||||
.node_type_opt(hir_id)
|
.node_type_opt(hir_id)
|
||||||
.map(|t| t.to_string())
|
.map(|t| t.to_string())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@ -1393,7 +1393,7 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
|
|||||||
match ex.kind {
|
match ex.kind {
|
||||||
hir::ExprKind::Struct(ref path, ref fields, ref base) => {
|
hir::ExprKind::Struct(ref path, ref fields, ref base) => {
|
||||||
let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id);
|
let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id);
|
||||||
let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
|
let adt = match self.save_ctxt.tables().expr_ty_opt(&hir_expr) {
|
||||||
Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
|
Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
|
||||||
_ => {
|
_ => {
|
||||||
intravisit::walk_expr(self, ex);
|
intravisit::walk_expr(self, ex);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
#![cfg_attr(bootstrap, feature(track_caller))]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
mod dump_visitor;
|
mod dump_visitor;
|
||||||
@ -47,12 +48,9 @@ use rls_data::{
|
|||||||
|
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
|
|
||||||
pub struct SaveContext<'l, 'tcx> {
|
pub struct SaveContext<'l, 'tcx: 'l> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
tables: &'l ty::TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx ty::TypeckTables<'tcx>>,
|
||||||
/// Used as a fallback when nesting the typeck tables during item processing
|
|
||||||
/// (if these are not available for that item, e.g. don't own a body)
|
|
||||||
empty_tables: &'l ty::TypeckTables<'tcx>,
|
|
||||||
access_levels: &'l AccessLevels,
|
access_levels: &'l AccessLevels,
|
||||||
span_utils: SpanUtils<'tcx>,
|
span_utils: SpanUtils<'tcx>,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -67,6 +65,14 @@ pub enum Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
||||||
|
/// Gets the type-checking side-tables for the current body.
|
||||||
|
/// As this will ICE if called outside bodies, only call when working with
|
||||||
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
||||||
|
#[track_caller]
|
||||||
|
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
|
||||||
|
self.maybe_typeck_tables.expect("`SaveContext::tables` called outside of body")
|
||||||
|
}
|
||||||
|
|
||||||
fn span_from_span(&self, span: Span) -> SpanData {
|
fn span_from_span(&self, span: Span) -> SpanData {
|
||||||
use rls_span::{Column, Row};
|
use rls_span::{Column, Row};
|
||||||
|
|
||||||
@ -518,13 +524,13 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
|
pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
|
||||||
let ty = self.tables.expr_ty_adjusted_opt(expr)?;
|
let ty = self.tables().expr_ty_adjusted_opt(expr)?;
|
||||||
if matches!(ty.kind, ty::Error(_)) {
|
if matches!(ty.kind, ty::Error(_)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Field(ref sub_ex, ident) => {
|
hir::ExprKind::Field(ref sub_ex, ident) => {
|
||||||
match self.tables.expr_ty_adjusted(&sub_ex).kind {
|
match self.tables().expr_ty_adjusted(&sub_ex).kind {
|
||||||
ty::Adt(def, _) if !def.is_enum() => {
|
ty::Adt(def, _) if !def.is_enum() => {
|
||||||
let variant = &def.non_enum_variant();
|
let variant = &def.non_enum_variant();
|
||||||
filter!(self.span_utils, ident.span);
|
filter!(self.span_utils, ident.span);
|
||||||
@ -569,7 +575,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::MethodCall(ref seg, ..) => {
|
hir::ExprKind::MethodCall(ref seg, ..) => {
|
||||||
let method_id = match self.tables.type_dependent_def_id(expr.hir_id) {
|
let method_id = match self.tables().type_dependent_def_id(expr.hir_id) {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => {
|
None => {
|
||||||
debug!("could not resolve method id for {:?}", expr);
|
debug!("could not resolve method id for {:?}", expr);
|
||||||
@ -618,7 +624,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
|
Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
|
||||||
self.tables.qpath_res(qpath, hir_id)
|
self.tables().qpath_res(qpath, hir_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(ref qpath), .. })
|
Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(ref qpath), .. })
|
||||||
@ -629,9 +635,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||||||
| hir::PatKind::TupleStruct(ref qpath, ..),
|
| hir::PatKind::TupleStruct(ref qpath, ..),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => {
|
| Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => match qpath {
|
||||||
self.tables.qpath_res(qpath, hir_id)
|
hir::QPath::Resolved(_, path) => path.res,
|
||||||
}
|
hir::QPath::TypeRelative(..) => self
|
||||||
|
.maybe_typeck_tables
|
||||||
|
.map_or(Res::Err, |tables| tables.qpath_res(qpath, hir_id)),
|
||||||
|
},
|
||||||
|
|
||||||
Node::Binding(&hir::Pat {
|
Node::Binding(&hir::Pat {
|
||||||
kind: hir::PatKind::Binding(_, canonical_id, ..), ..
|
kind: hir::PatKind::Binding(_, canonical_id, ..), ..
|
||||||
@ -1001,8 +1010,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
|
|||||||
|
|
||||||
let save_ctxt = SaveContext {
|
let save_ctxt = SaveContext {
|
||||||
tcx,
|
tcx,
|
||||||
tables: &ty::TypeckTables::empty(None),
|
maybe_typeck_tables: None,
|
||||||
empty_tables: &ty::TypeckTables::empty(None),
|
|
||||||
access_levels: &access_levels,
|
access_levels: &access_levels,
|
||||||
span_utils: SpanUtils::new(&tcx.sess),
|
span_utils: SpanUtils::new(&tcx.sess),
|
||||||
config: find_config(config),
|
config: find_config(config),
|
||||||
|
@ -1407,7 +1407,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
let query_tables;
|
let query_tables;
|
||||||
let tables: &TypeckTables<'tcx> = match &in_progress_tables {
|
let tables: &TypeckTables<'tcx> = match &in_progress_tables {
|
||||||
Some(t) if t.hir_owner.map(|owner| owner.to_def_id()) == Some(generator_did_root) => t,
|
Some(t) if t.hir_owner.to_def_id() == generator_did_root => t,
|
||||||
_ => {
|
_ => {
|
||||||
query_tables = self.tcx.typeck_tables_of(generator_did.expect_local());
|
query_tables = self.tcx.typeck_tables_of(generator_did.expect_local());
|
||||||
&query_tables
|
&query_tables
|
||||||
|
@ -1039,7 +1039,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let mut suggested = false;
|
let mut suggested = false;
|
||||||
if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) {
|
if let (Some(ref param), Some(ref table)) = (param_type, self.in_progress_tables) {
|
||||||
let table_owner = table.borrow().hir_owner;
|
let table_owner = table.borrow().hir_owner;
|
||||||
if let Some(table_owner) = table_owner {
|
|
||||||
let generics = self.tcx.generics_of(table_owner.to_def_id());
|
let generics = self.tcx.generics_of(table_owner.to_def_id());
|
||||||
let type_param = generics.type_param(param, self.tcx);
|
let type_param = generics.type_param(param, self.tcx);
|
||||||
let hir = &self.tcx.hir();
|
let hir = &self.tcx.hir();
|
||||||
@ -1051,10 +1050,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
match hir.get(id) {
|
match hir.get(id) {
|
||||||
Node::GenericParam(ref param) => {
|
Node::GenericParam(ref param) => {
|
||||||
let mut impl_trait = false;
|
let mut impl_trait = false;
|
||||||
let has_bounds = if let hir::GenericParamKind::Type {
|
let has_bounds =
|
||||||
synthetic: Some(_),
|
if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
|
||||||
..
|
¶m.kind
|
||||||
} = ¶m.kind
|
|
||||||
{
|
{
|
||||||
// We've found `fn foo(x: impl Trait)` instead of
|
// We've found `fn foo(x: impl Trait)` instead of
|
||||||
// `fn foo<T>(x: T)`. We want to suggest the correct
|
// `fn foo<T>(x: T)`. We want to suggest the correct
|
||||||
@ -1122,7 +1120,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !suggested {
|
if !suggested {
|
||||||
|
@ -1126,7 +1126,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
|
|||||||
|
|
||||||
// Consistency check our TypeckTables instance can hold all ItemLocalIds
|
// Consistency check our TypeckTables instance can hold all ItemLocalIds
|
||||||
// it will need to hold.
|
// it will need to hold.
|
||||||
assert_eq!(tables.hir_owner, Some(id.owner));
|
assert_eq!(tables.hir_owner, id.owner);
|
||||||
|
|
||||||
tables
|
tables
|
||||||
}
|
}
|
||||||
|
@ -109,12 +109,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
) -> WritebackCx<'cx, 'tcx> {
|
) -> WritebackCx<'cx, 'tcx> {
|
||||||
let owner = body.id().hir_id.owner;
|
let owner = body.id().hir_id.owner;
|
||||||
|
|
||||||
WritebackCx {
|
WritebackCx { fcx, tables: ty::TypeckTables::new(owner), body, rustc_dump_user_substs }
|
||||||
fcx,
|
|
||||||
tables: ty::TypeckTables::empty(Some(owner)),
|
|
||||||
body,
|
|
||||||
rustc_dump_user_substs,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
@ -342,7 +337,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
fn visit_closures(&mut self) {
|
fn visit_closures(&mut self) {
|
||||||
let fcx_tables = self.fcx.tables.borrow();
|
let fcx_tables = self.fcx.tables.borrow();
|
||||||
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
||||||
let common_hir_owner = fcx_tables.hir_owner.unwrap();
|
let common_hir_owner = fcx_tables.hir_owner;
|
||||||
|
|
||||||
for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
|
for (&id, &origin) in fcx_tables.closure_kind_origins().iter() {
|
||||||
let hir_id = hir::HirId { owner: common_hir_owner, local_id: id };
|
let hir_id = hir::HirId { owner: common_hir_owner, local_id: id };
|
||||||
@ -363,7 +358,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
fn visit_user_provided_tys(&mut self) {
|
fn visit_user_provided_tys(&mut self) {
|
||||||
let fcx_tables = self.fcx.tables.borrow();
|
let fcx_tables = self.fcx.tables.borrow();
|
||||||
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
||||||
let common_hir_owner = fcx_tables.hir_owner.unwrap();
|
let common_hir_owner = fcx_tables.hir_owner;
|
||||||
|
|
||||||
let mut errors_buffer = Vec::new();
|
let mut errors_buffer = Vec::new();
|
||||||
for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
|
for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() {
|
||||||
@ -561,7 +556,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
fn visit_liberated_fn_sigs(&mut self) {
|
fn visit_liberated_fn_sigs(&mut self) {
|
||||||
let fcx_tables = self.fcx.tables.borrow();
|
let fcx_tables = self.fcx.tables.borrow();
|
||||||
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
||||||
let common_hir_owner = fcx_tables.hir_owner.unwrap();
|
let common_hir_owner = fcx_tables.hir_owner;
|
||||||
|
|
||||||
for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
|
for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() {
|
||||||
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
|
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
|
||||||
@ -573,7 +568,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
fn visit_fru_field_types(&mut self) {
|
fn visit_fru_field_types(&mut self) {
|
||||||
let fcx_tables = self.fcx.tables.borrow();
|
let fcx_tables = self.fcx.tables.borrow();
|
||||||
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
assert_eq!(fcx_tables.hir_owner, self.tables.hir_owner);
|
||||||
let common_hir_owner = fcx_tables.hir_owner.unwrap();
|
let common_hir_owner = fcx_tables.hir_owner;
|
||||||
|
|
||||||
for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
|
for (&local_id, ftys) in fcx_tables.fru_field_types().iter() {
|
||||||
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
|
let hir_id = hir::HirId { owner: common_hir_owner, local_id };
|
||||||
|
@ -76,7 +76,7 @@ fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||||||
if method == "load" || method == "store";
|
if method == "load" || method == "store";
|
||||||
let ordering_arg = if method == "load" { &args[1] } else { &args[2] };
|
let ordering_arg = if method == "load" { &args[1] } else { &args[2] };
|
||||||
if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind;
|
if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind;
|
||||||
if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
|
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
|
||||||
then {
|
then {
|
||||||
if method == "load" &&
|
if method == "load" &&
|
||||||
match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) {
|
match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) {
|
||||||
@ -107,12 +107,12 @@ fn check_memory_fence(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(ref func, ref args) = expr.kind;
|
if let ExprKind::Call(ref func, ref args) = expr.kind;
|
||||||
if let ExprKind::Path(ref func_qpath) = func.kind;
|
if let ExprKind::Path(ref func_qpath) = func.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
|
||||||
if ["fence", "compiler_fence"]
|
if ["fence", "compiler_fence"]
|
||||||
.iter()
|
.iter()
|
||||||
.any(|func| match_def_path(cx, def_id, &["core", "sync", "atomic", func]));
|
.any(|func| match_def_path(cx, def_id, &["core", "sync", "atomic", func]));
|
||||||
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind;
|
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind;
|
||||||
if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
|
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
|
||||||
if match_ordering_def_path(cx, ordering_def_id, &["Relaxed"]);
|
if match_ordering_def_path(cx, ordering_def_id, &["Relaxed"]);
|
||||||
then {
|
then {
|
||||||
span_lint_and_help(
|
span_lint_and_help(
|
||||||
|
@ -192,7 +192,7 @@ fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block<'_>]) {
|
|||||||
/// Implementation of `IFS_SAME_COND`.
|
/// Implementation of `IFS_SAME_COND`.
|
||||||
fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
|
fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
|
||||||
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
|
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
|
||||||
let mut h = SpanlessHash::new(cx, cx.tables());
|
let mut h = SpanlessHash::new(cx);
|
||||||
h.hash_expr(expr);
|
h.hash_expr(expr);
|
||||||
h.finish()
|
h.finish()
|
||||||
};
|
};
|
||||||
@ -215,7 +215,7 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
|
|||||||
/// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`.
|
/// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`.
|
||||||
fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
|
fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
|
||||||
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
|
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
|
||||||
let mut h = SpanlessHash::new(cx, cx.tables());
|
let mut h = SpanlessHash::new(cx);
|
||||||
h.hash_expr(expr);
|
h.hash_expr(expr);
|
||||||
h.finish()
|
h.finish()
|
||||||
};
|
};
|
||||||
@ -251,7 +251,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) {
|
|||||||
|
|
||||||
if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind {
|
if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind {
|
||||||
let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 {
|
let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 {
|
||||||
let mut h = SpanlessHash::new(cx, cx.tables());
|
let mut h = SpanlessHash::new(cx);
|
||||||
h.hash_expr(&arm.body);
|
h.hash_expr(&arm.body);
|
||||||
h.finish()
|
h.finish()
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
|
|||||||
if let ExprKind::Call(ref path, ..) = expr.kind;
|
if let ExprKind::Call(ref path, ..) = expr.kind;
|
||||||
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
|
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
|
||||||
if let ExprKind::Path(ref qpath) = path.kind;
|
if let ExprKind::Path(ref qpath) = path.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(qpath, path.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
|
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
|
||||||
then {
|
then {
|
||||||
match qpath {
|
match qpath {
|
||||||
|
@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
|
|||||||
if let ExprKind::Path(ref qpath) = lhs.kind {
|
if let ExprKind::Path(ref qpath) = lhs.kind {
|
||||||
if let QPath::Resolved(_, ref path) = *qpath {
|
if let QPath::Resolved(_, ref path) = *qpath {
|
||||||
if path.segments.len() == 1 {
|
if path.segments.len() == 1 {
|
||||||
if let def::Res::Local(var) = cx.tables().qpath_res(qpath, lhs.hir_id) {
|
if let def::Res::Local(var) = cx.qpath_res(qpath, lhs.hir_id) {
|
||||||
let mut visitor = ReadVisitor {
|
let mut visitor = ReadVisitor {
|
||||||
cx,
|
cx,
|
||||||
var,
|
var,
|
||||||
@ -309,7 +309,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let QPath::Resolved(None, ref path) = *qpath;
|
if let QPath::Resolved(None, ref path) = *qpath;
|
||||||
if path.segments.len() == 1;
|
if path.segments.len() == 1;
|
||||||
if let def::Res::Local(local_id) = self.cx.tables().qpath_res(qpath, expr.hir_id);
|
if let def::Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id);
|
||||||
if local_id == self.var;
|
if local_id == self.var;
|
||||||
// Check that this is a read, not a write.
|
// Check that this is a read, not a write.
|
||||||
if !is_in_assignment_position(self.cx, expr);
|
if !is_in_assignment_position(self.cx, expr);
|
||||||
|
@ -88,7 +88,7 @@ fn on_argumentv1_new<'a, 'tcx>(
|
|||||||
// matches `core::fmt::Display::fmt`
|
// matches `core::fmt::Display::fmt`
|
||||||
if args.len() == 2;
|
if args.len() == 2;
|
||||||
if let ExprKind::Path(ref qpath) = args[1].kind;
|
if let ExprKind::Path(ref qpath) = args[1].kind;
|
||||||
if let Some(did) = cx.tables().qpath_res(qpath, args[1].hir_id).opt_def_id();
|
if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
|
||||||
if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
|
if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
|
||||||
// check `(arg0,)` in match block
|
// check `(arg0,)` in match block
|
||||||
if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
|
if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
|
||||||
|
@ -108,7 +108,7 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||||||
ExprKind::Call(expr, ..) => {
|
ExprKind::Call(expr, ..) => {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Path(qpath) = &expr.kind;
|
if let ExprKind::Path(qpath) = &expr.kind;
|
||||||
if let Some(path_def_id) = cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id();
|
if let Some(path_def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, path_def_id, &BEGIN_PANIC) ||
|
if match_def_path(cx, path_def_id, &BEGIN_PANIC) ||
|
||||||
match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT);
|
match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT);
|
||||||
then { }
|
then { }
|
||||||
|
@ -107,7 +107,7 @@ impl BorrowVisitor<'_, '_> {
|
|||||||
..
|
..
|
||||||
},
|
},
|
||||||
..,
|
..,
|
||||||
) => self.cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id(),
|
) => self.cx.qpath_res(qpath, expr.hir_id).opt_def_id(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,7 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
|||||||
})
|
})
|
||||||
{
|
{
|
||||||
let hir_id = ty.hir_id;
|
let hir_id = ty.hir_id;
|
||||||
match self.cx.tables().qpath_res(qpath, hir_id) {
|
match self.cx.qpath_res(qpath, hir_id) {
|
||||||
Res::Def(DefKind::TyAlias | DefKind::Struct, def_id) => {
|
Res::Def(DefKind::TyAlias | DefKind::Struct, def_id) => {
|
||||||
let generics = self.cx.tcx.generics_of(def_id);
|
let generics = self.cx.tcx.generics_of(def_id);
|
||||||
for _ in generics.params.as_slice() {
|
for _ in generics.params.as_slice() {
|
||||||
|
@ -160,10 +160,10 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_closure<'a, 'tcx>(
|
fn unit_closure<'tcx>(
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx: &LateContext<'_, 'tcx>,
|
||||||
expr: &'a hir::Expr<'a>,
|
expr: &hir::Expr<'_>,
|
||||||
) -> Option<(&'tcx hir::Param<'tcx>, &'a hir::Expr<'a>)> {
|
) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
|
||||||
if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.kind {
|
if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.kind {
|
||||||
let body = cx.tcx.hir().body(inner_expr_id);
|
let body = cx.tcx.hir().body(inner_expr_id);
|
||||||
let body_expr = &body.value;
|
let body_expr = &body.value;
|
||||||
|
@ -35,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemDiscriminant {
|
|||||||
if let ExprKind::Call(ref func, ref func_args) = expr.kind;
|
if let ExprKind::Call(ref func, ref func_args) = expr.kind;
|
||||||
// is `mem::discriminant`
|
// is `mem::discriminant`
|
||||||
if let ExprKind::Path(ref func_qpath) = func.kind;
|
if let ExprKind::Path(ref func_qpath) = func.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, def_id, &paths::MEM_DISCRIMINANT);
|
if match_def_path(cx, def_id, &paths::MEM_DISCRIMINANT);
|
||||||
// type is non-enum
|
// type is non-enum
|
||||||
let ty_param = cx.tables().node_substs(func.hir_id).type_at(0);
|
let ty_param = cx.tables().node_substs(func.hir_id).type_at(0);
|
||||||
|
@ -162,7 +162,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &Ex
|
|||||||
if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind;
|
if let ExprKind::Call(ref repl_func, ref repl_args) = src.kind;
|
||||||
if repl_args.is_empty();
|
if repl_args.is_empty();
|
||||||
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
||||||
if let Some(repl_def_id) = cx.tables().qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
||||||
then {
|
then {
|
||||||
if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
|
if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
@ -198,7 +198,7 @@ fn check_replace_with_default(cx: &LateContext<'_, '_>, src: &Expr<'_>, dest: &E
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if !in_external_macro(cx.tcx.sess, expr_span);
|
if !in_external_macro(cx.tcx.sess, expr_span);
|
||||||
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
||||||
if let Some(repl_def_id) = cx.tables().qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD);
|
if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD);
|
||||||
then {
|
then {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
@ -230,7 +230,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
|
|||||||
// Check that `expr` is a call to `mem::replace()`
|
// Check that `expr` is a call to `mem::replace()`
|
||||||
if let ExprKind::Call(ref func, ref func_args) = expr.kind;
|
if let ExprKind::Call(ref func, ref func_args) = expr.kind;
|
||||||
if let ExprKind::Path(ref func_qpath) = func.kind;
|
if let ExprKind::Path(ref func_qpath) = func.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, def_id, &paths::MEM_REPLACE);
|
if match_def_path(cx, def_id, &paths::MEM_REPLACE);
|
||||||
if let [dest, src] = &**func_args;
|
if let [dest, src] = &**func_args;
|
||||||
then {
|
then {
|
||||||
|
@ -1824,7 +1824,7 @@ fn lint_expect_fun_call(
|
|||||||
hir::ExprKind::Lit(_) => true,
|
hir::ExprKind::Lit(_) => true,
|
||||||
hir::ExprKind::Call(fun, _) => {
|
hir::ExprKind::Call(fun, _) => {
|
||||||
if let hir::ExprKind::Path(ref p) = fun.kind {
|
if let hir::ExprKind::Path(ref p) = fun.kind {
|
||||||
match cx.tables().qpath_res(p, fun.hir_id) {
|
match cx.qpath_res(p, fun.hir_id) {
|
||||||
hir::def::Res::Def(hir::def::DefKind::Fn | hir::def::DefKind::AssocFn, def_id) => matches!(
|
hir::def::Res::Def(hir::def::DefKind::Fn | hir::def::DefKind::AssocFn, def_id) => matches!(
|
||||||
cx.tcx.fn_sig(def_id).output().skip_binder().kind,
|
cx.tcx.fn_sig(def_id).output().skip_binder().kind,
|
||||||
ty::Ref(ty::ReStatic, ..)
|
ty::Ref(ty::ReStatic, ..)
|
||||||
@ -1844,7 +1844,7 @@ fn lint_expect_fun_call(
|
|||||||
ty::Ref(ty::ReStatic, ..)
|
ty::Ref(ty::ReStatic, ..)
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
hir::ExprKind::Path(ref p) => match cx.tables().qpath_res(p, arg.hir_id) {
|
hir::ExprKind::Path(ref p) => match cx.qpath_res(p, arg.hir_id) {
|
||||||
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) => true,
|
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
@ -3317,7 +3317,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let hir::ExprKind::Path(qpath) = &args[0].kind;
|
if let hir::ExprKind::Path(qpath) = &args[0].kind;
|
||||||
if let hir::def::Res::Local(local_id) = cx.tables().qpath_res(qpath, args[0].hir_id);
|
if let hir::def::Res::Local(local_id) = cx.qpath_res(qpath, args[0].hir_id);
|
||||||
if closure_body.params[0].pat.hir_id == local_id;
|
if closure_body.params[0].pat.hir_id == local_id;
|
||||||
let adj = cx.tables().expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>();
|
let adj = cx.tables().expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>();
|
||||||
if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
|
if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
|
||||||
@ -3334,7 +3334,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
|
|||||||
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner1) = inner.kind;
|
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner1) = inner.kind;
|
||||||
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner2) = inner1.kind;
|
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner2) = inner1.kind;
|
||||||
if let hir::ExprKind::Path(ref qpath) = inner2.kind;
|
if let hir::ExprKind::Path(ref qpath) = inner2.kind;
|
||||||
if let hir::def::Res::Local(local_id) = cx.tables().qpath_res(qpath, inner2.hir_id);
|
if let hir::def::Res::Local(local_id) = cx.qpath_res(qpath, inner2.hir_id);
|
||||||
then {
|
then {
|
||||||
closure_body.params[0].pat.hir_id == local_id
|
closure_body.params[0].pat.hir_id == local_id
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +65,7 @@ fn check_expression<'a, 'tcx>(
|
|||||||
if match_qpath(path, &paths::OPTION_SOME) {
|
if match_qpath(path, &paths::OPTION_SOME) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let hir::ExprKind::Path(path) = &args[0].kind;
|
if let hir::ExprKind::Path(path) = &args[0].kind;
|
||||||
if let Res::Local(ref local) = cx.tables().qpath_res(path, args[0].hir_id);
|
if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id);
|
||||||
then {
|
then {
|
||||||
if arg_id == *local {
|
if arg_id == *local {
|
||||||
return (false, false)
|
return (false, false)
|
||||||
|
@ -436,7 +436,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
|
|||||||
binding != "_result" && // FIXME: #944
|
binding != "_result" && // FIXME: #944
|
||||||
is_used(cx, expr) &&
|
is_used(cx, expr) &&
|
||||||
// don't lint if the declaration is in a macro
|
// don't lint if the declaration is in a macro
|
||||||
non_macro_local(cx, cx.tables().qpath_res(qpath, expr.hir_id))
|
non_macro_local(cx, cx.qpath_res(qpath, expr.hir_id))
|
||||||
{
|
{
|
||||||
Some(binding)
|
Some(binding)
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,7 +158,7 @@ impl QuestionMark {
|
|||||||
ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
|
ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
|
||||||
ExprKind::Path(ref qp) => {
|
ExprKind::Path(ref qp) => {
|
||||||
if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
|
if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
|
||||||
cx.tables().qpath_res(qp, expression.hir_id)
|
cx.qpath_res(qp, expression.hir_id)
|
||||||
{
|
{
|
||||||
return match_def_path(cx, def_id, &paths::OPTION_NONE);
|
return match_def_path(cx, def_id, &paths::OPTION_NONE);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Regex {
|
|||||||
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
||||||
if let ExprKind::Path(ref qpath) = fun.kind;
|
if let ExprKind::Path(ref qpath) = fun.kind;
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||||
then {
|
then {
|
||||||
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
|
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
|
||||||
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
|
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
|
||||||
|
@ -26,7 +26,7 @@ fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
|
|||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ExprKind::Struct(..) | ExprKind::Tup(..) => true,
|
ExprKind::Struct(..) | ExprKind::Tup(..) => true,
|
||||||
ExprKind::Path(qpath) => {
|
ExprKind::Path(qpath) => {
|
||||||
if let Res::Def(DefKind::Const, ..) = cx.tables().qpath_res(qpath, expr.hir_id) {
|
if let Res::Def(DefKind::Const, ..) = cx.qpath_res(qpath, expr.hir_id) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -56,7 +56,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ToDigitIsSome {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let [char_arg, radix_arg] = &**to_digit_args;
|
if let [char_arg, radix_arg] = &**to_digit_args;
|
||||||
if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind;
|
if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind;
|
||||||
if let to_digits_call_res = cx.tables().qpath_res(to_digits_path, to_digits_call.hir_id);
|
if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id);
|
||||||
if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id();
|
if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id();
|
||||||
if match_def_path(cx, to_digits_def_id, &["core", "char", "methods", "<impl char>", "to_digit"]);
|
if match_def_path(cx, to_digits_def_id, &["core", "char", "methods", "<impl char>", "to_digit"]);
|
||||||
then {
|
then {
|
||||||
|
@ -37,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let hash = |ty| -> u64 {
|
let hash = |ty| -> u64 {
|
||||||
let mut hasher = SpanlessHash::new(cx, cx.tables());
|
let mut hasher = SpanlessHash::new(cx);
|
||||||
hasher.hash_ty(ty);
|
hasher.hash_ty(ty);
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
};
|
};
|
||||||
|
@ -299,7 +299,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(ref path_expr, ref args) = e.kind;
|
if let ExprKind::Call(ref path_expr, ref args) = e.kind;
|
||||||
if let ExprKind::Path(ref qpath) = path_expr.kind;
|
if let ExprKind::Path(ref qpath) = path_expr.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, def_id, &paths::TRANSMUTE);
|
if match_def_path(cx, def_id, &paths::TRANSMUTE);
|
||||||
then {
|
then {
|
||||||
let from_ty = cx.tables().expr_ty(&args[0]);
|
let from_ty = cx.tables().expr_ty(&args[0]);
|
||||||
|
@ -2490,7 +2490,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> {
|
|||||||
/// Looks for default-hasher-dependent constructors like `HashMap::new`.
|
/// Looks for default-hasher-dependent constructors like `HashMap::new`.
|
||||||
struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
|
struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
|
||||||
cx: &'a LateContext<'a, 'tcx>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
body: &'a TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>,
|
||||||
target: &'b ImplicitHasherType<'tcx>,
|
target: &'b ImplicitHasherType<'tcx>,
|
||||||
suggestions: BTreeMap<Span, String>,
|
suggestions: BTreeMap<Span, String>,
|
||||||
}
|
}
|
||||||
@ -2499,7 +2499,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> {
|
|||||||
fn new(cx: &'a LateContext<'a, 'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
|
fn new(cx: &'a LateContext<'a, 'tcx>, target: &'b ImplicitHasherType<'tcx>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
cx,
|
||||||
body: cx.tables(),
|
maybe_typeck_tables: cx.maybe_typeck_tables(),
|
||||||
target,
|
target,
|
||||||
suggestions: BTreeMap::new(),
|
suggestions: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
@ -2510,10 +2510,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
|
|||||||
type Map = Map<'tcx>;
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
fn visit_body(&mut self, body: &'tcx Body<'_>) {
|
fn visit_body(&mut self, body: &'tcx Body<'_>) {
|
||||||
let prev_body = self.body;
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.cx.tcx.body_tables(body.id()));
|
||||||
self.body = self.cx.tcx.body_tables(body.id());
|
|
||||||
walk_body(self, body);
|
walk_body(self, body);
|
||||||
self.body = prev_body;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||||
@ -2522,7 +2521,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
|
|||||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind;
|
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref method)) = fun.kind;
|
||||||
if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
|
if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
|
||||||
then {
|
then {
|
||||||
if !TyS::same_type(self.target.ty(), self.body.expr_ty(e)) {
|
if !TyS::same_type(self.target.ty(), self.maybe_typeck_tables.unwrap().expr_ty(e)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl LateLintPass<'_, '_> for UnnamedAddress {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind;
|
if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind;
|
||||||
if let ExprKind::Path(ref func_qpath) = func.kind;
|
if let ExprKind::Path(ref func_qpath) = func.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, def_id, &paths::PTR_EQ) ||
|
if match_def_path(cx, def_id, &paths::PTR_EQ) ||
|
||||||
match_def_path(cx, def_id, &paths::RC_PTR_EQ) ||
|
match_def_path(cx, def_id, &paths::RC_PTR_EQ) ||
|
||||||
match_def_path(cx, def_id, &paths::ARC_PTR_EQ);
|
match_def_path(cx, def_id, &paths::ARC_PTR_EQ);
|
||||||
|
@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let ExprKind::Path(ref qpath) = path.kind;
|
if let ExprKind::Path(ref qpath) = path.kind;
|
||||||
if let Some(def_id) = cx.tables().qpath_res(qpath, path.hir_id).opt_def_id();
|
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
|
||||||
let a = cx.tables().expr_ty(e);
|
let a = cx.tables().expr_ty(e);
|
||||||
let b = cx.tables().expr_ty(&args[0]);
|
let b = cx.tables().expr_ty(&args[0]);
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr<'_>) -> Optio
|
|||||||
if let hir::ExprKind::Call(ref fun, ref args) = expr.kind;
|
if let hir::ExprKind::Call(ref fun, ref args) = expr.kind;
|
||||||
if let hir::ExprKind::Path(ref qpath) = fun.kind;
|
if let hir::ExprKind::Path(ref qpath) = fun.kind;
|
||||||
if is_expn_of(fun.span, "vec").is_some();
|
if is_expn_of(fun.span, "vec").is_some();
|
||||||
if let Some(fun_def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id();
|
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||||
then {
|
then {
|
||||||
return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
|
return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
|
||||||
// `vec![elem; size]` case
|
// `vec![elem; size]` case
|
||||||
|
@ -22,7 +22,7 @@ use std::hash::Hash;
|
|||||||
pub struct SpanlessEq<'a, 'tcx> {
|
pub struct SpanlessEq<'a, 'tcx> {
|
||||||
/// Context used to evaluate constant expressions.
|
/// Context used to evaluate constant expressions.
|
||||||
cx: &'a LateContext<'a, 'tcx>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
tables: &'a TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>,
|
||||||
/// If is true, never consider as equal expressions containing function
|
/// If is true, never consider as equal expressions containing function
|
||||||
/// calls.
|
/// calls.
|
||||||
ignore_fn: bool,
|
ignore_fn: bool,
|
||||||
@ -32,16 +32,15 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
|||||||
pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
cx,
|
||||||
tables: cx.tables(),
|
maybe_typeck_tables: cx.maybe_typeck_tables(),
|
||||||
ignore_fn: false,
|
ignore_fn: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ignore_fn(self) -> Self {
|
pub fn ignore_fn(self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx: self.cx,
|
|
||||||
tables: self.cx.tables(),
|
|
||||||
ignore_fn: true,
|
ignore_fn: true,
|
||||||
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,14 +71,16 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(tables) = self.maybe_typeck_tables {
|
||||||
if let (Some(l), Some(r)) = (
|
if let (Some(l), Some(r)) = (
|
||||||
constant_simple(self.cx, self.tables, left),
|
constant_simple(self.cx, tables, left),
|
||||||
constant_simple(self.cx, self.tables, right),
|
constant_simple(self.cx, tables, right),
|
||||||
) {
|
) {
|
||||||
if l == r {
|
if l == r {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match (&left.kind, &right.kind) {
|
match (&left.kind, &right.kind) {
|
||||||
(&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => {
|
(&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => {
|
||||||
@ -271,18 +272,18 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
|||||||
match (left, right) {
|
match (left, right) {
|
||||||
(&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
|
(&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
|
||||||
(&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => {
|
(&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => {
|
||||||
let full_table = self.tables;
|
let old_maybe_typeck_tables = self.maybe_typeck_tables;
|
||||||
|
|
||||||
let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body));
|
let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(ll_id.body));
|
||||||
self.tables = self.cx.tcx.body_tables(ll_id.body);
|
self.maybe_typeck_tables = Some(self.cx.tcx.body_tables(ll_id.body));
|
||||||
let ll = celcx.expr(&self.cx.tcx.hir().body(ll_id.body).value);
|
let ll = celcx.expr(&self.cx.tcx.hir().body(ll_id.body).value);
|
||||||
|
|
||||||
let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body));
|
let mut celcx = constant_context(self.cx, self.cx.tcx.body_tables(rl_id.body));
|
||||||
self.tables = self.cx.tcx.body_tables(rl_id.body);
|
self.maybe_typeck_tables = Some(self.cx.tcx.body_tables(rl_id.body));
|
||||||
let rl = celcx.expr(&self.cx.tcx.hir().body(rl_id.body).value);
|
let rl = celcx.expr(&self.cx.tcx.hir().body(rl_id.body).value);
|
||||||
|
|
||||||
let eq_ty = self.eq_ty(lt, rt);
|
let eq_ty = self.eq_ty(lt, rt);
|
||||||
self.tables = full_table;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
eq_ty && ll == rl
|
eq_ty && ll == rl
|
||||||
},
|
},
|
||||||
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
|
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
|
||||||
@ -347,15 +348,15 @@ pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -
|
|||||||
pub struct SpanlessHash<'a, 'tcx> {
|
pub struct SpanlessHash<'a, 'tcx> {
|
||||||
/// Context used to evaluate constant expressions.
|
/// Context used to evaluate constant expressions.
|
||||||
cx: &'a LateContext<'a, 'tcx>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
tables: &'a TypeckTables<'tcx>,
|
maybe_typeck_tables: Option<&'tcx TypeckTables<'tcx>>,
|
||||||
s: StableHasher,
|
s: StableHasher,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
pub fn new(cx: &'a LateContext<'a, 'tcx>, tables: &'a TypeckTables<'tcx>) -> Self {
|
pub fn new(cx: &'a LateContext<'a, 'tcx>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
cx,
|
||||||
tables,
|
maybe_typeck_tables: cx.maybe_typeck_tables(),
|
||||||
s: StableHasher::new(),
|
s: StableHasher::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,7 +385,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
|
|
||||||
#[allow(clippy::many_single_char_names, clippy::too_many_lines)]
|
#[allow(clippy::many_single_char_names, clippy::too_many_lines)]
|
||||||
pub fn hash_expr(&mut self, e: &Expr<'_>) {
|
pub fn hash_expr(&mut self, e: &Expr<'_>) {
|
||||||
let simple_const = constant_simple(self.cx, self.tables, e);
|
let simple_const = self
|
||||||
|
.maybe_typeck_tables
|
||||||
|
.and_then(|tables| constant_simple(self.cx, tables, e));
|
||||||
|
|
||||||
// const hashing may result in the same hash as some unrelated node, so add a sort of
|
// const hashing may result in the same hash as some unrelated node, so add a sort of
|
||||||
// discriminant depending on which path we're choosing next
|
// discriminant depending on which path we're choosing next
|
||||||
@ -599,7 +602,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
self.hash_name(path.ident.name);
|
self.hash_name(path.ident.name);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// self.cx.tables.qpath_res(p, id).hash(&mut self.s);
|
// self.maybe_typeck_tables.unwrap().qpath_res(p, id).hash(&mut self.s);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_path(&mut self, p: &Path<'_>) {
|
pub fn hash_path(&mut self, p: &Path<'_>) {
|
||||||
@ -728,9 +731,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
|
|
||||||
pub fn hash_body(&mut self, body_id: BodyId) {
|
pub fn hash_body(&mut self, body_id: BodyId) {
|
||||||
// swap out TypeckTables when hashing a body
|
// swap out TypeckTables when hashing a body
|
||||||
let old_tables = self.tables;
|
let old_maybe_typeck_tables = self.maybe_typeck_tables.replace(self.cx.tcx.body_tables(body_id));
|
||||||
self.tables = self.cx.tcx.body_tables(body_id);
|
|
||||||
self.hash_expr(&self.cx.tcx.hir().body(body_id).value);
|
self.hash_expr(&self.cx.tcx.hir().body(body_id).value);
|
||||||
self.tables = old_tables;
|
self.maybe_typeck_tables = old_maybe_typeck_tables;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty<'_>) -> bool {
|
|||||||
) = ty.kind
|
) = ty.kind
|
||||||
{
|
{
|
||||||
if let TyKind::Path(ref path) = inner.kind {
|
if let TyKind::Path(ref path) = inner.kind {
|
||||||
if let Res::Def(DefKind::Struct, def_id) = cx.tables().qpath_res(path, inner.hir_id) {
|
if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) {
|
||||||
return match_def_path(cx, def_id, &paths::LINT);
|
return match_def_path(cx, def_id, &paths::LINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,7 +898,7 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
|||||||
pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
|
pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
|
||||||
if let ExprKind::Call(ref fun, _) = expr.kind {
|
if let ExprKind::Call(ref fun, _) = expr.kind {
|
||||||
if let ExprKind::Path(ref qp) = fun.kind {
|
if let ExprKind::Path(ref qp) = fun.kind {
|
||||||
let res = cx.tables().qpath_res(qp, fun.hir_id);
|
let res = cx.qpath_res(qp, fun.hir_id);
|
||||||
return match res {
|
return match res {
|
||||||
def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
|
def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
|
||||||
def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
|
def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
|
||||||
@ -914,7 +914,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp
|
|||||||
pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool {
|
pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool {
|
||||||
fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool {
|
fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
cx.tables().qpath_res(qpath, id),
|
cx.qpath_res(qpath, id),
|
||||||
def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
|
def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1190,7 +1190,7 @@ pub fn match_function_call<'a, 'tcx>(
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
||||||
if let ExprKind::Path(ref qpath) = fun.kind;
|
if let ExprKind::Path(ref qpath) = fun.kind;
|
||||||
if let Some(fun_def_id) = cx.tables().qpath_res(qpath, fun.hir_id).opt_def_id();
|
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
|
||||||
if match_def_path(cx, fun_def_id, path);
|
if match_def_path(cx, fun_def_id, path);
|
||||||
then {
|
then {
|
||||||
return Some(&args)
|
return Some(&args)
|
||||||
@ -1317,7 +1317,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool
|
|||||||
let did = match expr.kind {
|
let did = match expr.kind {
|
||||||
ExprKind::Call(ref path, _) => if_chain! {
|
ExprKind::Call(ref path, _) => if_chain! {
|
||||||
if let ExprKind::Path(ref qpath) = path.kind;
|
if let ExprKind::Path(ref qpath) = path.kind;
|
||||||
if let def::Res::Def(_, did) = cx.tables().qpath_res(qpath, path.hir_id);
|
if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
|
||||||
then {
|
then {
|
||||||
Some(did)
|
Some(did)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user