Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/compiletest/compiletest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ pub fn parse_config(args: Vec<String> ) -> Config {
}

fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
Path::new(m.opt_str(nm).unwrap())
match m.opt_str(nm) {
Some(s) => Path::new(s),
None => panic!("no option (=path) found for {}", nm),
}
}

let filter = if !matches.free.is_empty() {
Expand Down
6 changes: 4 additions & 2 deletions src/libregex/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ impl<'r, 't> Nfa<'r, 't> {
};
let mut matched = false;
let ninsts = self.prog.insts.len();
let mut clist = &mut Threads::new(self.which, ninsts, ncaps);
let mut nlist = &mut Threads::new(self.which, ninsts, ncaps);
let mut cthread = Threads::new(self.which, ninsts, ncaps);
let mut nthread = Threads::new(self.which, ninsts, ncaps);
let mut clist = &mut cthread;
let mut nlist = &mut nthread;

let mut groups: Vec<_> = repeat(None).take(ncaps * 2).collect();

Expand Down
12 changes: 12 additions & 0 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,18 @@ fn parse_scope(st: &mut PState) -> region::CodeExtent {
let node_id = parse_uint(st) as ast::NodeId;
region::CodeExtent::Misc(node_id)
}
'D' => {
let node_id = parse_uint(st) as ast::NodeId;
region::CodeExtent::DestructionScope(node_id)
}
'B' => {
let node_id = parse_uint(st) as ast::NodeId;
let first_stmt_index = parse_uint(st);
let block_remainder = region::BlockRemainder {
block: node_id, first_statement_index: first_stmt_index,
};
region::CodeExtent::Remainder(block_remainder)
}
_ => panic!("parse_scope: bad input")
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,10 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {

fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) {
match scope {
region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id)
region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id),
region::CodeExtent::Remainder(region::BlockRemainder {
block: b, first_statement_index: i }) => mywrite!(w, "B{}{}", b, i),
region::CodeExtent::DestructionScope(node_id) => mywrite!(w, "D{}", node_id),
}
}

Expand Down
28 changes: 25 additions & 3 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
}
}
SubSupConflict(var_origin, _, sub_r, _, sup_r) => {
debug!("processing SubSupConflict");
debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub_r, sup_r);
match free_regions_from_same_fn(self.tcx, sub_r, sup_r) {
Some(ref same_frs) => {
var_origins.push(var_origin);
Expand Down Expand Up @@ -721,6 +721,22 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
sup,
"");
}
infer::SafeDestructor(span) => {
self.tcx.sess.span_err(
span,
"unsafe use of destructor: destructor might be called \
while references are dead");
note_and_explain_region(
self.tcx,
"superregion: ",
sup,
"");
note_and_explain_region(
self.tcx,
"subregion: ",
sub,
"");
}
infer::BindingTypeIsNotValidAtDecl(span) => {
self.tcx.sess.span_err(
span,
Expand Down Expand Up @@ -818,6 +834,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
let scope_id = same_regions[0].scope_id;
let parent = self.tcx.map.get_parent(scope_id);
let parent_node = self.tcx.map.find(parent);
let taken = lifetimes_in_scope(self.tcx, scope_id);
let life_giver = LifeGiver::with_taken(&taken[]);
let node_inner = match parent_node {
Some(ref node) => match *node {
ast_map::NodeItem(ref item) => {
Expand Down Expand Up @@ -860,8 +878,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
};
let (fn_decl, generics, unsafety, ident, expl_self, span)
= node_inner.expect("expect item fn");
let taken = lifetimes_in_scope(self.tcx, scope_id);
let life_giver = LifeGiver::with_taken(&taken[]);
let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
generics, same_regions, &life_giver);
let (fn_decl, expl_self, generics) = rebuilder.rebuild();
Expand Down Expand Up @@ -1641,6 +1657,12 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
&format!("...so that the declared lifetime parameter bounds \
are satisfied")[]);
}
infer::SafeDestructor(span) => {
self.tcx.sess.span_note(
span,
"...so that references are valid when the destructor \
runs")
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ pub enum SubregionOrigin<'tcx> {

// An auto-borrow that does not enclose the expr where it occurs
AutoBorrow(Span),

// Region constraint arriving from destructor safety
SafeDestructor(Span),
}

/// Times when we replace late-bound regions with variables:
Expand Down Expand Up @@ -1217,6 +1220,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
CallReturn(a) => a,
AddrOf(a) => a,
AutoBorrow(a) => a,
SafeDestructor(a) => a,
}
}
}
Expand Down Expand Up @@ -1279,6 +1283,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> {
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),
}
}
}
Expand Down
61 changes: 50 additions & 11 deletions src/librustc/middle/infer/region_inference/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
use graphviz as dot;

