add lint levels to VisibilityScope
This commit is contained in:
parent
acb73dbe8b
commit
8c7500f9b6
@ -28,6 +28,7 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
|
||||
name,
|
||||
source_info,
|
||||
internal,
|
||||
lexical_scope,
|
||||
is_user_variable
|
||||
});
|
||||
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
|
||||
@ -75,6 +76,22 @@ for mir::Terminator<'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearOnDecode<T>
|
||||
where T: HashStable<StableHashingContext<'gcx>>
|
||||
{
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'gcx>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
match *self {
|
||||
mir::ClearOnDecode::Clear => {}
|
||||
mir::ClearOnDecode::Set(ref value) => {
|
||||
value.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local {
|
||||
#[inline]
|
||||
@ -347,6 +364,7 @@ for mir::ProjectionElem<'gcx, V, T>
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
|
||||
impl_stable_hash_for!(struct mir::VisibilityScopeInfo { lint_root });
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
|
@ -384,6 +384,11 @@ impl LintLevelMap {
|
||||
self.sets.get_lint_level(lint, *idx, None)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns if this `id` has lint level information.
|
||||
pub fn lint_level_set(&self, id: HirId) -> Option<u32> {
|
||||
self.id_to_set.get(&id).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for LintLevelMap {
|
||||
|
@ -18,6 +18,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
|
||||
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
|
||||
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
|
||||
use rustc_serialize as serialize;
|
||||
use hir::def::CtorKind;
|
||||
use hir::def_id::DefId;
|
||||
use ty::subst::{Subst, Substs};
|
||||
@ -33,7 +34,7 @@ use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::{iter, u32};
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::vec::IntoIter;
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax_pos::Span;
|
||||
|
||||
mod cache;
|
||||
@ -96,6 +97,10 @@ pub struct Mir<'tcx> {
|
||||
/// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
|
||||
pub visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
||||
|
||||
/// Crate-local information for each visibility scope, that can't (and
|
||||
/// needn't) be tracked across crates.
|
||||
pub visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope, VisibilityScopeInfo>>,
|
||||
|
||||
/// Rvalues promoted from this function, such as borrows of constants.
|
||||
/// Each of them is the Mir of a constant with the fn's type parameters
|
||||
/// in scope, but a separate set of locals.
|
||||
@ -151,6 +156,8 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0);
|
||||
impl<'tcx> Mir<'tcx> {
|
||||
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
||||
visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope,
|
||||
VisibilityScopeInfo>>,
|
||||
promoted: IndexVec<Promoted, Mir<'tcx>>,
|
||||
return_ty: Ty<'tcx>,
|
||||
yield_ty: Option<Ty<'tcx>>,
|
||||
@ -167,6 +174,7 @@ impl<'tcx> Mir<'tcx> {
|
||||
Mir {
|
||||
basic_blocks,
|
||||
visibility_scopes,
|
||||
visibility_scope_info,
|
||||
promoted,
|
||||
return_ty,
|
||||
yield_ty,
|
||||
@ -278,9 +286,16 @@ impl<'tcx> Mir<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VisibilityScopeInfo {
|
||||
/// A NodeId with lint levels equivalent to this scope's lint levels.
|
||||
pub lint_root: ast::NodeId,
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct Mir<'tcx> {
|
||||
basic_blocks,
|
||||
visibility_scopes,
|
||||
visibility_scope_info,
|
||||
promoted,
|
||||
return_ty,
|
||||
yield_ty,
|
||||
@ -310,6 +325,24 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ClearOnDecode<T> {
|
||||
Clear,
|
||||
Set(T)
|
||||
}
|
||||
|
||||
impl<T> serialize::Encodable for ClearOnDecode<T> {
|
||||
fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
serialize::Encodable::encode(&(), s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> serialize::Decodable for ClearOnDecode<T> {
|
||||
fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||
serialize::Decodable::decode(d).map(|()| ClearOnDecode::Clear)
|
||||
}
|
||||
}
|
||||
|
||||
/// Grouped information about the source code origin of a MIR entity.
|
||||
/// Intended to be inspected by diagnostics and debuginfo.
|
||||
/// Most passes can work with it as a whole, within a single function.
|
||||
@ -438,6 +471,12 @@ pub struct LocalDecl<'tcx> {
|
||||
|
||||
/// Source info of the local.
|
||||
pub source_info: SourceInfo,
|
||||
|
||||
/// The *lexical* visibility scope the local is defined
|
||||
/// in. If the local was defined in a let-statement, this
|
||||
/// is *within* the let-statement, rather than outside
|
||||
/// of iit.
|
||||
pub lexical_scope: VisibilityScope,
|
||||
}
|
||||
|
||||
impl<'tcx> LocalDecl<'tcx> {
|
||||
@ -452,6 +491,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
span,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||
},
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
is_user_variable: false
|
||||
}
|
||||
@ -468,6 +508,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
span,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||
},
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: true,
|
||||
is_user_variable: false
|
||||
}
|
||||
@ -485,6 +526,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
span,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||
},
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
name: None, // FIXME maybe we do want some name here?
|
||||
is_user_variable: false
|
||||
@ -1607,6 +1649,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
|
||||
Mir {
|
||||
basic_blocks: self.basic_blocks.fold_with(folder),
|
||||
visibility_scopes: self.visibility_scopes.clone(),
|
||||
visibility_scope_info: self.visibility_scope_info.clone(),
|
||||
promoted: self.promoted.fold_with(folder),
|
||||
return_ty: self.return_ty.fold_with(folder),
|
||||
yield_ty: self.yield_ty.fold_with(folder),
|
||||
|
@ -690,11 +690,13 @@ macro_rules! make_mir_visitor {
|
||||
name: _,
|
||||
ref $($mutability)* source_info,
|
||||
internal: _,
|
||||
ref $($mutability)* lexical_scope,
|
||||
is_user_variable: _,
|
||||
} = *local_decl;
|
||||
|
||||
self.visit_ty(ty, Lookup::Src(*source_info));
|
||||
self.visit_source_info(source_info);
|
||||
self.visit_visibility_scope(lexical_scope);
|
||||
}
|
||||
|
||||
fn super_visibility_scope(&mut self,
|
||||
|
@ -1009,15 +1009,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
// FIXME: ariel points SimplifyBranches should run after
|
||||
// mir-borrowck; otherwise code within `if false { ... }` would
|
||||
// not be checked.
|
||||
passes.push_pass(MIR_VALIDATED,
|
||||
mir::transform::simplify_branches::SimplifyBranches::new("initial"));
|
||||
passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
|
||||
passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL);
|
||||
|
||||
// borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
|
||||
|
||||
// These next passes must be executed together
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
|
||||
passes.push_pass(MIR_OPTIMIZED,
|
||||
mir::transform::simplify_branches::SimplifyBranches::new("initial"));
|
||||
|
||||
// These next passes must be executed together
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
|
||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
|
||||
|
@ -24,7 +24,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let Block { region_scope, opt_destruction_scope, span, stmts, expr, targeted_by_break } =
|
||||
self.hir.mirror(ast_block);
|
||||
self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
|
||||
this.in_scope((region_scope, source_info), block, move |this| {
|
||||
this.in_scope((region_scope, source_info), LintLevel::Inherited, block, move |this| {
|
||||
if targeted_by_break {
|
||||
// This is a `break`-able block (currently only `catch { ... }`)
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
@ -76,13 +76,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
StmtKind::Expr { scope, expr } => {
|
||||
unpack!(block = this.in_opt_scope(
|
||||
opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
|
||||
this.in_scope((scope, source_info), block, |this| {
|
||||
let si = (scope, source_info);
|
||||
this.in_scope(si, LintLevel::Inherited, block, |this| {
|
||||
let expr = this.hir.mirror(expr);
|
||||
this.stmt_expr(block, expr)
|
||||
})
|
||||
}));
|
||||
}
|
||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
|
||||
StmtKind::Let {
|
||||
remainder_scope,
|
||||
init_scope,
|
||||
pattern,
|
||||
initializer,
|
||||
lint_level
|
||||
} => {
|
||||
// Enter the remainder scope, i.e. the bindings' destruction scope.
|
||||
this.push_scope((remainder_scope, source_info));
|
||||
let_scope_stack.push(remainder_scope);
|
||||
@ -90,13 +97,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// Declare the bindings, which may create a visibility scope.
|
||||
let remainder_span = remainder_scope.span(this.hir.tcx(),
|
||||
&this.hir.region_scope_tree);
|
||||
let scope = this.declare_bindings(None, remainder_span, &pattern);
|
||||
let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern);
|
||||
|
||||
// Evaluate the initializer, if present.
|
||||
if let Some(init) = initializer {
|
||||
unpack!(block = this.in_opt_scope(
|
||||
opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
|
||||
this.in_scope((init_scope, source_info), block, move |this| {
|
||||
let scope = (init_scope, source_info);
|
||||
this.in_scope(scope, lint_level, block, move |this| {
|
||||
// FIXME #30046 ^~~~
|
||||
this.expr_into_pattern(block, pattern, init)
|
||||
})
|
||||
|
@ -29,7 +29,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let Expr { ty, temp_lifetime: _, span, kind }
|
||||
= expr;
|
||||
match kind {
|
||||
ExprKind::Scope { region_scope: _, value } =>
|
||||
ExprKind::Scope { region_scope: _, lint_level: _, value } =>
|
||||
this.as_constant(value),
|
||||
ExprKind::Literal { literal } =>
|
||||
Constant { span: span, ty: ty, literal: literal },
|
||||
|
@ -39,8 +39,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr_span);
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, value } => {
|
||||
this.in_scope((region_scope, source_info), block, |this| {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||
this.as_lvalue(block, value)
|
||||
})
|
||||
}
|
||||
|
@ -55,10 +55,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
|
||||
let this = self;
|
||||
|
||||
if let ExprKind::Scope { region_scope, value } = expr.kind {
|
||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||
let source_info = this.source_info(expr.span);
|
||||
let region_scope = (region_scope, source_info);
|
||||
return this.in_scope(region_scope, block, |this| {
|
||||
return this.in_scope(region_scope, lint_level, block, |this| {
|
||||
this.as_operand(block, scope, value)
|
||||
});
|
||||
}
|
||||
|
@ -58,9 +58,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let source_info = this.source_info(expr_span);
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, value } => {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
let region_scope = (region_scope, source_info);
|
||||
this.in_scope(region_scope, block, |this| this.as_rvalue(block, scope, value))
|
||||
this.in_scope(region_scope, lint_level, block,
|
||||
|this| this.as_rvalue(block, scope, value))
|
||||
}
|
||||
ExprKind::Repeat { value, count } => {
|
||||
let value_operand = unpack!(block = this.as_operand(block, scope, value));
|
||||
|
@ -41,8 +41,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr_span);
|
||||
if let ExprKind::Scope { region_scope, value } = expr.kind {
|
||||
return this.in_scope((region_scope, source_info), block, |this| {
|
||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||
return this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||
this.as_temp(block, temp_lifetime, value)
|
||||
});
|
||||
}
|
||||
|
@ -38,9 +38,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let source_info = this.source_info(expr_span);
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, value } => {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
let region_scope = (region_scope, source_info);
|
||||
this.in_scope(region_scope, block, |this| this.into(destination, block, value))
|
||||
this.in_scope(region_scope, lint_level, block,
|
||||
|this| this.into(destination, block, value))
|
||||
}
|
||||
ExprKind::Block { body: ast_block } => {
|
||||
this.ast_block(destination, block, ast_block, source_info)
|
||||
|
@ -22,9 +22,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// Handle a number of expressions that don't need a destination at all. This
|
||||
// avoids needing a mountain of temporary `()` variables.
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, value } => {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
let value = this.hir.mirror(value);
|
||||
this.in_scope((region_scope, source_info), block, |this| {
|
||||
this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||
this.stmt_expr(block, value)
|
||||
})
|
||||
}
|
||||
|
@ -46,8 +46,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Get the arm bodies and their scopes, while declaring bindings.
|
||||
let arm_bodies: Vec<_> = arms.iter().map(|arm| {
|
||||
// BUG: use arm lint level
|
||||
let body = self.hir.mirror(arm.body.clone());
|
||||
let scope = self.declare_bindings(None, body.span, &arm.patterns[0]);
|
||||
let scope = self.declare_bindings(None, body.span,
|
||||
LintLevel::Inherited,
|
||||
&arm.patterns[0]);
|
||||
(body, scope.unwrap_or(self.visibility_scope))
|
||||
}).collect();
|
||||
|
||||
@ -171,11 +174,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
pub fn declare_bindings(&mut self,
|
||||
mut var_scope: Option<VisibilityScope>,
|
||||
scope_span: Span,
|
||||
lint_level: LintLevel,
|
||||
pattern: &Pattern<'tcx>)
|
||||
-> Option<VisibilityScope> {
|
||||
assert!(!(var_scope.is_some() && lint_level.is_explicit()),
|
||||
"can't have both a var and a lint scope at the same time");
|
||||
self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
|
||||
if var_scope.is_none() {
|
||||
var_scope = Some(this.new_visibility_scope(scope_span));
|
||||
var_scope = Some(this.new_visibility_scope(scope_span,
|
||||
LintLevel::Inherited));
|
||||
// If we have lints, create a new visibility scope
|
||||
// that marks the lints for the locals.
|
||||
if lint_level.is_explicit() {
|
||||
this.new_visibility_scope(scope_span, lint_level);
|
||||
}
|
||||
}
|
||||
let source_info = SourceInfo {
|
||||
span,
|
||||
@ -183,6 +195,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
this.declare_binding(source_info, mutability, name, var, ty);
|
||||
});
|
||||
// Pop any scope we created for the locals.
|
||||
if let Some(var_scope) = var_scope {
|
||||
self.visibility_scope = var_scope;
|
||||
}
|
||||
var_scope
|
||||
}
|
||||
|
||||
@ -712,6 +728,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ty: var_ty.clone(),
|
||||
name: Some(name),
|
||||
source_info,
|
||||
lexical_scope: self.visibility_scope,
|
||||
internal: false,
|
||||
is_user_variable: true,
|
||||
});
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
use build;
|
||||
use hair::cx::Cx;
|
||||
use hair::LintLevel;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::region;
|
||||
@ -277,6 +278,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
/// the vector of all scopes that we have created thus far;
|
||||
/// we track this for debuginfo later
|
||||
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
||||
visibility_scope_info: IndexVec<VisibilityScope, VisibilityScopeInfo>,
|
||||
visibility_scope: VisibilityScope,
|
||||
|
||||
/// Maps node ids of variable bindings to the `Local`s created for them.
|
||||
@ -378,8 +380,10 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
|
||||
let mut block = START_BLOCK;
|
||||
let source_info = builder.source_info(span);
|
||||
unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| {
|
||||
unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| {
|
||||
let call_site_s = (call_site_scope, source_info);
|
||||
unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
|
||||
let arg_scope_s = (arg_scope, source_info);
|
||||
unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
|
||||
builder.args_and_body(block, &arguments, arg_scope, &body.value)
|
||||
}));
|
||||
// Attribute epilogue to function's closing brace
|
||||
@ -456,9 +460,10 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
}
|
||||
|
||||
fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
body_id: hir::BodyId)
|
||||
-> Mir<'tcx> {
|
||||
let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
|
||||
body_id: hir::BodyId)
|
||||
-> Mir<'tcx> {
|
||||
let owner_id = hir.tcx().hir.body_owner(body_id);
|
||||
let span = hir.tcx().hir.span(owner_id);
|
||||
let ty = hir.tcx().types.err;
|
||||
let mut builder = Builder::new(hir, span, 0, ty);
|
||||
let source_info = builder.source_info(span);
|
||||
@ -472,6 +477,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
arg_count: usize,
|
||||
return_ty: Ty<'tcx>)
|
||||
-> Builder<'a, 'gcx, 'tcx> {
|
||||
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||
let mut builder = Builder {
|
||||
hir,
|
||||
cfg: CFG { basic_blocks: IndexVec::new() },
|
||||
@ -480,6 +486,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
scopes: vec![],
|
||||
visibility_scopes: IndexVec::new(),
|
||||
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
visibility_scope_info: IndexVec::new(),
|
||||
breakable_scopes: vec![],
|
||||
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
|
||||
span), 1),
|
||||
@ -490,7 +497,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
|
||||
assert_eq!(builder.new_visibility_scope(span), ARGUMENT_VISIBILITY_SCOPE);
|
||||
assert_eq!(
|
||||
builder.new_visibility_scope(span, lint_level),
|
||||
ARGUMENT_VISIBILITY_SCOPE);
|
||||
builder.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None;
|
||||
|
||||
builder
|
||||
@ -509,6 +518,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
Mir::new(self.cfg.basic_blocks,
|
||||
self.visibility_scopes,
|
||||
ClearOnDecode::Set(self.visibility_scope_info),
|
||||
IndexVec::new(),
|
||||
return_ty,
|
||||
yield_ty,
|
||||
@ -543,6 +553,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
span: pattern.map_or(self.fn_span, |pat| pat.span)
|
||||
},
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
name,
|
||||
internal: false,
|
||||
is_user_variable: false,
|
||||
@ -557,7 +568,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = self.hir.pattern_from_hir(pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span, &pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span,
|
||||
LintLevel::Inherited, &pattern);
|
||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,10 @@ should go to.
|
||||
*/
|
||||
|
||||
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
|
||||
use hair::LintLevel;
|
||||
use rustc::middle::region;
|
||||
use rustc::ty::{Ty, TyCtxt};
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use syntax_pos::{Span};
|
||||
@ -304,15 +306,37 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
/// to build its contents, popping the scope afterwards.
|
||||
pub fn in_scope<F, R>(&mut self,
|
||||
region_scope: (region::Scope, SourceInfo),
|
||||
lint_level: LintLevel,
|
||||
mut block: BasicBlock,
|
||||
f: F)
|
||||
-> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
|
||||
{
|
||||
debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block);
|
||||
let visibility_scope = self.visibility_scope;
|
||||
let tcx = self.hir.tcx();
|
||||
if let LintLevel::Explicit(node_id) = lint_level {
|
||||
let same_lint_scopes = tcx.dep_graph.with_ignore(|| {
|
||||
let sets = tcx.lint_levels(LOCAL_CRATE);
|
||||
let parent_hir_id =
|
||||
tcx.hir.definitions().node_to_hir_id(
|
||||
self.visibility_scope_info[visibility_scope].lint_root
|
||||
);
|
||||
let current_hir_id =
|
||||
tcx.hir.definitions().node_to_hir_id(node_id);
|
||||
sets.lint_level_set(parent_hir_id) ==
|
||||
sets.lint_level_set(current_hir_id)
|
||||
});
|
||||
|
||||
if !same_lint_scopes {
|
||||
self.visibility_scope =
|
||||
self.new_visibility_scope(region_scope.1.span, lint_level);
|
||||
}
|
||||
}
|
||||
self.push_scope(region_scope);
|
||||
let rv = unpack!(block = f(self));
|
||||
unpack!(block = self.pop_scope(region_scope, block));
|
||||
self.visibility_scope = visibility_scope;
|
||||
debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
|
||||
block.and(rv)
|
||||
}
|
||||
@ -474,13 +498,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
/// Creates a new visibility scope, nested in the current one.
|
||||
pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
|
||||
pub fn new_visibility_scope(&mut self,
|
||||
span: Span,
|
||||
lint_level: LintLevel) -> VisibilityScope {
|
||||
debug!("new_visibility_scope({:?}, {:?})", span, lint_level);
|
||||
let parent = self.visibility_scope;
|
||||
let scope = VisibilityScope::new(self.visibility_scopes.len());
|
||||
self.visibility_scopes.push(VisibilityScopeData {
|
||||
let info = if let LintLevel::Explicit(lint_level) = lint_level {
|
||||
VisibilityScopeInfo { lint_root: lint_level }
|
||||
} else {
|
||||
self.visibility_scope_info[parent].clone()
|
||||
};
|
||||
let scope = self.visibility_scopes.push(VisibilityScopeData {
|
||||
span,
|
||||
parent_scope: Some(parent),
|
||||
});
|
||||
self.visibility_scope_info.push(info);
|
||||
scope
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
init_scope: region::Scope::Node(hir_id.local_id),
|
||||
pattern,
|
||||
initializer: local.init.to_ref(),
|
||||
lint_level: cx.lint_level_of(local.id),
|
||||
},
|
||||
opt_destruction_scope: opt_dxn_ext,
|
||||
})));
|
||||
|
@ -48,22 +48,24 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
kind: ExprKind::Scope {
|
||||
region_scope: expr_scope,
|
||||
value: expr.to_ref(),
|
||||
lint_level: cx.lint_level_of(self.id),
|
||||
},
|
||||
};
|
||||
|
||||
// Finally, create a destruction scope, if any.
|
||||
if let Some(region_scope) =
|
||||
cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
|
||||
expr = Expr {
|
||||
temp_lifetime,
|
||||
ty: expr.ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Scope {
|
||||
region_scope,
|
||||
value: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
}
|
||||
cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
|
||||
expr = Expr {
|
||||
temp_lifetime,
|
||||
ty: expr.ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Scope {
|
||||
region_scope,
|
||||
value: expr.to_ref(),
|
||||
lint_level: LintLevel::Inherited,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// OK, all done!
|
||||
expr
|
||||
@ -619,6 +621,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm)
|
||||
patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
// BUG: fix this
|
||||
lint_level: LintLevel::Inherited,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,14 @@ use rustc::mir::transform::MirSource;
|
||||
use rustc::middle::const_val::{ConstEvalErr, ConstVal};
|
||||
use rustc_const_eval::ConstContext;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::middle::region;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir;
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
@ -37,6 +38,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
pub root_lint_level: ast::NodeId,
|
||||
pub param_env: ty::ParamEnv<'gcx>,
|
||||
|
||||
/// Identity `Substs` for use with const-evaluation.
|
||||
@ -57,7 +59,8 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
|
||||
let constness = match src {
|
||||
MirSource::Const(_) |
|
||||
MirSource::Static(..) => hir::Constness::Const,
|
||||
@ -87,9 +90,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
// Constants and const fn's always need overflow checks.
|
||||
check_overflow |= constness == hir::Constness::Const;
|
||||
|
||||
let lint_level = lint_level_for_hir_id(tcx, src_id);
|
||||
Cx {
|
||||
tcx,
|
||||
infcx,
|
||||
root_lint_level: lint_level,
|
||||
param_env: tcx.param_env(src_def_id),
|
||||
identity_substs: Substs::identity_for_item(tcx.global_tcx(), src_def_id),
|
||||
region_scope_tree: tcx.region_scope_tree(src_def_id),
|
||||
@ -99,6 +104,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
check_overflow,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
@ -229,6 +235,19 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
ty.needs_drop(self.tcx.global_tcx(), param_env)
|
||||
}
|
||||
|
||||
fn lint_level_of(&self, node_id: ast::NodeId) -> LintLevel {
|
||||
let hir_id = self.tcx.hir.definitions().node_to_hir_id(node_id);
|
||||
let has_lint_level = self.tcx.dep_graph.with_ignore(|| {
|
||||
self.tcx.lint_levels(LOCAL_CRATE).lint_level_set(hir_id).is_some()
|
||||
});
|
||||
|
||||
if has_lint_level {
|
||||
LintLevel::Explicit(node_id)
|
||||
} else {
|
||||
LintLevel::Inherited
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
@ -242,6 +261,31 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
|
||||
// Right now we insert a `with_ignore` node in the dep graph here to
|
||||
// ignore the fact that `lint_levels` below depends on the entire crate.
|
||||
// For now this'll prevent false positives of recompiling too much when
|
||||
// anything changes.
|
||||
//
|
||||
// Once red/green incremental compilation lands we should be able to
|
||||
// remove this because while the crate changes often the lint level map
|
||||
// will change rarely.
|
||||
tcx.dep_graph.with_ignore(|| {
|
||||
let sets = tcx.lint_levels(LOCAL_CRATE);
|
||||
loop {
|
||||
let hir_id = tcx.hir.definitions().node_to_hir_id(id);
|
||||
if sets.lint_level_set(hir_id).is_some() {
|
||||
return id
|
||||
}
|
||||
let next = tcx.hir.get_parent_node(id);
|
||||
if next == id {
|
||||
bug!("lint traversal reached the root of the crate");
|
||||
}
|
||||
id = next;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
mod block;
|
||||
mod expr;
|
||||
mod to_ref;
|
||||
|
@ -29,6 +29,21 @@ pub mod cx;
|
||||
|
||||
pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum LintLevel {
|
||||
Inherited,
|
||||
Explicit(ast::NodeId)
|
||||
}
|
||||
|
||||
impl LintLevel {
|
||||
pub fn is_explicit(self) -> bool {
|
||||
match self {
|
||||
LintLevel::Inherited => false,
|
||||
LintLevel::Explicit(_) => true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Block<'tcx> {
|
||||
pub targeted_by_break: bool,
|
||||
@ -73,7 +88,10 @@ pub enum StmtKind<'tcx> {
|
||||
pattern: Pattern<'tcx>,
|
||||
|
||||
/// let pat = <INIT> ...
|
||||
initializer: Option<ExprRef<'tcx>>
|
||||
initializer: Option<ExprRef<'tcx>>,
|
||||
|
||||
/// the lint level for this let-statement
|
||||
lint_level: LintLevel,
|
||||
},
|
||||
}
|
||||
|
||||
@ -111,6 +129,7 @@ pub struct Expr<'tcx> {
|
||||
pub enum ExprKind<'tcx> {
|
||||
Scope {
|
||||
region_scope: region::Scope,
|
||||
lint_level: LintLevel,
|
||||
value: ExprRef<'tcx>,
|
||||
},
|
||||
Box {
|
||||
@ -275,6 +294,7 @@ pub struct Arm<'tcx> {
|
||||
pub patterns: Vec<Pattern<'tcx>>,
|
||||
pub guard: Option<ExprRef<'tcx>>,
|
||||
pub body: ExprRef<'tcx>,
|
||||
pub lint_level: LintLevel,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -140,6 +140,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
|
||||
LocalDecl {
|
||||
mutability, ty, name: None,
|
||||
source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
is_user_variable: false
|
||||
}
|
||||
@ -195,6 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||
),
|
||||
ClearOnDecode::Clear,
|
||||
IndexVec::new(),
|
||||
sig.output(),
|
||||
None,
|
||||
@ -342,6 +344,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: self.span, parent_scope: None }, 1
|
||||
),
|
||||
ClearOnDecode::Clear,
|
||||
IndexVec::new(),
|
||||
self.sig.output(),
|
||||
None,
|
||||
@ -804,6 +807,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||
),
|
||||
ClearOnDecode::Clear,
|
||||
IndexVec::new(),
|
||||
sig.output(),
|
||||
None,
|
||||
@ -876,6 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||
),
|
||||
ClearOnDecode::Clear,
|
||||
IndexVec::new(),
|
||||
sig.output(),
|
||||
None,
|
||||
|
@ -301,6 +301,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
|
||||
ty: ret_ty,
|
||||
name: None,
|
||||
source_info: source_info(mir),
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
is_user_variable: false,
|
||||
};
|
||||
@ -559,6 +560,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||
ty: tcx.mk_nil(),
|
||||
name: None,
|
||||
source_info,
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
is_user_variable: false,
|
||||
};
|
||||
@ -574,6 +576,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||
}),
|
||||
name: None,
|
||||
source_info,
|
||||
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
internal: false,
|
||||
is_user_variable: false,
|
||||
};
|
||||
|
@ -380,10 +380,10 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||
let mut promoter = Promoter {
|
||||
promoted: Mir::new(
|
||||
IndexVec::new(),
|
||||
Some(VisibilityScopeData {
|
||||
span,
|
||||
parent_scope: None
|
||||
}).into_iter().collect(),
|
||||
// FIXME: maybe try to filter this to avoid blowing up
|
||||
// memory usage?
|
||||
mir.visibility_scopes.clone(),
|
||||
mir.visibility_scope_info.clone(),
|
||||
IndexVec::new(),
|
||||
ty,
|
||||
None,
|
||||
|
@ -2236,7 +2236,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
adjusted_ty,
|
||||
index_ty);
|
||||
|
||||
|
||||
// First, try built-in indexing.
|
||||
match (adjusted_ty.builtin_index(), &index_ty.sty) {
|
||||
(Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user