add lint levels to VisibilityScope

This commit is contained in:
Ariel Ben-Yehuda 2017-09-13 22:33:07 +03:00
parent acb73dbe8b
commit 8c7500f9b6
24 changed files with 269 additions and 53 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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),

View File

@ -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,

View File

@ -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);

View File

@ -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)
}) })

View File

@ -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 },

View File

@ -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)
}) })
} }

View File

@ -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)
}); });
} }

View File

@ -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));

View File

@ -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)
}); });
} }

View File

@ -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)

View File

@ -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)
}) })
} }

View File

@ -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,
}); });

View File

@ -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));
} }

View File

@ -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
} }

View File

@ -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,
}))); })));

View File

@ -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,
} }
} }

View File

@ -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;

View File

@ -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)]

View File

@ -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,

View File

@ -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,
}; };

View File

@ -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,

View File

@ -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(_))) => {