use middle::ty;
use middle::region::CodeExtent;
use super::Constraint;
use middle::infer::SubregionOrigin;
use middle::infer::region_inference::RegionVarBindings;
use util::nodemap::{FnvHashMap, FnvHashSet};
use util::ppaux::Repr;

use std::borrow::Cow;
use std::collections::hash_map::Entry::Vacant;
use std::io::{self, File};
use std::os;
Expand Down Expand Up @@ -120,13 +122,18 @@ struct ConstraintGraph<'a, 'tcx: 'a> {
node_ids: FnvHashMap<Node, uint>,
}

#[derive(Clone, Hash, PartialEq, Eq, Show)]
#[derive(Clone, Hash, PartialEq, Eq, Show, Copy)]
enum Node {
RegionVid(ty::RegionVid),
Region(ty::Region),
}

type Edge = Constraint;
// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Show, Copy)]
enum Edge {
Constraint(Constraint),
EnclScope(CodeExtent, CodeExtent),
}

impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
fn new(tcx: &'a ty::ctxt<'tcx>,
Expand All @@ -146,6 +153,11 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
add_node(n1);
add_node(n2);
}

tcx.region_maps.each_encl_scope(|&mut: sub, sup| {
add_node(Node::Region(ty::ReScope(*sub)));
add_node(Node::Region(ty::ReScope(*sup)));
});
}

ConstraintGraph { tcx: tcx,
Expand All @@ -160,7 +172,17 @@ impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
dot::Id::new(self.graph_name.as_slice()).unwrap()
}
fn node_id(&self, n: &Node) -> dot::Id {
dot::Id::new(format!("node_{}", self.node_ids.get(n).unwrap())).unwrap()
let node_id = match self.node_ids.get(n) {
Some(node_id) => node_id,
None => panic!("no node_id found for node: {:?}", n),
};
let name = |&:| format!("node_{}", node_id);
match dot::Id::new(name()) {
Ok(id) => id,
Err(()) => {
panic!("failed to create graphviz node identified by {}", name());
}
}
}
fn node_label(&self, n: &Node) -> dot::LabelText {
match *n {
Expand All @@ -171,7 +193,12 @@ impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
}
}
fn edge_label(&self, e: &Edge) -> dot::LabelText {
dot::LabelText::label(format!("{}", self.map.get(e).unwrap().repr(self.tcx)))
match *e {
Edge::Constraint(ref c) =>
dot::LabelText::label(format!("{}", self.map.get(c).unwrap().repr(self.tcx))),
Edge::EnclScope(..) =>
dot::LabelText::label(format!("(enclosed)")),
}
}
}

Expand All @@ -186,28 +213,40 @@ fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
}
}

fn edge_to_nodes(e: &Edge) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
(Node::Region(ty::ReScope(sub)), Node::Region(ty::ReScope(sup)))
}
}
}

impl<'a, 'tcx> dot::GraphWalk<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
fn nodes(&self) -> dot::Nodes<Node> {
let mut set = FnvHashSet::new();
for constraint in self.map.keys() {
let (n1, n2) = constraint_to_nodes(constraint);
set.insert(n1);
set.insert(n2);
for node in self.node_ids.keys() {
set.insert(*node);
}
debug!("constraint graph has {} nodes", set.len());
set.into_iter().collect()
}
fn edges(&self) -> dot::Edges<Edge> {
debug!("constraint graph has {} edges", self.map.len());
self.map.keys().map(|e|*e).collect()
let mut v : Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
self.tcx.region_maps.each_encl_scope(|&mut: sub, sup| {
v.push(Edge::EnclScope(*sub, *sup))
});
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
fn source(&self, edge: &Edge) -> Node {
let (n1, _) = constraint_to_nodes(edge);
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
fn target(&self, edge: &Edge) -> Node {
let (_, n2) = constraint_to_nodes(edge);
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/infer/region_inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
for upper_bound in upper_bounds.iter() {
if !self.is_subregion_of(lower_bound.region,
upper_bound.region) {
debug!("pushing SubSupConflict sub: {:?} sup: {:?}",
lower_bound.region, upper_bound.region);
errors.push(SubSupConflict(
(*self.var_origins.borrow())[node_idx.index as uint].clone(),
lower_bound.origin.clone(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let fn_ret =
ty::liberate_late_bound_regions(
self.ir.tcx,
CodeExtent::from_node_id(body.id),
CodeExtent::DestructionScope(body.id),
&self.fn_ret(id));

match fn_ret {
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {

// Region of environment pointer
let env_region = ty::ReFree(ty::FreeRegion {
scope: region::CodeExtent::from_node_id(fn_body_id),
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
scope: region::CodeExtent::DestructionScope(fn_body_id),
bound_region: ty::BrEnv
});

Expand Down
Loading