mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 10:45:18 +00:00
Add result sanity check to is_to_be_inferred
.
This version of `is_to_be_inferred` double-checks the result from `inferred_map` by querying the `named_region_map` and `ast_map` and then asserts that the `inferred_map` state is consistent with its own findings. (See issue 13261 for further discussion of the approaches).
This commit is contained in:
parent
364d82e7f3
commit
3099451020
@ -198,6 +198,7 @@ use arena::Arena;
|
||||
use middle::ty;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util;
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
use syntax::visit;
|
||||
@ -517,6 +518,13 @@ impl<'a> Visitor<()> for ConstraintContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is `param_id` a lifetime according to `map`?
|
||||
fn is_lifetime(map: &ast_map::Map, param_id: ast::NodeId) -> bool {
|
||||
match map.find(param_id) {
|
||||
Some(ast_map::NodeLifetime(..)) => true, _ => false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ConstraintContext<'a> {
|
||||
fn tcx(&self) -> &'a ty::ctxt {
|
||||
self.terms_cx.tcx
|
||||
@ -533,8 +541,68 @@ impl<'a> ConstraintContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
|
||||
let tcx = self.terms_cx.tcx;
|
||||
assert!(is_lifetime(&tcx.map, param_id));
|
||||
match tcx.named_region_map.find(¶m_id) {
|
||||
Some(&ast::DefEarlyBoundRegion(_, lifetime_decl_id))
|
||||
=> lifetime_decl_id,
|
||||
Some(_) => fail!("should not encounter non early-bound cases"),
|
||||
|
||||
// The lookup should only fail when `param_id` is
|
||||
// itself a lifetime binding: use it as the decl_id.
|
||||
None => param_id,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Is `param_id` a type parameter for which we infer variance?
|
||||
fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
|
||||
self.terms_cx.inferred_map.contains_key(¶m_id)
|
||||
let result = self.terms_cx.inferred_map.contains_key(¶m_id);
|
||||
|
||||
// To safe-guard against invalid inferred_map constructions,
|
||||
// double-check if variance is inferred at some use of a type
|
||||
// parameter (by inspecting parent of its binding declaration
|
||||
// to see if it is introduced by a type or by a fn/impl).
|
||||
|
||||
let check_result = |this:&ConstraintContext| -> bool {
|
||||
let tcx = this.terms_cx.tcx;
|
||||
let decl_id = this.find_binding_for_lifetime(param_id);
|
||||
// Currently only called on lifetimes; double-checking that.
|
||||
assert!(is_lifetime(&tcx.map, param_id));
|
||||
let parent_id = tcx.map.get_parent(decl_id);
|
||||
let parent = tcx.map.find(parent_id).unwrap_or_else(
|
||||
|| fail!("tcx.map missing entry for id: {}", parent_id));
|
||||
|
||||
let is_inferred;
|
||||
macro_rules! cannot_happen { () => { {
|
||||
fail!("invalid parent: {:s} for {:s}",
|
||||
tcx.map.node_to_str(parent_id),
|
||||
tcx.map.node_to_str(param_id));
|
||||
} } }
|
||||
|
||||
match parent {
|
||||
ast_map::NodeItem(p) => {
|
||||
match p.node {
|
||||
ast::ItemTy(..) |
|
||||
ast::ItemEnum(..) |
|
||||
ast::ItemStruct(..) |
|
||||
ast::ItemTrait(..) => is_inferred = true,
|
||||
ast::ItemFn(..) => is_inferred = false,
|
||||
_ => cannot_happen!(),
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(..) => is_inferred = false,
|
||||
ast_map::NodeMethod(_) => is_inferred = false,
|
||||
_ => cannot_happen!(),
|
||||
}
|
||||
|
||||
return is_inferred;
|
||||
};
|
||||
|
||||
assert_eq!(result, check_result(self));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn declared_variance(&self,
|
||||
|
Loading…
Reference in New Issue
Block a user