mirror of https://github.com/rust-lang/rust.git
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,
|
name,
|
||||||
source_info,
|
source_info,
|
||||||
internal,
|
internal,
|
||||||
|
lexical_scope,
|
||||||
is_user_variable
|
is_user_variable
|
||||||
});
|
});
|
||||||
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
|
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 {
|
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local {
|
||||||
#[inline]
|
#[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::VisibilityScopeData { span, parent_scope });
|
||||||
|
impl_stable_hash_for!(struct mir::VisibilityScopeInfo { lint_root });
|
||||||
|
|
||||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
|
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
|
|
@ -384,6 +384,11 @@ impl LintLevelMap {
|
||||||
self.sets.get_lint_level(lint, *idx, None)
|
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 {
|
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::dominators::{Dominators, dominators};
|
||||||
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
|
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
|
||||||
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
|
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
|
||||||
|
use rustc_serialize as serialize;
|
||||||
use hir::def::CtorKind;
|
use hir::def::CtorKind;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use ty::subst::{Subst, Substs};
|
use ty::subst::{Subst, Substs};
|
||||||
|
@ -33,7 +34,7 @@ use std::fmt::{self, Debug, Formatter, Write};
|
||||||
use std::{iter, u32};
|
use std::{iter, u32};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
use syntax::ast::Name;
|
use syntax::ast::{self, Name};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
|
@ -96,6 +97,10 @@ pub struct Mir<'tcx> {
|
||||||
/// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
|
/// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
|
||||||
pub visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
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.
|
/// 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
|
/// Each of them is the Mir of a constant with the fn's type parameters
|
||||||
/// in scope, but a separate set of locals.
|
/// in scope, but a separate set of locals.
|
||||||
|
@ -151,6 +156,8 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0);
|
||||||
impl<'tcx> Mir<'tcx> {
|
impl<'tcx> Mir<'tcx> {
|
||||||
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||||
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
||||||
|
visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope,
|
||||||
|
VisibilityScopeInfo>>,
|
||||||
promoted: IndexVec<Promoted, Mir<'tcx>>,
|
promoted: IndexVec<Promoted, Mir<'tcx>>,
|
||||||
return_ty: Ty<'tcx>,
|
return_ty: Ty<'tcx>,
|
||||||
yield_ty: Option<Ty<'tcx>>,
|
yield_ty: Option<Ty<'tcx>>,
|
||||||
|
@ -167,6 +174,7 @@ impl<'tcx> Mir<'tcx> {
|
||||||
Mir {
|
Mir {
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
visibility_scopes,
|
visibility_scopes,
|
||||||
|
visibility_scope_info,
|
||||||
promoted,
|
promoted,
|
||||||
return_ty,
|
return_ty,
|
||||||
yield_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> {
|
impl_stable_hash_for!(struct Mir<'tcx> {
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
visibility_scopes,
|
visibility_scopes,
|
||||||
|
visibility_scope_info,
|
||||||
promoted,
|
promoted,
|
||||||
return_ty,
|
return_ty,
|
||||||
yield_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.
|
/// Grouped information about the source code origin of a MIR entity.
|
||||||
/// Intended to be inspected by diagnostics and debuginfo.
|
/// Intended to be inspected by diagnostics and debuginfo.
|
||||||
/// Most passes can work with it as a whole, within a single function.
|
/// 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.
|
/// Source info of the local.
|
||||||
pub source_info: SourceInfo,
|
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> {
|
impl<'tcx> LocalDecl<'tcx> {
|
||||||
|
@ -452,6 +491,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||||
span,
|
span,
|
||||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||||
},
|
},
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false
|
is_user_variable: false
|
||||||
}
|
}
|
||||||
|
@ -468,6 +508,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||||
span,
|
span,
|
||||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||||
},
|
},
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: true,
|
internal: true,
|
||||||
is_user_variable: false
|
is_user_variable: false
|
||||||
}
|
}
|
||||||
|
@ -485,6 +526,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||||
span,
|
span,
|
||||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||||
},
|
},
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
name: None, // FIXME maybe we do want some name here?
|
name: None, // FIXME maybe we do want some name here?
|
||||||
is_user_variable: false
|
is_user_variable: false
|
||||||
|
@ -1607,6 +1649,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
|
||||||
Mir {
|
Mir {
|
||||||
basic_blocks: self.basic_blocks.fold_with(folder),
|
basic_blocks: self.basic_blocks.fold_with(folder),
|
||||||
visibility_scopes: self.visibility_scopes.clone(),
|
visibility_scopes: self.visibility_scopes.clone(),
|
||||||
|
visibility_scope_info: self.visibility_scope_info.clone(),
|
||||||
promoted: self.promoted.fold_with(folder),
|
promoted: self.promoted.fold_with(folder),
|
||||||
return_ty: self.return_ty.fold_with(folder),
|
return_ty: self.return_ty.fold_with(folder),
|
||||||
yield_ty: self.yield_ty.fold_with(folder),
|
yield_ty: self.yield_ty.fold_with(folder),
|
||||||
|
|
|
@ -690,11 +690,13 @@ macro_rules! make_mir_visitor {
|
||||||
name: _,
|
name: _,
|
||||||
ref $($mutability)* source_info,
|
ref $($mutability)* source_info,
|
||||||
internal: _,
|
internal: _,
|
||||||
|
ref $($mutability)* lexical_scope,
|
||||||
is_user_variable: _,
|
is_user_variable: _,
|
||||||
} = *local_decl;
|
} = *local_decl;
|
||||||
|
|
||||||
self.visit_ty(ty, Lookup::Src(*source_info));
|
self.visit_ty(ty, Lookup::Src(*source_info));
|
||||||
self.visit_source_info(source_info);
|
self.visit_source_info(source_info);
|
||||||
|
self.visit_visibility_scope(lexical_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_visibility_scope(&mut self,
|
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
|
// FIXME: ariel points SimplifyBranches should run after
|
||||||
// mir-borrowck; otherwise code within `if false { ... }` would
|
// mir-borrowck; otherwise code within `if false { ... }` would
|
||||||
// not be checked.
|
// 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::simplify::SimplifyCfg::new("qualify-consts"));
|
||||||
passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL);
|
passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL);
|
||||||
|
|
||||||
// borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
|
// 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::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::add_call_guards::CriticalCallEdges);
|
||||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
|
passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
|
||||||
passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
|
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 } =
|
let Block { region_scope, opt_destruction_scope, span, stmts, expr, targeted_by_break } =
|
||||||
self.hir.mirror(ast_block);
|
self.hir.mirror(ast_block);
|
||||||
self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
|
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 {
|
if targeted_by_break {
|
||||||
// This is a `break`-able block (currently only `catch { ... }`)
|
// This is a `break`-able block (currently only `catch { ... }`)
|
||||||
let exit_block = this.cfg.start_new_block();
|
let exit_block = this.cfg.start_new_block();
|
||||||
|
@ -76,13 +76,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
StmtKind::Expr { scope, expr } => {
|
StmtKind::Expr { scope, expr } => {
|
||||||
unpack!(block = this.in_opt_scope(
|
unpack!(block = this.in_opt_scope(
|
||||||
opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
|
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);
|
let expr = this.hir.mirror(expr);
|
||||||
this.stmt_expr(block, 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.
|
// Enter the remainder scope, i.e. the bindings' destruction scope.
|
||||||
this.push_scope((remainder_scope, source_info));
|
this.push_scope((remainder_scope, source_info));
|
||||||
let_scope_stack.push(remainder_scope);
|
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.
|
// Declare the bindings, which may create a visibility scope.
|
||||||
let remainder_span = remainder_scope.span(this.hir.tcx(),
|
let remainder_span = remainder_scope.span(this.hir.tcx(),
|
||||||
&this.hir.region_scope_tree);
|
&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.
|
// Evaluate the initializer, if present.
|
||||||
if let Some(init) = initializer {
|
if let Some(init) = initializer {
|
||||||
unpack!(block = this.in_opt_scope(
|
unpack!(block = this.in_opt_scope(
|
||||||
opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
|
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 ^~~~
|
// FIXME #30046 ^~~~
|
||||||
this.expr_into_pattern(block, pattern, init)
|
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 }
|
let Expr { ty, temp_lifetime: _, span, kind }
|
||||||
= expr;
|
= expr;
|
||||||
match kind {
|
match kind {
|
||||||
ExprKind::Scope { region_scope: _, value } =>
|
ExprKind::Scope { region_scope: _, lint_level: _, value } =>
|
||||||
this.as_constant(value),
|
this.as_constant(value),
|
||||||
ExprKind::Literal { literal } =>
|
ExprKind::Literal { literal } =>
|
||||||
Constant { span: span, ty: ty, 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 expr_span = expr.span;
|
||||||
let source_info = this.source_info(expr_span);
|
let source_info = this.source_info(expr_span);
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
this.in_scope((region_scope, source_info), block, |this| {
|
this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||||
this.as_lvalue(block, value)
|
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);
|
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
|
||||||
let this = self;
|
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 source_info = this.source_info(expr.span);
|
||||||
let region_scope = (region_scope, source_info);
|
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)
|
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);
|
let source_info = this.source_info(expr_span);
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
let region_scope = (region_scope, source_info);
|
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 } => {
|
ExprKind::Repeat { value, count } => {
|
||||||
let value_operand = unpack!(block = this.as_operand(block, scope, value));
|
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 expr_span = expr.span;
|
||||||
let source_info = this.source_info(expr_span);
|
let source_info = this.source_info(expr_span);
|
||||||
if let ExprKind::Scope { region_scope, value } = expr.kind {
|
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||||
return this.in_scope((region_scope, source_info), block, |this| {
|
return this.in_scope((region_scope, source_info), lint_level, block, |this| {
|
||||||
this.as_temp(block, temp_lifetime, value)
|
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);
|
let source_info = this.source_info(expr_span);
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
let region_scope = (region_scope, source_info);
|
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 } => {
|
ExprKind::Block { body: ast_block } => {
|
||||||
this.ast_block(destination, block, ast_block, source_info)
|
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
|
// Handle a number of expressions that don't need a destination at all. This
|
||||||
// avoids needing a mountain of temporary `()` variables.
|
// avoids needing a mountain of temporary `()` variables.
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
let value = this.hir.mirror(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)
|
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.
|
// Get the arm bodies and their scopes, while declaring bindings.
|
||||||
let arm_bodies: Vec<_> = arms.iter().map(|arm| {
|
let arm_bodies: Vec<_> = arms.iter().map(|arm| {
|
||||||
|
// BUG: use arm lint level
|
||||||
let body = self.hir.mirror(arm.body.clone());
|
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))
|
(body, scope.unwrap_or(self.visibility_scope))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
@ -171,11 +174,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
pub fn declare_bindings(&mut self,
|
pub fn declare_bindings(&mut self,
|
||||||
mut var_scope: Option<VisibilityScope>,
|
mut var_scope: Option<VisibilityScope>,
|
||||||
scope_span: Span,
|
scope_span: Span,
|
||||||
|
lint_level: LintLevel,
|
||||||
pattern: &Pattern<'tcx>)
|
pattern: &Pattern<'tcx>)
|
||||||
-> Option<VisibilityScope> {
|
-> 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| {
|
self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
|
||||||
if var_scope.is_none() {
|
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 {
|
let source_info = SourceInfo {
|
||||||
span,
|
span,
|
||||||
|
@ -183,6 +195,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
this.declare_binding(source_info, mutability, name, var, ty);
|
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
|
var_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,6 +728,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
ty: var_ty.clone(),
|
ty: var_ty.clone(),
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
source_info,
|
source_info,
|
||||||
|
lexical_scope: self.visibility_scope,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: true,
|
is_user_variable: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
use build;
|
use build;
|
||||||
use hair::cx::Cx;
|
use hair::cx::Cx;
|
||||||
|
use hair::LintLevel;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::middle::region;
|
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;
|
/// the vector of all scopes that we have created thus far;
|
||||||
/// we track this for debuginfo later
|
/// we track this for debuginfo later
|
||||||
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
|
||||||
|
visibility_scope_info: IndexVec<VisibilityScope, VisibilityScopeInfo>,
|
||||||
visibility_scope: VisibilityScope,
|
visibility_scope: VisibilityScope,
|
||||||
|
|
||||||
/// Maps node ids of variable bindings to the `Local`s created for them.
|
/// 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 arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| {
|
let call_site_s = (call_site_scope, source_info);
|
||||||
unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| {
|
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)
|
builder.args_and_body(block, &arguments, arg_scope, &body.value)
|
||||||
}));
|
}));
|
||||||
// Attribute epilogue to function's closing brace
|
// 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>,
|
fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||||
body_id: hir::BodyId)
|
body_id: hir::BodyId)
|
||||||
-> Mir<'tcx> {
|
-> Mir<'tcx> {
|
||||||
let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
|
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 ty = hir.tcx().types.err;
|
||||||
let mut builder = Builder::new(hir, span, 0, ty);
|
let mut builder = Builder::new(hir, span, 0, ty);
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
|
@ -472,6 +477,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
return_ty: Ty<'tcx>)
|
return_ty: Ty<'tcx>)
|
||||||
-> Builder<'a, 'gcx, 'tcx> {
|
-> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||||
let mut builder = Builder {
|
let mut builder = Builder {
|
||||||
hir,
|
hir,
|
||||||
cfg: CFG { basic_blocks: IndexVec::new() },
|
cfg: CFG { basic_blocks: IndexVec::new() },
|
||||||
|
@ -480,6 +486,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
scopes: vec![],
|
scopes: vec![],
|
||||||
visibility_scopes: IndexVec::new(),
|
visibility_scopes: IndexVec::new(),
|
||||||
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
|
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
|
visibility_scope_info: IndexVec::new(),
|
||||||
breakable_scopes: vec![],
|
breakable_scopes: vec![],
|
||||||
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
|
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
|
||||||
span), 1),
|
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.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.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None;
|
||||||
|
|
||||||
builder
|
builder
|
||||||
|
@ -509,6 +518,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
Mir::new(self.cfg.basic_blocks,
|
Mir::new(self.cfg.basic_blocks,
|
||||||
self.visibility_scopes,
|
self.visibility_scopes,
|
||||||
|
ClearOnDecode::Set(self.visibility_scope_info),
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
return_ty,
|
return_ty,
|
||||||
yield_ty,
|
yield_ty,
|
||||||
|
@ -543,6 +553,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
scope: ARGUMENT_VISIBILITY_SCOPE,
|
scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
span: pattern.map_or(self.fn_span, |pat| pat.span)
|
span: pattern.map_or(self.fn_span, |pat| pat.span)
|
||||||
},
|
},
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
name,
|
name,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false,
|
is_user_variable: false,
|
||||||
|
@ -557,7 +568,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Some(pattern) = pattern {
|
if let Some(pattern) = pattern {
|
||||||
let pattern = self.hir.pattern_from_hir(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));
|
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,10 @@ should go to.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
|
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
|
||||||
|
use hair::LintLevel;
|
||||||
use rustc::middle::region;
|
use rustc::middle::region;
|
||||||
use rustc::ty::{Ty, TyCtxt};
|
use rustc::ty::{Ty, TyCtxt};
|
||||||
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::transform::MirSource;
|
use rustc::mir::transform::MirSource;
|
||||||
use syntax_pos::{Span};
|
use syntax_pos::{Span};
|
||||||
|
@ -304,15 +306,37 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
/// to build its contents, popping the scope afterwards.
|
/// to build its contents, popping the scope afterwards.
|
||||||
pub fn in_scope<F, R>(&mut self,
|
pub fn in_scope<F, R>(&mut self,
|
||||||
region_scope: (region::Scope, SourceInfo),
|
region_scope: (region::Scope, SourceInfo),
|
||||||
|
lint_level: LintLevel,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
f: F)
|
f: F)
|
||||||
-> BlockAnd<R>
|
-> BlockAnd<R>
|
||||||
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
|
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
|
||||||
{
|
{
|
||||||
debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block);
|
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);
|
self.push_scope(region_scope);
|
||||||
let rv = unpack!(block = f(self));
|
let rv = unpack!(block = f(self));
|
||||||
unpack!(block = self.pop_scope(region_scope, block));
|
unpack!(block = self.pop_scope(region_scope, block));
|
||||||
|
self.visibility_scope = visibility_scope;
|
||||||
debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
|
debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
|
||||||
block.and(rv)
|
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.
|
/// 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 parent = self.visibility_scope;
|
||||||
let scope = VisibilityScope::new(self.visibility_scopes.len());
|
let info = if let LintLevel::Explicit(lint_level) = lint_level {
|
||||||
self.visibility_scopes.push(VisibilityScopeData {
|
VisibilityScopeInfo { lint_root: lint_level }
|
||||||
|
} else {
|
||||||
|
self.visibility_scope_info[parent].clone()
|
||||||
|
};
|
||||||
|
let scope = self.visibility_scopes.push(VisibilityScopeData {
|
||||||
span,
|
span,
|
||||||
parent_scope: Some(parent),
|
parent_scope: Some(parent),
|
||||||
});
|
});
|
||||||
|
self.visibility_scope_info.push(info);
|
||||||
scope
|
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),
|
init_scope: region::Scope::Node(hir_id.local_id),
|
||||||
pattern,
|
pattern,
|
||||||
initializer: local.init.to_ref(),
|
initializer: local.init.to_ref(),
|
||||||
|
lint_level: cx.lint_level_of(local.id),
|
||||||
},
|
},
|
||||||
opt_destruction_scope: opt_dxn_ext,
|
opt_destruction_scope: opt_dxn_ext,
|
||||||
})));
|
})));
|
||||||
|
|
|
@ -48,22 +48,24 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||||
kind: ExprKind::Scope {
|
kind: ExprKind::Scope {
|
||||||
region_scope: expr_scope,
|
region_scope: expr_scope,
|
||||||
value: expr.to_ref(),
|
value: expr.to_ref(),
|
||||||
|
lint_level: cx.lint_level_of(self.id),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Finally, create a destruction scope, if any.
|
// Finally, create a destruction scope, if any.
|
||||||
if let Some(region_scope) =
|
if let Some(region_scope) =
|
||||||
cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
|
cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
|
||||||
expr = Expr {
|
expr = Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: expr.ty,
|
ty: expr.ty,
|
||||||
span: self.span,
|
span: self.span,
|
||||||
kind: ExprKind::Scope {
|
kind: ExprKind::Scope {
|
||||||
region_scope,
|
region_scope,
|
||||||
value: expr.to_ref(),
|
value: expr.to_ref(),
|
||||||
},
|
lint_level: LintLevel::Inherited,
|
||||||
};
|
},
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// OK, all done!
|
// OK, all done!
|
||||||
expr
|
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(),
|
patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
|
||||||
guard: arm.guard.to_ref(),
|
guard: arm.guard.to_ref(),
|
||||||
body: arm.body.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::middle::const_val::{ConstEvalErr, ConstVal};
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
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::hir::map::blocks::FnLikeNode;
|
||||||
use rustc::middle::region;
|
use rustc::middle::region;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::ty::subst::Subst;
|
use rustc::ty::subst::Subst;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
use syntax::ast;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc_const_math::{ConstInt, ConstUsize};
|
use rustc_const_math::{ConstInt, ConstUsize};
|
||||||
|
@ -37,6 +38,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
|
pub root_lint_level: ast::NodeId,
|
||||||
pub param_env: ty::ParamEnv<'gcx>,
|
pub param_env: ty::ParamEnv<'gcx>,
|
||||||
|
|
||||||
/// Identity `Substs` for use with const-evaluation.
|
/// 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> {
|
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 {
|
let constness = match src {
|
||||||
MirSource::Const(_) |
|
MirSource::Const(_) |
|
||||||
MirSource::Static(..) => hir::Constness::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.
|
// Constants and const fn's always need overflow checks.
|
||||||
check_overflow |= constness == hir::Constness::Const;
|
check_overflow |= constness == hir::Constness::Const;
|
||||||
|
|
||||||
|
let lint_level = lint_level_for_hir_id(tcx, src_id);
|
||||||
Cx {
|
Cx {
|
||||||
tcx,
|
tcx,
|
||||||
infcx,
|
infcx,
|
||||||
|
root_lint_level: lint_level,
|
||||||
param_env: tcx.param_env(src_def_id),
|
param_env: tcx.param_env(src_def_id),
|
||||||
identity_substs: Substs::identity_for_item(tcx.global_tcx(), 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),
|
region_scope_tree: tcx.region_scope_tree(src_def_id),
|
||||||
|
@ -99,6 +104,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
check_overflow,
|
check_overflow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
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)
|
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> {
|
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.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 block;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod to_ref;
|
mod to_ref;
|
||||||
|
|
|
@ -29,6 +29,21 @@ pub mod cx;
|
||||||
|
|
||||||
pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Block<'tcx> {
|
pub struct Block<'tcx> {
|
||||||
pub targeted_by_break: bool,
|
pub targeted_by_break: bool,
|
||||||
|
@ -73,7 +88,10 @@ pub enum StmtKind<'tcx> {
|
||||||
pattern: Pattern<'tcx>,
|
pattern: Pattern<'tcx>,
|
||||||
|
|
||||||
/// let pat = <INIT> ...
|
/// 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> {
|
pub enum ExprKind<'tcx> {
|
||||||
Scope {
|
Scope {
|
||||||
region_scope: region::Scope,
|
region_scope: region::Scope,
|
||||||
|
lint_level: LintLevel,
|
||||||
value: ExprRef<'tcx>,
|
value: ExprRef<'tcx>,
|
||||||
},
|
},
|
||||||
Box {
|
Box {
|
||||||
|
@ -275,6 +294,7 @@ pub struct Arm<'tcx> {
|
||||||
pub patterns: Vec<Pattern<'tcx>>,
|
pub patterns: Vec<Pattern<'tcx>>,
|
||||||
pub guard: Option<ExprRef<'tcx>>,
|
pub guard: Option<ExprRef<'tcx>>,
|
||||||
pub body: ExprRef<'tcx>,
|
pub body: ExprRef<'tcx>,
|
||||||
|
pub lint_level: LintLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
|
@ -140,6 +140,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
|
||||||
LocalDecl {
|
LocalDecl {
|
||||||
mutability, ty, name: None,
|
mutability, ty, name: None,
|
||||||
source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
|
source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false
|
is_user_variable: false
|
||||||
}
|
}
|
||||||
|
@ -195,6 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
IndexVec::from_elem_n(
|
IndexVec::from_elem_n(
|
||||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||||
),
|
),
|
||||||
|
ClearOnDecode::Clear,
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
sig.output(),
|
sig.output(),
|
||||||
None,
|
None,
|
||||||
|
@ -342,6 +344,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
||||||
IndexVec::from_elem_n(
|
IndexVec::from_elem_n(
|
||||||
VisibilityScopeData { span: self.span, parent_scope: None }, 1
|
VisibilityScopeData { span: self.span, parent_scope: None }, 1
|
||||||
),
|
),
|
||||||
|
ClearOnDecode::Clear,
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
self.sig.output(),
|
self.sig.output(),
|
||||||
None,
|
None,
|
||||||
|
@ -804,6 +807,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
IndexVec::from_elem_n(
|
IndexVec::from_elem_n(
|
||||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||||
),
|
),
|
||||||
|
ClearOnDecode::Clear,
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
sig.output(),
|
sig.output(),
|
||||||
None,
|
None,
|
||||||
|
@ -876,6 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
IndexVec::from_elem_n(
|
IndexVec::from_elem_n(
|
||||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||||
),
|
),
|
||||||
|
ClearOnDecode::Clear,
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
sig.output(),
|
sig.output(),
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -301,6 +301,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
|
||||||
ty: ret_ty,
|
ty: ret_ty,
|
||||||
name: None,
|
name: None,
|
||||||
source_info: source_info(mir),
|
source_info: source_info(mir),
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false,
|
is_user_variable: false,
|
||||||
};
|
};
|
||||||
|
@ -559,6 +560,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||||
ty: tcx.mk_nil(),
|
ty: tcx.mk_nil(),
|
||||||
name: None,
|
name: None,
|
||||||
source_info,
|
source_info,
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false,
|
is_user_variable: false,
|
||||||
};
|
};
|
||||||
|
@ -574,6 +576,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||||
}),
|
}),
|
||||||
name: None,
|
name: None,
|
||||||
source_info,
|
source_info,
|
||||||
|
lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||||
internal: false,
|
internal: false,
|
||||||
is_user_variable: false,
|
is_user_variable: false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -380,10 +380,10 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
||||||
let mut promoter = Promoter {
|
let mut promoter = Promoter {
|
||||||
promoted: Mir::new(
|
promoted: Mir::new(
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
Some(VisibilityScopeData {
|
// FIXME: maybe try to filter this to avoid blowing up
|
||||||
span,
|
// memory usage?
|
||||||
parent_scope: None
|
mir.visibility_scopes.clone(),
|
||||||
}).into_iter().collect(),
|
mir.visibility_scope_info.clone(),
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
ty,
|
ty,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -2236,7 +2236,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
adjusted_ty,
|
adjusted_ty,
|
||||||
index_ty);
|
index_ty);
|
||||||
|
|
||||||
|
|
||||||
// First, try built-in indexing.
|
// First, try built-in indexing.
|
||||||
match (adjusted_ty.builtin_index(), &index_ty.sty) {
|
match (adjusted_ty.builtin_index(), &index_ty.sty) {
|
||||||
(Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
|
(Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
|
||||||
|
|
Loading…
Reference in New Issue