CFG_OSTYPE=unknown-openbsd
;;
+ NetBSD)
+ CFG_OSTYPE=unknown-netbsd
+ ;;
+
Darwin)
CFG_OSTYPE=apple-darwin
;;
--- /dev/null
+# x86_64-unknown-netbsd configuration
+CC_x86_64-unknown-netbsd=$(CC)
+CXX_x86_64-unknown-netbsd=$(CXX)
+CPP_x86_64-unknown-netbsd=$(CPP)
+AR_x86_64-unknown-netbsd=$(AR)
+CFG_LIB_NAME_x86_64-unknown-netbsd=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-netbsd=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread -lrt
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
+CFG_INSTALL_NAME_x86_64-unknown-netbsd =
+CFG_EXE_SUFFIX_x86_64-unknown-netbsd :=
+CFG_WINDOWSY_x86_64-unknown-netbsd :=
+CFG_UNIXY_x86_64-unknown-netbsd := 1
+CFG_LDPATH_x86_64-unknown-netbsd :=
+CFG_RUN_x86_64-unknown-netbsd=$(2)
+CFG_RUN_TARG_x86_64-unknown-netbsd=$(call CFG_RUN_x86_64-unknown-netbsd,,$(2))
+CFG_GNU_TRIPLE_x86_64-unknown-netbsd := x86_64-unknown-netbsd
("ios", "ios"),
("linux", "linux"),
("mingw32", "windows"),
+ ("netbsd", "netbsd"),
("openbsd", "openbsd"),
("win32", "windows"),
("windows", "windows"),
as a configuration itself, like `unix` or `windows`.
* `target_os = "..."`. Operating system of the target, examples include
`"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
- `"bitrig"` or `"openbsd"`.
+ `"bitrig"` , `"openbsd"` or `"netbsd"`.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
download_unpack_base = os.path.join(download_dir_base, "unpack")
snapshot_files = {
+ "bitrig": ["bin/rustc"],
+ "dragonfly": ["bin/rustc"],
+ "freebsd": ["bin/rustc"],
"linux": ["bin/rustc"],
"macos": ["bin/rustc"],
- "winnt": ["bin/rustc.exe"],
- "freebsd": ["bin/rustc"],
- "dragonfly": ["bin/rustc"],
- "bitrig": ["bin/rustc"],
+ "netbsd": ["bin/rustc"],
"openbsd": ["bin/rustc"],
+ "winnt": ["bin/rustc.exe"],
}
winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"]
return "dragonfly"
if os_name == "bitrig":
return "bitrig"
+ if os_name == "netbsd":
+ return "netbsd"
if os_name == "openbsd":
return "openbsd"
return "linux"
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl<T: ?Sized> !marker::Send for Weak<T> {}
impl<T: ?Sized> !marker::Sync for Weak<T> {}
+impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
#[unstable(feature = "rc_weak",
reason = "Weak pointers may not belong in this module.")]
impl<T: ?Sized> Weak<T> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Traits for dynamic typing of any `'static` type (through runtime reflection)
-//!
//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
}
}
- #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+ #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os ="openbsd"))]
pub mod os {
pub mod common {
pub mod posix01 {
pub __unused7: *mut c_void,
}
- #[cfg(target_os = "openbsd")]
+ #[cfg(any(target_os = "netbsd", target_os="openbsd"))]
#[repr(C)]
#[derive(Copy, Clone)] pub struct glob_t {
pub gl_pathc: c_int,
}
}
- #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+ #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
pub mod os {
pub mod c95 {
use types::os::arch::c95::{c_int, c_uint};
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "nacl"))]
pub mod posix88 {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "nacl"))]
pub mod posix01 {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "ios",
}
- #[cfg(any(target_os = "windows",
- target_os = "linux",
- target_os = "android",
- target_os = "macos",
+ #[cfg(any(target_os = "android",
+ target_os = "bitrig",
+ target_os = "dragonfly",
target_os = "ios",
target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "bitrig",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "nacl",
+ target_os = "netbsd",
target_os = "openbsd",
- target_os = "nacl"))]
+ target_os = "windows"))]
pub mod posix08 {
pub mod unistd {
}
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub mod bsd44 {
use types::common::c95::{c_void};
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub mod extra {
}
NodeLifetime(&'ast Lifetime),
}
-/// Represents an entry and its parent Node ID
+/// Represents an entry and its parent NodeID.
/// The odd layout is to bring down the total size.
#[derive(Copy, Debug)]
enum MapEntry<'ast> {
}
}
- fn parent(self) -> Option<NodeId> {
+ fn parent_node(self) -> Option<NodeId> {
Some(match self {
EntryItem(id, _) => id,
EntryForeignItem(id, _) => id,
self.find_entry(id).and_then(|x| x.to_node())
}
- /// Retrieve the parent NodeId for `id`, or `id` itself if no
- /// parent is registered in this map.
+ /// Similar to get_parent, returns the parent node id or id if there is no
+ /// parent.
+ /// This function returns the immediate parent in the AST, whereas get_parent
+ /// returns the enclosing item. Note that this might not be the actual parent
+ /// node in the AST - some kinds of nodes are not in the map and these will
+ /// never appear as the parent_node. So you can always walk the parent_nodes
+ /// from a node to the root of the ast (unless you get the same id back here
+ /// that can happen if the id is not in the map itself or is just weird).
+ pub fn get_parent_node(&self, id: NodeId) -> NodeId {
+ self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
+ }
+
+ /// If there is some error when walking the parents (e.g., a node does not
+ /// have a parent in the map or a node can't be found), then we return the
+ /// last good node id we found. Note that reaching the crate root (id == 0),
+ /// is not an error, since items in the crate module have the crate root as
+ /// parent.
+ fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
+ where F: Fn(&Node<'ast>) -> bool
+ {
+ let mut id = start_id;
+ loop {
+ let parent_node = self.get_parent_node(id);
+ if parent_node == 0 {
+ return Ok(0);
+ }
+ if parent_node == id {
+ return Err(id);
+ }
+
+ let node = self.find_entry(parent_node);
+ if node.is_none() {
+ return Err(id);
+ }
+ let node = node.unwrap().to_node();
+ match node {
+ Some(ref node) => {
+ if found(node) {
+ return Ok(parent_node);
+ }
+ }
+ None => {
+ return Err(parent_node);
+ }
+ }
+ id = parent_node;
+ }
+ }
+
+ /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
+ /// parent item is in this map. The "parent item" is the closest parent node
+ /// in the AST which is recorded by the map and is an item, either an item
+ /// in a module, trait, or impl.
pub fn get_parent(&self, id: NodeId) -> NodeId {
- self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
+ match self.walk_parent_nodes(id, |node| match *node {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) => true,
+ _ => false,
+ }) {
+ Ok(id) => id,
+ Err(id) => id,
+ }
+ }
+
+ /// Returns the nearest enclosing scope. A scope is an item or block.
+ /// FIXME it is not clear to me that all items qualify as scopes - statics
+ /// and associated types probably shouldn't, for example. Behaviour in this
+ /// regard should be expected to be highly unstable.
+ pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
+ match self.walk_parent_nodes(id, |node| match *node {
+ NodeItem(_) |
+ NodeForeignItem(_) |
+ NodeTraitItem(_) |
+ NodeImplItem(_) |
+ NodeBlock(_) => true,
+ _ => false,
+ }) {
+ Ok(id) => Some(id),
+ Err(_) => None,
+ }
}
pub fn get_parent_did(&self, id: NodeId) -> DefId {
return None;
}
self.idx += 1;
- let (p, name) = match self.map.find_entry(idx) {
- Some(EntryItem(p, n)) => (p, n.name()),
- Some(EntryForeignItem(p, n))=> (p, n.name()),
- Some(EntryTraitItem(p, n)) => (p, n.name()),
- Some(EntryImplItem(p, n)) => (p, n.name()),
- Some(EntryVariant(p, n)) => (p, n.name()),
+ let name = match self.map.find_entry(idx) {
+ Some(EntryItem(_, n)) => n.name(),
+ Some(EntryForeignItem(_, n))=> n.name(),
+ Some(EntryTraitItem(_, n)) => n.name(),
+ Some(EntryImplItem(_, n)) => n.name(),
+ Some(EntryVariant(_, n)) => n.name(),
_ => continue,
};
- if self.matches_names(p, name) {
+ if self.matches_names(self.map.get_parent(idx), name) {
return Some(idx)
}
}
/// A Visitor that walks over an AST and collects Node's into an AST Map.
struct NodeCollector<'ast> {
map: Vec<MapEntry<'ast>>,
- /// The node in which we are currently mapping (an item or a method).
- parent: NodeId
+ parent_node: NodeId,
}
impl<'ast> NodeCollector<'ast> {
}
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
- let entry = MapEntry::from_node(self.parent, node);
+ let entry = MapEntry::from_node(self.parent_node, node);
self.insert_entry(id, entry);
}
impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
fn visit_item(&mut self, i: &'ast Item) {
self.insert(i.id, NodeItem(i));
- let parent = self.parent;
- self.parent = i.id;
+
+ let parent_node = self.parent_node;
+ self.parent_node = i.id;
+
match i.node {
ItemImpl(_, _, _, _, _, ref impl_items) => {
for ii in impl_items {
_ => {}
}
visit::walk_item(self, i);
- self.parent = parent;
+ self.parent_node = parent_node;
}
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
- let parent = self.parent;
- self.parent = ti.id;
+ let parent_node = self.parent_node;
+ self.parent_node = ti.id;
visit::walk_trait_item(self, ti);
- self.parent = parent;
+ self.parent_node = parent_node;
}
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
- let parent = self.parent;
- self.parent = ii.id;
+ let parent_node = self.parent_node;
+ self.parent_node = ii.id;
+
visit::walk_impl_item(self, ii);
- self.parent = parent;
+
+ self.parent_node = parent_node;
}
fn visit_pat(&mut self, pat: &'ast Pat) {
PatIdent(..) => NodeLocal(pat),
_ => NodePat(pat)
});
+
+ let parent_node = self.parent_node;
+ self.parent_node = pat.id;
visit::walk_pat(self, pat);
+ self.parent_node = parent_node;
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.insert(expr.id, NodeExpr(expr));
+ let parent_node = self.parent_node;
+ self.parent_node = expr.id;
visit::walk_expr(self, expr);
+ self.parent_node = parent_node;
}
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
- self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
+ let id = ast_util::stmt_id(stmt);
+ self.insert(id, NodeStmt(stmt));
+ let parent_node = self.parent_node;
+ self.parent_node = id;
visit::walk_stmt(self, stmt);
+ self.parent_node = parent_node;
}
fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
- b: &'ast Block, s: Span, _: NodeId) {
+ b: &'ast Block, s: Span, id: NodeId) {
+ let parent_node = self.parent_node;
+ self.parent_node = id;
self.visit_fn_decl(fd);
visit::walk_fn(self, fk, fd, b, s);
+ self.parent_node = parent_node;
}
fn visit_ty(&mut self, ty: &'ast Ty) {
+ let parent_node = self.parent_node;
+ self.parent_node = ty.id;
match ty.node {
TyBareFn(ref fd) => {
self.visit_fn_decl(&*fd.decl);
_ => {}
}
visit::walk_ty(self, ty);
+ self.parent_node = parent_node;
}
fn visit_block(&mut self, block: &'ast Block) {
self.insert(block.id, NodeBlock(block));
+ let parent_node = self.parent_node;
+ self.parent_node = block.id;
visit::walk_block(self, block);
+ self.parent_node = parent_node;
}
fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
let mut collector = NodeCollector {
map: vec![],
- parent: CRATE_NODE_ID
+ parent_node: CRATE_NODE_ID,
};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
visit::walk_crate(&mut collector, &forest.krate);
ii: ii
});
+ let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let mut collector = NodeCollector {
map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
- parent: fld.new_id(DUMMY_NODE_ID)
+ parent_node: ii_parent_id,
};
- let ii_parent_id = collector.parent;
collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
visit::walk_inlined_item(&mut collector, &ii_parent.ii);
E0267: r##"
This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Break and continue can be used as normal inside
-closures as long as they are also contained within a loop. To halt the execution
-of a closure you should instead use a return statement.
+closure but outside of any loop. Erroneous code example:
+
+```
+let w = || { break; }; // error: `break` inside of a closure
+```
+
+`break` and `continue` keywords can be used as normal inside closures as long as
+they are also contained within a loop. To halt the execution of a closure you
+should instead use a return statement. Example:
+
+```
+let w = || {
+ for _ in 0..10 {
+ break;
+ }
+};
+
+w();
+```
"##,
E0268: r##"
This error indicates the use of a loop keyword (`break` or `continue`) outside
of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken.
+be taken. Erroneous code example:
+
+```
+fn some_func() {
+ break; // error: `break` outside of loop
+}
+```
+
+Please verify that you are using `break` and `continue` only in loops. Example:
+
+```
+fn some_func() {
+ for _ in 0..10 {
+ break; // ok!
+ }
+}
+```
"##,
E0271: r##"
```
"##,
+E0277: r##"
+You tried to use a type which doesn't implement some trait in a place which
+expected that trait. Erroneous code example:
+
+```
+// here we declare the Foo trait with a bar method
+trait Foo {
+ fn bar(&self);
+}
+
+// we now declare a function which takes an object with Foo trait implemented
+// as parameter
+fn some_func<T: Foo>(foo: T) {
+ foo.bar();
+}
+
+fn main() {
+ // we now call the method with the i32 type, which doesn't implement
+ // the Foo trait
+ some_func(5i32); // error: the trait `Foo` is not implemented for the
+ // type `i32`
+}
+```
+
+In order to fix this error, verify that the type you're using does implement
+the trait. Example:
+
+```
+trait Foo {
+ fn bar(&self);
+}
+
+fn some_func<T: Foo>(foo: T) {
+ foo.bar(); // we can now use this method since i32 implements the
+ // Foo trait
+}
+
+// we implement the trait on the i32 type
+impl Foo for i32 {
+ fn bar(&self) {}
+}
+
+fn main() {
+ some_func(5i32); // ok!
+}
+```
+"##,
+
E0282: r##"
This error indicates that type inference did not result in one unique possible
type, and extra information is required. In most cases this can be provided
E0274, // rustc_on_unimplemented must have a value
E0275, // overflow evaluating requirement
E0276, // requirement appears on impl method but not on corresponding trait method
- E0277, // trait is not implemented for type
E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
E0280, // requirement is not satisfied
#![feature(vec_push_all)]
#![feature(wrapping)]
#![feature(cell_extras)]
+#![feature(page_size)]
#![cfg_attr(test, feature(test))]
#![allow(trivial_casts)]
use metadata::tyencode;
use middle::cast;
use middle::check_const::ConstQualif;
-use middle::mem_categorization::Typer;
use middle::privacy::{AllPublic, LastMod};
use middle::subst;
use middle::subst::VecPerParamSpace;
c::tag_table_tcache => {
let type_scheme = val_dsr.read_type_scheme(dcx);
let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
- dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme);
+ dcx.tcx.register_item_type(lid, type_scheme);
}
c::tag_table_param_defs => {
let bounds = val_dsr.read_type_param_def(dcx);
}
fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
- F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'tcx,
- ty::ParameterEnvironment<'a, 'tcx>>) -> R,
+ F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
{
let param_env = match item_id {
Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
None => self.tcx.empty_parameter_environment()
};
- f(&mut euv::ExprUseVisitor::new(self, ¶m_env))
+
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), false);
+
+ f(&mut euv::ExprUseVisitor::new(self, &infcx))
}
fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
fn check_static_type(&self, e: &ast::Expr) {
let ty = self.tcx.node_id_to_type(e.id);
- let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
- let mut fulfill_cx = traits::FulfillmentContext::new(false);
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
- match fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+ match fulfill_cx.select_all_or_error(&infcx) {
Ok(()) => { },
Err(ref errors) => {
traits::report_fulfillment_errors(&infcx, errors);
use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
use middle::expr_use_visitor::WriteAndRead;
use middle::expr_use_visitor as euv;
-use middle::mem_categorization::{cmt, Typer};
+use middle::infer;
+use middle::mem_categorization::{cmt};
use middle::pat_util::*;
use middle::ty::*;
use middle::ty;
match p.node {
ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
let pat_ty = tcx.node_id_to_type(p.id);
- if cx.param_env.type_moves_by_default(pat_ty, pat.span) {
+ //FIXME: (@jroesch) this code should be floated up as well
+ let infcx = infer::new_infer_ctxt(cx.tcx,
+ &cx.tcx.tables,
+ Some(cx.param_env.clone()),
+ false);
+ if infcx.type_moves_by_default(pat_ty, pat.span) {
check_move(p, sub.as_ref().map(|p| &**p));
}
}
let mut checker = MutationChecker {
cx: cx,
};
- let mut visitor = ExprUseVisitor::new(&mut checker,
- &checker.cx.param_env);
+
+ let infcx = infer::new_infer_ctxt(cx.tcx,
+ &cx.tcx.tables,
+ Some(checker.cx.param_env.clone()),
+ false);
+
+ let mut visitor = ExprUseVisitor::new(&mut checker, &infcx);
visitor.walk_expr(guard);
}
// is the public starting point.
use middle::expr_use_visitor as euv;
+use middle::infer;
use middle::mem_categorization as mc;
use middle::ty::ParameterEnvironment;
use middle::ty;
s: Span,
fn_id: ast::NodeId) {
{
+ // FIXME (@jroesch) change this to be an inference context
let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+ let infcx = infer::new_infer_ctxt(self.tcx,
+ &self.tcx.tables,
+ Some(param_env.clone()),
+ false);
let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env };
- let mut euv = euv::ExprUseVisitor::new(&mut delegate, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
euv.walk_fn(fd, b);
}
visit::walk_fn(self, fk, fd, b, s)
substs: trait_substs });
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
- let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+ let mut selcx = traits::SelectionContext::new(&infcx);
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
trait_ref.to_poly_trait_predicate());
let selection = match selcx.select(&obligation) {
use self::OverloadedCallType::*;
use middle::{def, region, pat_util};
+use middle::infer;
use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::ty::{self};
use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
// supplies types from the tree. After type checking is complete, you
// can just use the tcx as the typer.
-pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> {
- typer: &'t TYPER,
- mc: mc::MemCategorizationContext<'t,TYPER>,
+pub struct ExprUseVisitor<'d,'t,'a: 't, 'tcx:'a> {
+ typer: &'t infer::InferCtxt<'a, 'tcx>,
+ mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
delegate: &'d mut (Delegate<'tcx>+'d),
}
ByRef,
}
-impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
pub fn new(delegate: &'d mut Delegate<'tcx>,
- typer: &'t TYPER)
- -> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+ typer: &'t infer::InferCtxt<'a, 'tcx>)
+ -> ExprUseVisitor<'d,'t,'a, 'tcx> {
ExprUseVisitor {
typer: typer,
mc: mc::MemCategorizationContext::new(typer),
}
fn tcx(&self) -> &'t ty::ctxt<'tcx> {
- self.typer.tcx()
+ self.typer.tcx
}
fn delegate_consume(&mut self,
match local.init {
None => {
let delegate = &mut self.delegate;
- pat_util::pat_bindings(&self.typer.tcx().def_map, &*local.pat,
+ pat_util::pat_bindings(&self.typer.tcx.def_map, &*local.pat,
|_, id, span, _| {
delegate.decl_without_init(id, span);
})
let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
if pat_util::pat_is_binding(def_map, pat) {
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
cmt_pat,
// the leaves of the pattern tree structure.
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
let def_map = def_map.borrow();
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
match pat.node {
ast::PatEnum(_, _) | ast::PatQPath(..) |
}
}
-fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
+fn copy_or_move<'a, 'tcx>(typer: &infer::InferCtxt<'a, 'tcx>,
cmt: &mc::cmt<'tcx>,
move_reason: MoveReason)
-> ConsumeMode
struct Implicator<'a, 'tcx: 'a> {
infcx: &'a InferCtxt<'a,'tcx>,
- closure_typer: &'a (ty::ClosureTyper<'tcx>+'a),
body_id: ast::NodeId,
stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
span: Span,
/// appear in a context with lifetime `outer_region`
pub fn implications<'a,'tcx>(
infcx: &'a InferCtxt<'a,'tcx>,
- closure_typer: &ty::ClosureTyper<'tcx>,
body_id: ast::NodeId,
ty: Ty<'tcx>,
outer_region: ty::Region,
let mut stack = Vec::new();
stack.push((outer_region, None));
- let mut wf = Implicator { closure_typer: closure_typer,
- infcx: infcx,
+ let mut wf = Implicator { infcx: infcx,
body_id: body_id,
span: span,
stack: stack,
{
let value =
traits::fully_normalize(self.infcx,
- self.closure_typer,
traits::ObligationCause::misc(self.span, self.body_id),
value);
match value {
use middle::subst;
use middle::subst::Substs;
use middle::subst::Subst;
-use middle::traits;
+use middle::traits::{self, FulfillmentContext, Normalized,
+ SelectionContext, ObligationCause};
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
use middle::ty::{self, Ty, HasTypeFlags};
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
use std::fmt;
use syntax::ast;
use syntax::codemap;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
use util::nodemap::{FnvHashMap, NodeMap};
use self::combine::CombineFields;
pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>,
+ pub fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+
// This is a temporary field used for toggling on normalization in the inference context,
// as we move towards the approach described here:
// https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
}
}
+/// errors_will_be_reported is required to proxy to the fulfillment context
+/// FIXME -- a better option would be to hold back on modifying
+/// the global cache until we know that all dependent obligations
+/// are also satisfied. In that case, we could actually remove
+/// this boolean flag, and we'd also avoid the problem of squelching
+/// duplicate errors that occur across fns.
pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
tables: &'a RefCell<ty::Tables<'tcx>>,
- param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
+ param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
+ errors_will_be_reported: bool)
-> InferCtxt<'a, 'tcx> {
InferCtxt {
tcx: tcx,
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(tcx),
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
+ fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
normalize: false,
err_count_on_creation: tcx.sess.err_count()
}
}
+pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
+ tables: &'a RefCell<ty::Tables<'tcx>>)
+ -> InferCtxt<'a, 'tcx> {
+ let mut infcx = new_infer_ctxt(tcx, tables, None, false);
+ infcx.normalize = true;
+ infcx
+}
+
/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
/// returns ty::err.
pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
region_vars_snapshot: RegionSnapshot,
}
-impl<'a, 'tcx> mc::Typer<'tcx> for InferCtxt<'a, 'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
- let ty = self.node_ty(id);
- self.resolve_type_vars_or_error(&ty)
- }
+pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
+ where T : TypeFoldable<'tcx> + HasTypeFlags
+{
+ debug!("normalize_associated_type(t={:?})", value);
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
- let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
- self.resolve_type_vars_or_error(&ty)
- }
+ let value = erase_regions(tcx, value);
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- let ty = self.resolve_type_vars_if_possible(&ty);
- !traits::type_known_to_meet_builtin_bound(self, self, ty, ty::BoundCopy, span)
+ if !value.has_projection_types() {
+ return value;
}
- fn node_method_ty(&self, method_call: ty::MethodCall)
- -> Option<Ty<'tcx>> {
- self.tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.ty)
- .map(|ty| self.resolve_type_vars_if_possible(&ty))
- }
+ let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let cause = traits::ObligationCause::dummy();
+ let traits::Normalized { value: result, obligations } =
+ traits::normalize(&mut selcx, cause, &value);
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.origin.clone())
- }
+ debug!("normalize_associated_type: result={:?} obligations={:?}",
+ result,
+ obligations);
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
- -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
- Ref::map(self.tables.borrow(), project_adjustments)
+ for obligation in obligations {
+ fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
- }
+ let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
- self.parameter_environment.temporary_scope(rvalue_id)
- }
+ result
+}
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
+ infcx: &InferCtxt<'a,'tcx>,
+ fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+ result: &T)
+ -> T
+ where T : TypeFoldable<'tcx>
+{
+ match drain_fulfillment_cx(infcx, fulfill_cx, result) {
+ Ok(v) => v,
+ Err(errors) => {
+ infcx.tcx.sess.span_bug(
+ span,
+ &format!("Encountered errors `{:?}` fulfilling during trans",
+ errors));
+ }
}
}
-impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- &self.parameter_environment
+/// Finishes processes any obligations that remain in the fulfillment
+/// context, and then "freshens" and returns `result`. This is
+/// primarily used during normalization and other cases where
+/// processing the obligations in `fulfill_cx` may cause type
+/// inference variables that appear in `result` to be unified, and
+/// hence we need to process those obligations to get the complete
+/// picture of the type.
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+ fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+ result: &T)
+ -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
+ where T : TypeFoldable<'tcx>
+{
+ debug!("drain_fulfillment_cx(result={:?})",
+ result);
+
+ // In principle, we only need to do this so long as `result`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ match fulfill_cx.select_all_or_error(infcx) {
+ Ok(()) => { }
+ Err(errors) => {
+ return Err(errors);
+ }
}
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- self.tables.borrow().closure_kinds.get(&def_id).cloned()
- }
+ // Use freshen to simultaneously replace all type variables with
+ // their bindings and replace all regions with 'static. This is
+ // sort of overkill because we do not expect there to be any
+ // unbound type variables, hence no `TyFresh` types should ever be
+ // inserted.
+ Ok(result.fold_with(&mut infcx.freshener()))
+}
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
+/// Returns an equivalent value with all free regions removed (note
+/// that late-bound regions remain, because they are important for
+/// subtyping, but they are anonymized and normalized as well). This
+/// is a stronger, caching version of `ty_fold::erase_regions`.
+pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
+ where T : TypeFoldable<'tcx>
+{
+ let value1 = value.fold_with(&mut RegionEraser(cx));
+ debug!("erase_regions({:?}) = {:?}",
+ value, value1);
+ return value1;
- let closure_ty = self.tables
- .borrow()
- .closure_tys
- .get(&def_id)
- .unwrap()
- .subst(self.tcx, substs);
+ struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
- if self.normalize {
- // NOTE: this flag is currently *always* set to false, we are slowly folding
- // normalization into this trait and will come back to remove this in the near
- // future.
-
- // code from NormalizingClosureTyper:
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- // normalize_associated_type(self.param_env.tcx, &closure_ty)
- panic!("see issue 26597: fufillment context refactor must occur")
- } else {
- closure_ty
+ impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
+ fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
+ None => {}
+ Some(u) => return u
+ }
+
+ let t_norm = ty_fold::super_fold_ty(self, ty);
+ self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
+ return t_norm;
}
- }
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- let result = ty::ctxt::closure_upvars(self, def_id, substs);
+ fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+ where T : TypeFoldable<'tcx>
+ {
+ let u = self.tcx().anonymize_late_bound_regions(t);
+ ty_fold::super_fold_binder(self, &u)
+ }
- if self.normalize {
- // NOTE: this flag is currently *always* set to false, we are slowly folding
- // normalization into this trait and will come back to remove this in the near
- // future.
-
- // code from NormalizingClosureTyper:
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- // monomorphize::normalize_associated_type(self.param_env.tcx, &result)
- panic!("see issue 26597: fufillment context refactor must occur")
- } else {
- result
+ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+ // because late-bound regions affect subtyping, we can't
+ // erase the bound/free distinction, but we can replace
+ // all free regions with 'static.
+ //
+ // Note that we *CAN* replace early-bound regions -- the
+ // type system never "sees" those, they get substituted
+ // away. In trans, they will always be erased to 'static
+ // whenever a substitution occurs.
+ match r {
+ ty::ReLateBound(..) => r,
+ _ => ty::ReStatic
+ }
+ }
+
+ fn fold_substs(&mut self,
+ substs: &subst::Substs<'tcx>)
+ -> subst::Substs<'tcx> {
+ subst::Substs { regions: subst::ErasedRegions,
+ types: substs.types.fold_with(self) }
}
}
}
.map(|method| resolve_ty(method.ty)))
}
- pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+ pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
match self.tables.borrow().node_types.get(&id) {
Some(&t) => t,
// FIXME
self.equate(true, trace).relate(a, b)
}).map(|_| ())
}
+
+ pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
+ let ty = self.node_type(id);
+ self.resolve_type_vars_or_error(&ty)
+ }
+
+ pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+ let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
+ self.resolve_type_vars_or_error(&ty)
+ }
+
+ pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+ let ty = self.resolve_type_vars_if_possible(&ty);
+ !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
+ // FIXME(@jroesch): should be able to use:
+ // ty.moves_by_default(&self.parameter_environment, span)
+ }
+
+ pub fn node_method_ty(&self, method_call: ty::MethodCall)
+ -> Option<Ty<'tcx>> {
+ self.tables
+ .borrow()
+ .method_map
+ .get(&method_call)
+ .map(|method| method.ty)
+ .map(|ty| self.resolve_type_vars_if_possible(&ty))
+ }
+
+ pub fn node_method_origin(&self, method_call: ty::MethodCall)
+ -> Option<ty::MethodOrigin<'tcx>>
+ {
+ self.tables
+ .borrow()
+ .method_map
+ .get(&method_call)
+ .map(|method| method.origin.clone())
+ }
+
+ pub fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
+ fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
+ -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
+ &tables.adjustments
+ }
+
+ Ref::map(self.tables.borrow(), project_adjustments)
+ }
+
+ pub fn is_method_call(&self, id: ast::NodeId) -> bool {
+ self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
+ }
+
+ pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
+ self.tcx.region_maps.temporary_scope(rvalue_id)
+ }
+
+ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
+ self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+ }
+
+ pub fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
+ &self.parameter_environment
+ }
+
+ pub fn closure_kind(&self,
+ def_id: ast::DefId)
+ -> Option<ty::ClosureKind>
+ {
+ self.tables.borrow().closure_kinds.get(&def_id).cloned()
+ }
+
+ pub fn closure_type(&self,
+ def_id: ast::DefId,
+ substs: &subst::Substs<'tcx>)
+ -> ty::ClosureTy<'tcx>
+ {
+
+ let closure_ty = self.tables
+ .borrow()
+ .closure_tys
+ .get(&def_id)
+ .unwrap()
+ .subst(self.tcx, substs);
+
+ if self.normalize {
+ normalize_associated_type(&self.tcx, &closure_ty)
+ } else {
+ closure_ty
+ }
+ }
+
+ pub fn closure_upvars(&self,
+ def_id: ast::DefId,
+ substs: &Substs<'tcx>)
+ -> Option<Vec<ty::ClosureUpvar<'tcx>>>
+ {
+ let result = ty::ctxt::closure_upvars(self, def_id, substs);
+
+ if self.normalize {
+ normalize_associated_type(&self.tcx, &result)
+ } else {
+ result
+ }
+ }
}
impl<'tcx> TypeTrace<'tcx> {
use self::VarKind::*;
use middle::def::*;
-use middle::mem_categorization::Typer;
use middle::pat_util;
use middle::region;
use middle::ty;
-use middle::ty::ClosureTyper;
use lint;
use util::nodemap::NodeMap;
use self::Aliasability::*;
use ast_map;
+use middle::infer;
use middle::check_const;
use middle::def;
use middle::region;
use middle::ty::{self, Ty};
-use util::nodemap::NodeMap;
use syntax::ast::{MutImmutable, MutMutable};
use syntax::ast;
use syntax::codemap::Span;
-use std::cell::Ref;
use std::fmt;
use std::rc::Rc;
fn span(&self) -> Span { self.span }
}
-pub struct MemCategorizationContext<'t,TYPER:'t> {
- typer: &'t TYPER
-}
-
-impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
-impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> {
- fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self }
+#[derive(Copy, Clone)]
+pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
+ pub typer: &'t infer::InferCtxt<'a, 'tcx>,
}
pub type McResult<T> = Result<T, ()>;
-/// The `Typer` trait provides the interface for the mem-categorization
-/// module to the results of the type check. It can be used to query
-/// the type assigned to an expression node, to inquire after adjustments,
-/// and so on.
-///
-/// This interface is needed because mem-categorization is used from
-/// two places: `regionck` and `borrowck`. `regionck` executes before
-/// type inference is complete, and hence derives types and so on from
-/// intermediate tables. This also implies that type errors can occur,
-/// and hence `node_ty()` and friends return a `Result` type -- any
-/// error will propagate back up through the mem-categorization
-/// routines.
-///
-/// In the borrow checker, in contrast, type checking is complete and we
-/// know that no errors have occurred, so we simply consult the tcx and we
-/// can be sure that only `Ok` results will occur.
-pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool;
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>;
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>>;
- fn is_method_call(&self, id: ast::NodeId) -> bool;
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture>;
-}
-
impl MutabilityCategory {
pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
let ret = match m {
}
}
-impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
- pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
+impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
+ pub fn new(typer: &'t infer::InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> {
MemCategorizationContext { typer: typer }
}
- fn tcx(&self) -> &'t ty::ctxt<'tcx> {
- self.typer.tcx()
+ fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+ self.typer.tcx
}
fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
}
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()>
- where F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+ where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
{
self.cat_pattern_(cmt, pat, &mut op)
}
// FIXME(#19596) This is a workaround, but there should be a better way to do this
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
-> McResult<()>
- where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+ where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
{
// Here, `cmt` is the categorization for the value being
// matched and pat is the pattern it is being matched against.
impl1_def_id,
impl2_def_id);
- let param_env = &infcx.tcx.empty_parameter_environment();
- let selcx = &mut SelectionContext::intercrate(infcx, param_env);
+ let selcx = &mut SelectionContext::intercrate(infcx);
infcx.probe(|_| {
overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
})
// particular node-id).
region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
- errors_will_be_reported: bool,
+ pub errors_will_be_reported: bool,
}
#[derive(Clone)]
/// `projection_ty` again.
pub fn normalize_projection_type<'a>(&mut self,
infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>)
-> Ty<'tcx>
// FIXME(#20304) -- cache
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
for obligation in normalized.obligations {
}
pub fn select_all_or_error<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- try!(self.select_where_possible(infcx, typer));
+ try!(self.select_where_possible(infcx));
// Anything left is ambiguous.
let errors: Vec<FulfillmentError> =
/// gaining type information. It'd be equally valid to use `select_where_possible` but it
/// results in `O(n^2)` performance (#18208).
pub fn select_new_obligations<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
self.select(&mut selcx, true)
}
pub fn select_where_possible<'a>(&mut self,
- infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>)
+ infcx: &InferCtxt<'a,'tcx>)
-> Result<(),Vec<FulfillmentError<'tcx>>>
{
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
self.select(&mut selcx, false)
}
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
- typer: &ty::ClosureTyper<'tcx>,
ty: Ty<'tcx>,
bound: ty::BuiltinBound,
span: Span)
// Note: we only assume something is `Copy` if we can
// *definitively* show that it implements `Copy`. Otherwise,
// assume it is move; linear is always ok.
- match fulfill_cx.select_all_or_error(infcx, typer) {
+ match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => {
debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
ty,
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
- let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause,
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), false);
+ let predicates = match fully_normalize(&infcx, cause,
&infcx.parameter_environment.caller_bounds) {
Ok(predicates) => predicates,
Err(errors) => {
}
pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
- closure_typer: &ty::ClosureTyper<'tcx>,
cause: ObligationCause<'tcx>,
value: &T)
-> Result<T, Vec<FulfillmentError<'tcx>>>
{
debug!("normalize_param_env(value={:?})", value);
- let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
+ let mut selcx = &mut SelectionContext::new(infcx);
+ // FIXME (@jroesch) ISSUE 26721
+ // I'm not sure if this is a bug or not, needs further investigation.
+ // It appears that by reusing the fulfillment_cx here we incur more
+ // obligations and later trip an asssertion on regionck.rs line 337.
+ //
+ // The two possibilities I see is:
+ // - normalization is not actually fully happening and we
+ // have a bug else where
+ // - we are adding a duplicate bound into the list causing
+ // its size to change.
+ //
+ // I think we should probably land this refactor and then come
+ // back to this is a follow-up patch.
let mut fulfill_cx = FulfillmentContext::new(false);
+
let Normalized { value: normalized_value, obligations } =
project::normalize(selcx, cause, value);
debug!("normalize_param_env: normalized_value={:?} obligations={:?}",
for obligation in obligations {
fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
}
- try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
+
+ try!(fulfill_cx.select_all_or_error(infcx));
let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
debug!("normalize_param_env: resolved_value={:?}", resolved_value);
Ok(resolved_value)
pub struct SelectionContext<'cx, 'tcx:'cx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx (ty::ClosureTyper<'tcx>+'cx),
-
/// Freshener used specifically for skolemizing entries on the
/// obligation stack. This ensures that all entries on the stack
/// at one time will have the same set of skolemized entries,
}
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx ty::ClosureTyper<'tcx>)
+ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>)
-> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
- closure_typer: closure_typer,
freshener: infcx.freshener(),
intercrate: false,
}
}
- pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
- closure_typer: &'cx ty::ClosureTyper<'tcx>)
+ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>)
-> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
- closure_typer: closure_typer,
freshener: infcx.freshener(),
intercrate: true,
}
}
pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'cx, 'tcx> {
- self.closure_typer.param_env()
+ self.infcx.param_env()
}
- pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) {
- self.closure_typer
+ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+ self.infcx
}
///////////////////////////////////////////////////////////////////////////
kind,
obligation);
- match self.closure_typer.closure_kind(closure_def_id) {
+ match self.infcx.closure_kind(closure_def_id) {
Some(closure_kind) => {
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
if closure_kind.extends(kind) {
return ok_if(Vec::new());
}
- match self.closure_typer.closure_upvars(def_id, substs) {
+ match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()),
None => {
debug!("assemble_builtin_bound_candidates: no upvar types available yet");
ty::TyClosure(def_id, substs) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
- match self.closure_typer.closure_upvars(def_id, substs) {
+ match self.infcx.closure_upvars(def_id, substs) {
Some(upvars) => {
Some(upvars.iter().map(|c| c.ty).collect())
}
substs: &Substs<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
- let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
+ let closure_type = self.infcx.closure_type(closure_def_id, substs);
let ty::Binder((trait_ref, _)) =
util::closure_trait_ref_and_return_type(self.tcx(),
obligation.predicate.def_id(),
use middle::fast_reject;
use middle::free_region::FreeRegionMap;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::region;
use middle::resolve_lifetime;
use middle::infer;
-> Result<(),CopyImplementationError> {
let tcx = self.tcx;
+ // FIXME: (@jroesch) float this code up
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false);
+
let did = match self_type.sty {
ty::TyStruct(struct_did, substs) => {
let fields = tcx.struct_fields(struct_did, substs);
for field in &fields {
- if self.type_moves_by_default(field.mt.ty, span) {
+ if infcx.type_moves_by_default(field.mt.ty, span) {
return Err(FieldDoesNotImplementCopy(field.name))
}
}
for variant_arg_type in &variant.args {
let substd_arg_type =
variant_arg_type.subst(tcx, substs);
- if self.type_moves_by_default(substd_arg_type, span) {
+ if infcx.type_moves_by_default(substd_arg_type, span) {
return Err(VariantDoesNotImplementCopy(variant.name))
}
}
}
}
-pub trait ClosureTyper<'tcx> {
- fn tcx(&self) -> &ctxt<'tcx> {
- self.param_env().tcx
- }
-
- fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>;
-
- /// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck,
- /// returns `None` if the kind of this closure has not yet been
- /// inferred.
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>;
-
- /// Returns the argument/return types of this closure.
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>;
-
- /// Returns the set of all upvars and their transformed
- /// types. During typeck, maybe return `None` if the upvar types
- /// have not yet been inferred.
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ClosureUpvar<'tcx>>>;
-}
-
impl<'tcx> CommonTypes<'tcx> {
fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
- interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
+ interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
-> CommonTypes<'tcx>
{
- let mut mk = |sty| ctxt::intern_ty(arena, interner, sty);
+ let mk = |sty| ctxt::intern_ty(arena, interner, sty);
CommonTypes {
bool: mk(TyBool),
char: mk(TyChar),
f: F) -> (Session, R)
where F: FnOnce(&ctxt<'tcx>) -> R
{
- let mut interner = FnvHashMap();
- let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+ let interner = RefCell::new(FnvHashMap());
+ let common_types = CommonTypes::new(&arenas.type_, &interner);
tls::enter(ctxt {
arenas: arenas,
- interner: RefCell::new(interner),
+ interner: interner,
substs_interner: RefCell::new(FnvHashMap()),
bare_fn_interner: RefCell::new(FnvHashMap()),
region_interner: RefCell::new(FnvHashMap()),
}
fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
- interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+ interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
st: TypeVariants<'tcx>)
-> Ty<'tcx> {
- match interner.get(&st) {
- Some(ty) => return *ty,
- _ => ()
- }
+ let ty: Ty /* don't be &mut TyS */ = {
+ let mut interner = interner.borrow_mut();
+ match interner.get(&st) {
+ Some(ty) => return *ty,
+ _ => ()
+ }
+
+ let flags = FlagComputation::for_sty(&st);
- let flags = FlagComputation::for_sty(&st);
+ let ty = match () {
+ () => type_arena.alloc(TyS { sty: st,
+ flags: Cell::new(flags.flags),
+ region_depth: flags.depth, }),
+ };
- let ty = match () {
- () => type_arena.alloc(TyS { sty: st,
- flags: Cell::new(flags.flags),
- region_depth: flags.depth, }),
+ interner.insert(InternedTy { ty: ty }, ty);
+ ty
};
debug!("Interned type: {:?} Pointer: {:?}",
ty, ty as *const TyS);
-
- interner.insert(InternedTy { ty: ty }, ty);
-
ty
}
// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for Ty above).
pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
- let mut interner = self.interner.borrow_mut();
- ctxt::intern_ty(&self.arenas.type_, &mut *interner, st)
+ ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
}
pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
TyClosure(did, substs) => {
// FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
let param_env = cx.empty_parameter_environment();
- let upvars = param_env.closure_upvars(did, substs).unwrap();
+ let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
+ let upvars = infcx.closure_upvars(did, substs).unwrap();
TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
}
span: Span)
-> bool
{
- let tcx = param_env.tcx();
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()));
+ let tcx = param_env.tcx;
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false);
- let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env,
+ let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
self, bound, span);
debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
is_impld
}
- fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+ // FIXME (@jroesch): I made this public to use it, not sure if should be private
+ pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
span: Span) -> bool {
if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
.clone()
}
+ // Register a given item type
+ pub fn register_item_type(&self, did: ast::DefId, ty: TypeScheme<'tcx>) {
+ self.tcache.borrow_mut().insert(did, ty);
+ }
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
if id.krate == ast::LOCAL_CRATE {
self.node_id_to_type(id.node)
} else {
- let mut tcache = self.tcache.borrow_mut();
- tcache.entry(id).or_insert_with(|| csearch::get_field_type(self, struct_id, id)).ty
+ memoized(&self.tcache, id,
+ |id| csearch::get_field_type(self, struct_id, id)).ty
}
}
}
// Returns a list of `ClosureUpvar`s for each upvar.
- pub fn closure_upvars(typer: &Typer<'tcx>,
+ pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
closure_id: ast::DefId,
substs: &Substs<'tcx>)
-> Option<Vec<ClosureUpvar<'tcx>>>
// This may change if abstract return types of some sort are
// implemented.
assert!(closure_id.krate == ast::LOCAL_CRATE);
- let tcx = typer.tcx();
+ let tcx = typer.tcx;
match tcx.freevars.borrow().get(&closure_id.node) {
None => Some(vec![]),
Some(ref freevars) => {
}
}
-impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
- Ok(self.tcx.node_id_to_type(id))
- }
-
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
- Ok(self.tcx.expr_ty_adjusted(expr))
- }
-
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
- self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.ty)
- }
-
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.origin.clone())
- }
-
- fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
-
- Ref::map(self.tcx.tables.borrow(), projection)
- }
-
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tcx.is_method_call(id)
- }
-
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
- self.tcx.region_maps.temporary_scope(rvalue_id)
- }
-
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- self.tcx.upvar_capture(upvar_id)
- }
-
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- ty.moves_by_default(self, span)
- }
-}
-
-impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- self
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- Some(self.tcx.closure_kind(def_id))
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- self.tcx.closure_type(def_id, substs)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ClosureUpvar<'tcx>>> {
- ctxt::closure_upvars(self, def_id, substs)
- }
-}
-
-
/// The category of explicit self.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum ExplicitSelfCategory {
const NANOS_PER_SEC: f64 = 1_000_000_000.0;
let secs = dur.secs() as f64;
let secs = secs + dur.extra_nanos() as f64 / NANOS_PER_SEC;
- println!("{}time: {:.3} \t{}", repeat(" ").take(old).collect::<String>(),
- secs, what);
+
+ let mem_string = match get_resident() {
+ Some(n) => {
+ let mb = n as f64 / 1_000_000.0;
+ format!("; rss: {}MB", mb.round() as usize)
+ }
+ None => "".to_owned(),
+ };
+ println!("{}time: {:.3}{}\t{}", repeat(" ").take(old).collect::<String>(),
+ secs, mem_string, what);
DEPTH.with(|slot| slot.set(old));
rv
}
+// Memory reporting
+fn get_resident() -> Option<usize> {
+ if cfg!(unix) {
+ get_proc_self_statm_field(1)
+ } else {
+ None
+ }
+}
+
+// Like std::macros::try!, but for Option<>.
+macro_rules! option_try(
+ ($e:expr) => (match $e { Some(e) => e, None => return None })
+);
+
+fn get_proc_self_statm_field(field: usize) -> Option<usize> {
+ use std::fs::File;
+ use std::io::Read;
+
+ assert!(cfg!(unix));
+
+ let mut f = option_try!(File::open("/proc/self/statm").ok());
+ let mut contents = String::new();
+ option_try!(f.read_to_string(&mut contents).ok());
+ let s = option_try!(contents.split_whitespace().nth(field));
+ let npages = option_try!(s.parse::<usize>().ok());
+ Some(npages * ::std::env::page_size())
+}
+
pub fn indent<R, F>(op: F) -> R where
R: Debug,
F: FnOnce() -> R,
TyError => write!(f, "[type error]"),
TyParam(ref param_ty) => write!(f, "{}", param_ty),
TyEnum(did, substs) | TyStruct(did, substs) => {
- parameterized(f, substs, did, &[],
- |tcx| tcx.lookup_item_type(did).generics)
+ ty::tls::with(|tcx| {
+ if did.krate == ast::LOCAL_CRATE &&
+ !tcx.tcache.borrow().contains_key(&did) {
+ write!(f, "{}<..>", tcx.item_path_str(did))
+ } else {
+ parameterized(f, substs, did, &[],
+ |tcx| tcx.lookup_item_type(did).generics)
+ }
+ })
}
TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data),
-a:0:64-n32".to_string()
}
- abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+ abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
"e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-a:0:64-n32".to_string()
}
- abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+ abi::OsBitrig | abi::OsDragonfly | abi::OsFreebsd | abi::OsNetbsd | abi::OsOpenbsd => {
"E-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-a:0:64-n32".to_string()
}
- abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+ abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
"e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
mod freebsd_base;
mod linux_base;
mod openbsd_base;
+mod netbsd_base;
mod windows_base;
mod windows_msvc_base;
x86_64_unknown_bitrig,
x86_64_unknown_openbsd,
+ x86_64_unknown_netbsd,
x86_64_apple_darwin,
i686_apple_darwin,
--- /dev/null
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::TargetOptions;
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+ TargetOptions {
+ linker: "cc".to_string(),
+ dynamic_linking: true,
+ executables: true,
+ morestack: false,
+ linker_is_gnu: true,
+ has_rpath: true,
+ pre_link_args: vec!(
+ // GNU-style linkers will use this to omit linking to libraries
+ // which don't actually fulfill any relocations, but only for
+ // libraries which follow this flag. Thus, use it before
+ // specifying libraries to link to.
+ "-Wl,--as-needed".to_string(),
+ ),
+ position_independent_executables: true,
+ .. Default::default()
+ }
+}
--- /dev/null
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+ let mut base = super::netbsd_base::opts();
+ base.pre_link_args.push("-m64".to_string());
+
+ Target {
+ data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+ f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
+ s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
+ llvm_target: "x86_64-unknown-netbsd".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ arch: "x86_64".to_string(),
+ target_os: "netbsd".to_string(),
+ target_env: "".to_string(),
+ options: base,
+ }
+}
"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
}
- abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+ abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
}
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}
- abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+ abi::OsBitrig | abi::OsDragonfly | abi::OsFreebsd | abi::OsNetbsd | abi::OsOpenbsd => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
use borrowck::*;
use borrowck::InteriorKind::{InteriorElement, InteriorField};
use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::region;
use rustc::middle::ty;
debug!("check_loans(body id={})", body.id);
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
+ let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
let mut clcx = CheckLoanCtxt {
bccx: bccx,
dfcx_loans: dfcx_loans,
move_data: move_data,
all_loans: all_loans,
- param_env: ¶m_env,
+ param_env: &infcx.parameter_environment
};
{
- let mut euv = euv::ExprUseVisitor::new(&mut clcx, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut clcx, &infcx);
euv.walk_fn(decl, body);
}
}
use borrowck::*;
use borrowck::move_data::MoveData;
use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::region;
use rustc::middle::ty;
};
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
-
+ let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
{
- let mut euv = euv::ExprUseVisitor::new(&mut glcx, ¶m_env);
+ let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx);
euv.walk_fn(decl, body);
}
impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
fn visit_expr(&mut self, ex: &Expr) {
if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
- let param_env = self.bccx.tcx.empty_parameter_environment();
- let mc = mc::MemCategorizationContext::new(¶m_env);
+ let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None, false);
+ let mc = mc::MemCategorizationContext::new(&infcx);
let base_cmt = mc.cat_expr(&**base).unwrap();
let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
// Check that we don't allow borrows of unsafe static items.
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::mem_categorization as mc;
-use rustc::middle::mem_categorization::Typer;
use rustc::middle::region;
use rustc::middle::ty::{self, Ty};
-> (&'static str, &'static str) {
match ty.sty {
_ => {
- if param_env.type_moves_by_default(ty, span) {
+ if ty.moves_by_default(param_env, span) {
("non-copyable",
"perhaps you meant to use `clone()`?")
} else {
lang_items,
stability::Index::new(krate),
|tcx| {
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
body(Env { infcx: &infcx });
let free_regions = FreeRegionMap::new();
infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
use metadata::{csearch, decoder};
use middle::def::*;
-use middle::mem_categorization::Typer;
use middle::subst::Substs;
use middle::ty::{self, Ty};
use middle::{def, pat_util, stability};
_ => return,
};
let parameter_environment = cx.tcx.empty_parameter_environment();
- if !parameter_environment.type_moves_by_default(ty, item.span) {
+ // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
+ // method
+ if !ty.moves_by_default(¶meter_environment, item.span) {
return;
}
if parameter_environment.can_type_implement_copy(ty, item.span).is_ok() {
#![feature(unicode)]
#![feature(unicode)]
#![feature(vec_push_all)]
-#![feature(cell_extras)]
#![allow(trivial_casts)]
qualname: qualname,
declaration: None,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
})
}
ast::ItemStatic(ref typ, mt, ref expr) => {
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
value: value,
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
value: self.span_utils.snippet(expr.span),
type_value: ty_to_string(&typ),
})
name: get_ident(item.ident).to_string(),
qualname: qualname,
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
filename: filename,
})
},
value: val,
span: sub_span.unwrap(),
qualname: enum_name,
- scope: self.tcx.map.get_parent(item.id),
+ scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
})
},
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
let mut type_data = None;
let sub_span;
- let parent = self.tcx.map.get_parent(item.id);
+ let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0);
match typ.node {
// Common case impl for a struct or something basic.
return Some(Data::VariableRefData(VariableRefData {
name: get_ident(ident.node).to_string(),
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
ref_id: f.id,
}));
}
let sub_span = self.span_utils.span_for_last_ident(path.span);
Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(),
- scope: self.tcx.map.get_parent(expr.id),
+ scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
ref_id: def_id,
}))
}
use middle::const_eval;
use middle::def::{self, DefMap};
use middle::expr_use_visitor as euv;
+use middle::infer;
use middle::lang_items::StrEqFnLangItem;
use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
use middle::pat_util::*;
use trans::adt;
use trans::base::*;
use trans::tvec;
use trans::type_of;
use middle::ty::{self, Ty};
-use session::config::{NoDebugInfo, FullDebugInfo};
+use session::config::NoDebugInfo;
use util::common::indenter;
use util::nodemap::FnvHashMap;
use util::ppaux;
reassigned: false
};
{
- let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx);
+ let infcx = infer::new_infer_ctxt(bcx.tcx(), &bcx.tcx().tables, None, false);
+ let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx);
visitor.walk_expr(body);
}
rc.reassigned
let trmode;
match bm {
ast::BindByValue(_)
- if !param_env.type_moves_by_default(variable_ty, span) || reassigned =>
+ if !variable_ty.moves_by_default(¶m_env, span) || reassigned =>
{
llmatch = alloca_no_lifetime(bcx,
llvariable_ty.ptr_to(),
}
}
-/// Generates code for argument patterns like `fn foo(<pat>: T)`.
-/// Creates entries in the `lllocals` map for each of the bindings
-/// in `pat`.
-///
-/// # Arguments
-///
-/// - `pat` is the argument pattern
-/// - `llval` is a pointer to the argument value (in other words,
-/// if the argument type is `T`, then `llval` is a `T*`). In some
-/// cases, this code may zero out the memory `llval` points at.
-pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
- pat: &ast::Pat,
- arg: Datum<'tcx, Rvalue>,
- arg_scope: cleanup::ScopeId)
- -> Block<'blk, 'tcx> {
- let _icx = push_ctxt("match::store_arg");
-
- match simple_identifier(&*pat) {
- Some(ident) => {
- // Generate nicer LLVM for the common case of fn a pattern
- // like `x: T`
- let arg_ty = node_id_type(bcx, pat.id);
- if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
- && bcx.sess().opts.debuginfo != FullDebugInfo {
- // Don't copy an indirect argument to an alloca, the caller
- // already put it in a temporary alloca and gave it up, unless
- // we emit extra-debug-info, which requires local allocas :(.
- let arg_val = arg.add_clean(bcx.fcx, arg_scope);
- bcx.fcx.lllocals.borrow_mut()
- .insert(pat.id, Datum::new(arg_val, arg_ty, Lvalue));
- bcx
- } else {
- mk_binding_alloca(
- bcx, pat.id, ident.name, arg_scope, arg,
- |arg, bcx, llval, _| arg.store_to(bcx, llval))
- }
- }
-
- None => {
- // General path. Copy out the values that are used in the
- // pattern.
- let arg = unpack_datum!(
- bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
- bind_irrefutable_pat(bcx, pat, arg.val, arg_scope)
- }
- }
-}
-
fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
p_id: ast::NodeId,
name: ast::Name,
/// - bcx: starting basic block context
/// - pat: the irrefutable pattern being matched.
/// - val: the value being matched -- must be an lvalue (by ref, with cleanup)
-fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
pat: &ast::Pat,
val: ValueRef,
cleanup_scope: cleanup::ScopeId)
use llvm::{ValueRef, True, IntEQ, IntNE};
use back::abi::FAT_PTR_ADDR;
use middle::subst;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::infer;
+use middle::ty::{self, Ty};
use middle::ty::Disr;
use syntax::ast;
use syntax::attr;
Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
}
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
}
// Perhaps one of the upvars of this struct is non-zero
// Let's recurse and find out!
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(tcx);
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
for (j, &ty) in upvar_types.iter().enumerate() {
use libc::{c_uint, c_ulonglong};
use llvm::{self, ValueRef, AttrHelper};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
use session::config::NoDebugInfo;
use syntax::abi;
use syntax::ast;
let (fn_sig, abi, env_ty) = match fn_type.sty {
ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
ty::TyClosure(closure_did, substs) => {
- let typer = common::NormalizingClosureTyper::new(ccx.tcx());
- function_type = typer.closure_type(closure_did, substs);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
(&function_type.sig, abi::RustCall, Some(self_type))
}
use metadata::{csearch, encoder, loader};
use middle::astencode;
use middle::cfg;
+use middle::infer;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
+use middle::pat_util::simple_identifier;
use middle::subst::Substs;
-use middle::ty::{self, Ty, ClosureTyper, HasTypeFlags};
+use middle::ty::{self, Ty, HasTypeFlags};
use rustc::ast_map;
-use session::config::{self, NoDebugInfo};
+use session::config::{self, NoDebugInfo, FullDebugInfo};
use session::Session;
use trans::_match;
use trans::adt;
}
ty::TyClosure(def_id, substs) => {
let repr = adt::represent_type(cx.ccx(), t);
- let typer = common::NormalizingClosureTyper::new(cx.tcx());
- let upvars = typer.closure_upvars(def_id, substs).unwrap();
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let upvars = infcx.closure_upvars(def_id, substs).unwrap();
for (i, upvar) in upvars.iter().enumerate() {
let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
cx = f(cx, llupvar, upvar.ty);
Alloca(cx, ty, name)
}
+pub fn set_value_name(val: ValueRef, name: &str) {
+ unsafe {
+ let name = CString::new(name).unwrap();
+ llvm::LLVMSetValueName(val, name.as_ptr());
+ }
+}
+
// Creates the alloca slot which holds the pointer to the slot for the final return value
pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
output_type: Ty<'tcx>) -> ValueRef {
}
}
-// work around bizarre resolve errors
-pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
-
-// create_datums_for_fn_args: creates rvalue datums for each of the
-// incoming function arguments. These will later be stored into
-// appropriate lvalue datums.
-pub fn create_datums_for_fn_args<'a, 'tcx>(bcx: Block<'a, 'tcx>,
- arg_tys: &[Ty<'tcx>])
- -> Vec<RvalueDatum<'tcx>> {
+// create_datums_for_fn_args: creates lvalue datums for each of the
+// incoming function arguments.
+pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
+ args: &[ast::Arg],
+ arg_tys: &[Ty<'tcx>],
+ has_tupled_arg: bool,
+ arg_scope: cleanup::CustomScopeIndex)
+ -> Block<'a, 'tcx> {
let _icx = push_ctxt("create_datums_for_fn_args");
let fcx = bcx.fcx;
+ let arg_scope_id = cleanup::CustomScope(arg_scope);
// Return an array wrapping the ValueRefs that we get from `get_param` for
// each argument into datums.
- let mut i = fcx.arg_offset() as c_uint;
- arg_tys.iter().map(|&arg_ty| {
- if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
- let llty = type_of::type_of(bcx.ccx(), arg_ty);
- let data = get_param(fcx.llfn, i);
- let extra = get_param(fcx.llfn, i + 1);
- let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
- i += 2;
- datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
- } else {
- let llarg = get_param(fcx.llfn, i);
- i += 1;
- datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
- }
- }).collect()
-}
-
-/// Creates rvalue datums for each of the incoming function arguments and
-/// tuples the arguments. These will later be stored into appropriate lvalue
-/// datums.
-///
-/// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
-fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
- mut bcx: Block<'blk, 'tcx>,
- arg_scope: cleanup::CustomScopeIndex,
- arg_tys: &[Ty<'tcx>])
- -> Vec<RvalueDatum<'tcx>> {
- let mut result = Vec::new();
- let mut idx = bcx.fcx.arg_offset() as c_uint;
+ //
+ // For certain mode/type combinations, the raw llarg values are passed
+ // by value. However, within the fn body itself, we want to always
+ // have all locals and arguments be by-ref so that we can cancel the
+ // cleanup and for better interaction with LLVM's debug info. So, if
+ // the argument would be passed by value, we store it into an alloca.
+ // This alloca should be optimized away by LLVM's mem-to-reg pass in
+ // the event it's not truly needed.
+ let mut idx = fcx.arg_offset() as c_uint;
for (i, &arg_ty) in arg_tys.iter().enumerate() {
- if i < arg_tys.len() - 1 {
- // Regular argument.
- result.push(if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
- let llty = type_of::type_of(bcx.ccx(), arg_ty);
- let data = get_param(bcx.fcx.llfn, idx);
- let extra = get_param(bcx.fcx.llfn, idx + 1);
+ let arg_datum = if !has_tupled_arg || i < arg_tys.len() - 1 {
+ if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
+ && bcx.sess().opts.debuginfo != FullDebugInfo {
+ // Don't copy an indirect argument to an alloca, the caller
+ // already put it in a temporary alloca and gave it up, unless
+ // we emit extra-debug-info, which requires local allocas :(.
+ let llarg = get_param(fcx.llfn, idx);
+ idx += 1;
+ bcx.fcx.schedule_lifetime_end(arg_scope_id, llarg);
+ bcx.fcx.schedule_drop_mem(arg_scope_id, llarg, arg_ty);
+
+ datum::Datum::new(llarg, arg_ty, datum::Lvalue)
+ } else if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+ let data = get_param(fcx.llfn, idx);
+ let extra = get_param(fcx.llfn, idx + 1);
idx += 2;
- let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
- datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
+ unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
+ arg_scope_id, (data, extra),
+ |(data, extra), bcx, dst| {
+ Store(bcx, data, expr::get_dataptr(bcx, dst));
+ Store(bcx, extra, expr::get_len(bcx, dst));
+ bcx
+ }))
} else {
- let val = get_param(bcx.fcx.llfn, idx);
+ let llarg = get_param(fcx.llfn, idx);
idx += 1;
- datum::Datum::new(val, arg_ty, arg_kind(bcx.fcx, arg_ty))
- });
-
- continue
- }
-
- // This is the last argument. Tuple it.
- match arg_ty.sty {
- ty::TyTuple(ref tupled_arg_tys) => {
- let tuple_args_scope_id = cleanup::CustomScope(arg_scope);
- let tuple =
+ let tmp = datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty));
+ unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
+ arg_scope_id, tmp,
+ |tmp, bcx, dst| tmp.store_to(bcx, dst)))
+ }
+ } else {
+ // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
+ match arg_ty.sty {
+ ty::TyTuple(ref tupled_arg_tys) => {
unpack_datum!(bcx,
datum::lvalue_scratch_datum(bcx,
arg_ty,
"tupled_args",
- tuple_args_scope_id,
+ arg_scope_id,
(),
|(),
mut bcx,
};
}
bcx
- }));
- let tuple = unpack_datum!(bcx,
- tuple.to_expr_datum()
- .to_rvalue_datum(bcx,
- "argtuple"));
- result.push(tuple);
- }
- _ => {
- bcx.tcx().sess.bug("last argument of a function with \
- `rust-call` ABI isn't a tuple?!")
+ }))
+ }
+ _ => {
+ bcx.tcx().sess.bug("last argument of a function with \
+ `rust-call` ABI isn't a tuple?!")
+ }
}
};
- }
-
- result
-}
-
-fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
- arg_scope: cleanup::CustomScopeIndex,
- args: &[ast::Arg],
- arg_datums: Vec<RvalueDatum<'tcx>>)
- -> Block<'blk, 'tcx> {
- debug!("copy_args_to_allocas");
-
- let _icx = push_ctxt("copy_args_to_allocas");
- let mut bcx = bcx;
-
- let arg_scope_id = cleanup::CustomScope(arg_scope);
-
- for (i, arg_datum) in arg_datums.into_iter().enumerate() {
- // For certain mode/type combinations, the raw llarg values are passed
- // by value. However, within the fn body itself, we want to always
- // have all locals and arguments be by-ref so that we can cancel the
- // cleanup and for better interaction with LLVM's debug info. So, if
- // the argument would be passed by value, we store it into an alloca.
- // This alloca should be optimized away by LLVM's mem-to-reg pass in
- // the event it's not truly needed.
-
- bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
+ let pat = &*args[i].pat;
+ bcx = if let Some(ident) = simple_identifier(&*pat) {
+ // Generate nicer LLVM for the common case of fn a pattern
+ // like `x: T`
+ set_value_name(arg_datum.val, &bcx.name(ident.name));
+ bcx.fcx.lllocals.borrow_mut().insert(pat.id, arg_datum);
+ bcx
+ } else {
+ // General path. Copy out the values that are used in the
+ // pattern.
+ _match::bind_irrefutable_pat(bcx, pat, arg_datum.val, arg_scope_id)
+ };
debuginfo::create_argument_metadata(bcx, &args[i]);
}
decl.inputs.iter()
.map(|arg| node_id_type(bcx, arg.id))
.collect::<Vec<_>>();
- let monomorphized_arg_types = match closure_env {
- closure::ClosureEnv::NotClosure => {
- monomorphized_arg_types
- }
-
- // Tuple up closure argument types for the "rust-call" ABI.
- closure::ClosureEnv::Closure(_) => {
- vec![ccx.tcx().mk_tup(monomorphized_arg_types)]
- }
- };
for monomorphized_arg_type in &monomorphized_arg_types {
debug!("trans_closure: monomorphized_arg_type: {:?}",
monomorphized_arg_type);
debug!("trans_closure: function lltype: {}",
bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn));
- let arg_datums = match closure_env {
- closure::ClosureEnv::NotClosure if abi == RustCall => {
- create_datums_for_fn_args_under_call_abi(bcx, arg_scope, &monomorphized_arg_types[..])
- }
- _ => {
- let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi);
- create_datums_for_fn_args(bcx, &arg_tys)
- }
+ let has_tupled_arg = match closure_env {
+ closure::ClosureEnv::NotClosure => abi == RustCall,
+ _ => false
};
- bcx = copy_args_to_allocas(bcx, arg_scope, &decl.inputs, arg_datums);
+ bcx = create_datums_for_fn_args(bcx, &decl.inputs, &monomorphized_arg_types,
+ has_tupled_arg, arg_scope);
bcx = closure_env.load(bcx, cleanup::CustomScope(arg_scope));
let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());
- let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
-
if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
let repr = adt::represent_type(ccx, result_ty.unwrap());
- for (i, arg_datum) in arg_datums.into_iter().enumerate() {
+ let mut llarg_idx = fcx.arg_offset() as c_uint;
+ for (i, arg_ty) in arg_tys.into_iter().enumerate() {
let lldestptr = adt::trans_field_ptr(bcx,
&*repr,
dest,
disr,
i);
- arg_datum.store_to(bcx, lldestptr);
+ if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+ Store(bcx, get_param(fcx.llfn, llarg_idx), expr::get_dataptr(bcx, lldestptr));
+ Store(bcx, get_param(fcx.llfn, llarg_idx + 1), expr::get_len(bcx, lldestptr));
+ llarg_idx += 2;
+ } else {
+ let arg = get_param(fcx.llfn, llarg_idx);
+ llarg_idx += 1;
+
+ if arg_is_indirect(ccx, arg_ty) {
+ memcpy_ty(bcx, lldestptr, arg, arg_ty);
+ } else {
+ store_ty(bcx, arg, lldestptr, arg_ty);
+ }
+ }
}
adt::trans_set_discr(bcx, &*repr, dest, disr);
}
use arena::TypedArena;
use back::link::{self, mangle_internal_name_by_path_and_seq};
use llvm::{ValueRef, get_params};
-use middle::mem_categorization::Typer;
+use middle::infer;
use trans::adt;
use trans::attributes;
use trans::base::*;
use trans::expr;
use trans::monomorphize::{self, MonoId};
use trans::type_of::*;
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
use middle::subst::Substs;
use session::config::FullDebugInfo;
// takes the same set of type arguments as the enclosing fn, and
// this function (`trans_closure`) is invoked at the point
// of the closure expression.
- let typer = NormalizingClosureTyper::new(tcx);
- let function_type = typer.closure_type(closure_id, param_substs);
+
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ let function_type = infcx.closure_type(closure_id, param_substs);
let freevars: Vec<ty::Freevar> =
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
ccx.tn().val_to_string(llreffn));
let tcx = ccx.tcx();
- let typer = NormalizingClosureTyper::new(tcx);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
// Find a version of the closure type. Substitute static for the
// region since it doesn't really matter.
let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
// Make a version with the type of by-ref closure.
- let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
+ let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
abi: abi,
use middle::def;
use middle::infer;
use middle::lang_items::LangItem;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
-use middle::region;
use middle::subst::{self, Substs};
use trans::base;
use trans::build;
use arena::TypedArena;
use libc::{c_uint, c_char};
use std::ffi::CString;
-use std::cell::{Cell, RefCell, Ref};
+use std::cell::{Cell, RefCell};
use std::result::Result as StdResult;
use std::vec::Vec;
use syntax::ast;
// normalized version of the type, and therefore will definitely
// know whether the type implements Copy (and thus needs no
// cleanup/drop/zeroing) ...
- let implements_copy = !param_env.type_moves_by_default(ty, DUMMY_SP);
+ let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP);
if implements_copy { return false; }
}
}
-impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
- fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
- Ok(node_id_type(self, id))
- }
-
- fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
- Ok(expr_ty_adjusted(self, expr))
- }
-
- fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
- self.tcx()
- .tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| monomorphize_type(self, method.ty))
- }
-
- fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
- {
- self.tcx()
- .tables
- .borrow()
- .method_map
- .get(&method_call)
- .map(|method| method.origin.clone())
- }
-
- fn adjustments<'a>(&'a self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
- // FIXME (@jroesch): this is becuase we currently have a HR inference problem
- // in the snapshot that causes this code not to work.
- fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) ->
- &'a NodeMap<ty::AutoAdjustment<'tcx>> {
- &tables.adjustments
- }
-
- Ref::map(self.tcx().tables.borrow(), project_adjustments)
- }
-
- fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tcx().tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
- }
-
- fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
- self.tcx().region_maps.temporary_scope(rvalue_id)
- }
-
- fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
- Some(self.tcx().tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
- }
-
- fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
- self.fcx.param_env.type_moves_by_default(ty, span)
- }
-}
-
-impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
- fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> {
- &self.fcx.param_env
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_kind(def_id)
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_type(def_id, substs)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- let typer = NormalizingClosureTyper::new(self.tcx());
- typer.closure_upvars(def_id, substs)
- }
-}
-
pub struct Result<'blk, 'tcx: 'blk> {
pub bcx: Block<'blk, 'tcx>,
pub val: ValueRef
trait_ref, trait_ref.def_id());
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+
let obligation =
traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
trait_ref.to_poly_trait_predicate());
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters.
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
let vtable = selection.map(|predicate| {
fulfill_cx.register_predicate_obligation(&infcx, predicate);
});
predicates);
let tcx = ccx.tcx();
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
- let mut fulfill_cx = traits::FulfillmentContext::new(false);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: predicates, obligations } =
traits::normalize(&mut selcx, cause.clone(), &predicates);
drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
}
-// NOTE: here is another use of parameter environment without an InferCtxt,
-// this is obviously related to the typer interface requiring a parameter env.
-// We should pay attention to this when refactoring
-// - @jroesch
-pub struct NormalizingClosureTyper<'a,'tcx:'a> {
- param_env: ty::ParameterEnvironment<'a, 'tcx>
-}
-
-impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> {
- pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> {
- // Parameter environment is used to give details about type parameters,
- // but since we are in trans, everything is fully monomorphized.
- NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() }
- }
-}
-
-impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> {
- fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- &self.param_env
- }
-
- fn closure_kind(&self,
- def_id: ast::DefId)
- -> Option<ty::ClosureKind>
- {
- self.param_env.closure_kind(def_id)
- }
-
- fn closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let closure_ty = self.param_env.tcx.closure_type(def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
- }
-
- fn closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::ClosureUpvar<'tcx>>>
- {
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let result = self.param_env.closure_upvars(def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &result)
- }
-}
-
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
infcx: &infer::InferCtxt<'a,'tcx>,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
// In principle, we only need to do this so long as `result`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
- let typer = NormalizingClosureTyper::new(infcx.tcx);
- match fulfill_cx.select_all_or_error(infcx, &typer) {
+ match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => { }
Err(errors) => {
return Err(errors);
use trans::expr;
use trans::tvec;
use trans::type_of;
-use middle::mem_categorization::Typer;
use middle::ty::Ty;
use std::fmt;
* affine values (since they must never be duplicated).
*/
- assert!(!bcx.tcx().empty_parameter_environment()
- .type_moves_by_default(self.ty, DUMMY_SP));
+ assert!(!self.ty
+ .moves_by_default(&bcx.tcx().empty_parameter_environment(), DUMMY_SP));
self.shallow_copy_raw(bcx, dst)
}
use trans::common::{C_bytes, CrateContext};
use trans::declare;
use trans::type_::Type;
-use middle::ty::ClosureTyper;
use session::config::NoDebugInfo;
use std::ffi::CString;
use metadata::csearch;
use middle::pat_util;
use middle::subst::{self, Substs};
+use middle::infer;
use rustc::ast_map;
use trans::{type_of, adt, machine, monomorphize};
-use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
+use trans::common::{self, CrateContext, FunctionContext, Block};
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
use trans::type_::Type;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use session::config::{self, FullDebugInfo};
use util::nodemap::FnvHashMap;
use util::common::path2cstr;
}
},
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let closure_ty = typer.closure_type(def_id, substs);
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let closure_ty = infcx.closure_type(def_id, substs);
self.get_unique_type_id_of_closure_type(cx,
closure_ty,
&mut unique_type_id);
subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
}
ty::TyClosure(def_id, substs) => {
- let typer = NormalizingClosureTyper::new(cx.tcx());
- let sig = typer.closure_type(def_id, substs).sig;
+ let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+ let sig = infcx.closure_type(def_id, substs).sig;
subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
}
ty::TyStruct(def_id, substs) => {
use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
use trans;
use trans::monomorphize;
-use middle::ty::{Ty, ClosureTyper};
+use middle::ty::Ty;
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
use llvm::debuginfo::DIScope;
use rustc::ast_map;
use trans::common::CrateContext;
-use middle::ty::ClosureTyper;
use std::ffi::CString;
use std::ptr;
use trans::common::CrateContext;
use middle::subst::{self, Substs};
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use syntax::ast;
use syntax::parse::token;
output.push('>');
}
}
-
//! * Use define_* family of methods when you might be defining the ValueRef.
//! * When in doubt, define.
use llvm::{self, ValueRef};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
use syntax::abi;
use trans::attributes;
use trans::base;
-use trans::common;
use trans::context::CrateContext;
use trans::monomorphize;
use trans::type_::Type;
(&f.sig, f.abi, None)
}
ty::TyClosure(closure_did, substs) => {
- let typer = common::NormalizingClosureTyper::new(ccx.tcx());
- function_type = typer.closure_type(closure_did, substs);
+ let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+ function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
debug!("declare_rust_fn function_type={:?} self_type={:?}",
use middle::check_const;
use middle::def;
use middle::lang_items::CoerceUnsizedTraitLangItem;
-use middle::mem_categorization::Typer;
use middle::subst::{Substs, VecPerParamSpace};
use middle::traits;
use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
}
-pub fn make_fat_ptr(bcx: Block, ty: Type, data: ValueRef, extra: ValueRef) -> ValueRef {
- InsertValue(bcx, InsertValue(bcx, C_undef(ty), data, 0), extra, 1)
-}
pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));
use middle::subst::VecPerParamSpace;
use middle::subst;
use middle::traits;
-use middle::ty::ClosureTyper;
use rustc::ast_map;
use trans::base::*;
use trans::build::*;
}
// FIXME(#20304) -- cache
- // NOTE: @jroesch
- // Here is of an example where we do not use a param_env but use a typer instead.
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let typer = NormalizingClosureTyper::new(tcx);
- let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+ let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+ let mut selcx = traits::SelectionContext::new(&infcx);
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: result, obligations } =
traits::normalize(&mut selcx, cause, &value);
result,
obligations);
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+
for obligation in obligations {
fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
}
}
-/// Yields the types of the "real" arguments for this function. For most
-/// functions, these are simply the types of the arguments. For functions with
-/// the `RustCall` ABI, however, this untuples the arguments of the function.
-pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- inputs: &[Ty<'tcx>],
- abi: abi::Abi)
- -> Vec<Ty<'tcx>> {
- if abi != abi::RustCall {
- return inputs.iter().cloned().collect()
- }
-
+/// Yields the types of the "real" arguments for a function using the `RustCall`
+/// ABI by untupling the arguments of the function.
+pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+ inputs: &[Ty<'tcx>])
+ -> Vec<Ty<'tcx>> {
if inputs.is_empty() {
return Vec::new()
}
match inputs[inputs.len() - 1].sty {
ty::TyTuple(ref tupled_arguments) => {
- debug!("untuple_arguments_if_necessary(): untupling arguments");
+ debug!("untuple_arguments(): untupling arguments");
for &tupled_argument in tupled_arguments {
result.push(tupled_argument);
}
let mut atys: Vec<Type> = Vec::new();
// First, munge the inputs, if this has the `rust-call` ABI.
- let inputs = untuple_arguments_if_necessary(cx, &sig.inputs, abi);
+ let inputs = &if abi == abi::RustCall {
+ untuple_arguments(cx, &sig.inputs)
+ } else {
+ sig.inputs
+ };
// Arg 0: Output pointer.
// (if the output type is non-immediate)
}
// ... then explicit args.
- for input in &inputs {
+ for input in inputs {
let arg_ty = type_of_explicit_arg(cx, input);
if type_is_fat_ptr(cx.tcx(), input) {
use middle::infer::InferCtxt;
use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
SelectionContext, ObligationCause};
-use middle::ty::{self, HasTypeFlags};
+use middle::ty::HasTypeFlags;
use middle::ty_fold::TypeFoldable;
use syntax::ast;
use syntax::codemap::Span;
+//FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
- typer: &(ty::ClosureTyper<'tcx>+'a),
fulfillment_cx: &mut FulfillmentContext<'tcx>,
span: Span,
body_id: ast::NodeId,
where T : TypeFoldable<'tcx> + HasTypeFlags
{
debug!("normalize_associated_types_in(value={:?})", value);
- let mut selcx = SelectionContext::new(infcx, typer);
+ let mut selcx = SelectionContext::new(infcx);
let cause = ObligationCause::new(span, body_id, MiscObligation);
let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
debug!("normalize_associated_types_in: result={:?} predicates={:?}",
use CrateCtxt;
use middle::infer;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
expected_vid: ty::TyVid)
-> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
{
- let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+ let fulfillment_cx = fcx.inh.infcx.fulfillment_cx.borrow();
// Here `expected_ty` is known to be a type inference variable.
let expected_sig =
};
let source = source.adjust_for_autoref(self.tcx(), reborrow);
- let mut selcx = traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = traits::SelectionContext::new(self.fcx.infcx());
// Use a FIFO queue for this custom fulfillment procedure.
let mut queue = VecDeque::new();
debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
impl_trait_ref);
- let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+ let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
let trait_to_impl_substs = &impl_trait_ref.substs;
debug!("compare_impl_method: trait_bounds={:?}",
infcx.parameter_environment.caller_bounds);
- let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+ let mut selcx = traits::SelectionContext::new(&infcx);
for predicate in impl_pred.fns {
let traits::Normalized { value: predicate, .. } =
impl_sig.subst(tcx, impl_to_skol_substs);
let impl_sig =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_m_span,
impl_m_body_id,
trait_sig.subst(tcx, &trait_to_skol_substs);
let trait_sig =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_m_span,
impl_m_body_id,
// Check that all obligations are satisfied by the implementation's
// version.
- match fulfillment_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+ match fulfillment_cx.select_all_or_error(&infcx) {
Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
Ok(_) => {}
}
debug!("compare_const_impl(impl_trait_ref={:?})",
impl_trait_ref);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
- let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+ let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
// The below is for the most part highly similar to the procedure
// for methods above. It is simpler in many respects, especially
// There is no "body" here, so just pass dummy id.
let impl_ty =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_c_span,
0,
&impl_ty);
+
debug!("compare_const_impl: impl_ty={:?}",
impl_ty);
let trait_ty =
assoc::normalize_associated_types_in(&infcx,
- &impl_param_env,
&mut fulfillment_cx,
impl_c_span,
0,
&trait_ty);
+
debug!("compare_const_impl: trait_ty={:?}",
trait_ty);
ty: named_type } =
tcx.lookup_item_type(self_type_did);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
infcx.commit_if_ok(|snapshot| {
let (named_type_to_skolem, skol_map) =
use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
use check::UnresolvedTypeAction;
-use middle::mem_categorization::Typer;
use middle::subst::{self};
use middle::traits;
use middle::ty::{self, Ty};
poly_trait_ref.to_predicate());
// Now we want to know if this can be matched
- let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+ let mut selcx = traits::SelectionContext::new(fcx.infcx());
if !selcx.evaluate_obligation(&obligation) {
debug!("--> Cannot match obligation");
return None; // Cannot be matched, no such method resolution is possible.
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
- let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, cause, &xform_self_ty);
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
// as it will pollute the fcx's fulfillment context after this probe
// is over.
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
- let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+ let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, cause, &xform_self_ty);
match probe.kind {
InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
- let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx.infcx());
+ let selcx = &mut traits::SelectionContext::new(self.infcx());
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
// Check whether the impl imposes obligations we have to worry about.
let obligation = Obligation::misc(span,
fcx.body_id,
poly_trait_ref.to_predicate());
- let mut selcx = SelectionContext::new(infcx, fcx.infcx());
+ let mut selcx = SelectionContext::new(infcx);
if selcx.evaluate_obligation(&obligation) {
span_stored_function();
// one is never copied into the tcx: it is only used by regionck.
fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
- // Tracks trait obligations incurred during this function body.
- fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
-
// When we process a call like `c()` where `c` is a closure type,
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
// `FnOnce` closure. In that case, we defer full resolution of the
-> Inherited<'a, 'tcx> {
Inherited {
- infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
+ infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
locals: RefCell::new(NodeMap()),
tables: tables,
fn_sig_map: RefCell::new(NodeMap()),
- fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
}
}
fn normalize_associated_types_in<T>(&self,
- typer: &ty::ClosureTyper<'tcx>,
span: Span,
body_id: ast::NodeId,
value: &T)
-> T
where T : TypeFoldable<'tcx> + HasTypeFlags
{
- let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+ let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
assoc::normalize_associated_types_in(&self.infcx,
- typer,
- &mut *fulfillment_cx, span,
+ &mut fulfillment_cx,
+ span,
body_id,
value)
}
ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id),
&fn_sig);
let fn_sig =
- inh.normalize_associated_types_in(&inh.infcx.parameter_environment,
- body.span,
+ inh.normalize_associated_types_in(body.span,
body.id,
&fn_sig);
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
where T : TypeFoldable<'tcx> + HasTypeFlags
{
- self.inh.normalize_associated_types_in(self.infcx(), span, self.body_id, value)
+ self.inh.normalize_associated_types_in(span, self.body_id, value)
}
fn normalize_associated_type(&self,
let cause = traits::ObligationCause::new(span,
self.body_id,
traits::ObligationCauseCode::MiscObligation);
- self.inh.fulfillment_cx
+ self.inh
+ .infcx
+ .fulfillment_cx
.borrow_mut()
.normalize_projection_type(self.infcx(),
- self.infcx(),
ty::ProjectionTy {
trait_ref: trait_ref,
item_name: item_name,
-> bool
{
traits::type_known_to_meet_builtin_bound(self.infcx(),
- self.param_env(),
ty,
ty::BoundSized,
span)
builtin_bound: ty::BuiltinBound,
cause: traits::ObligationCause<'tcx>)
{
- self.inh.fulfillment_cx.borrow_mut()
+ self.inh.infcx.fulfillment_cx.borrow_mut()
.register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
}
{
debug!("register_predicate({:?})",
obligation);
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
.register_predicate_obligation(self.infcx(), obligation);
}
region: ty::Region,
cause: traits::ObligationCause<'tcx>)
{
- let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
+ let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
fulfillment_cx.register_region_obligation(ty, region, cause);
}
assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
self.select_all_obligations_and_apply_defaults();
- let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
- match fulfillment_cx.select_all_or_error(self.infcx(), self.infcx()) {
+ let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
+ match fulfillment_cx.select_all_or_error(self.infcx()) {
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
}
/// Select as many obligations as we can at present.
fn select_obligations_where_possible(&self) {
match
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
- .select_where_possible(self.infcx(), self.infcx())
+ .select_where_possible(self.infcx())
{
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
/// work.
fn select_new_obligations(&self) {
match
- self.inh.fulfillment_cx
+ self.inh.infcx.fulfillment_cx
.borrow_mut()
- .select_new_obligations(self.infcx(), self.infcx())
+ .select_new_obligations(self.infcx())
{
Ok(()) => { }
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
let inh = static_inherited_fields(ccx, &tables);
let rty = ccx.tcx.node_id_to_type(id);
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
- let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
+ let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
check_const_with_ty(&fcx, sp, e, declty);
}
use check::dropck;
use check::FnCtxt;
use middle::free_region::FreeRegionMap;
-use middle::infer::InferCtxt;
use middle::implicator;
use middle::mem_categorization as mc;
use middle::region::CodeExtent;
use middle::subst::Substs;
use middle::traits;
-use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall, HasTypeFlags};
+use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags};
use middle::infer::{self, GenericKind};
use middle::pat_util;
// Make a copy of the region obligations vec because we'll need
// to be able to borrow the fulfillment-cx below when projecting.
let region_obligations =
- self.fcx.inh.fulfillment_cx.borrow()
- .region_obligations(node_id)
- .to_vec();
+ self.fcx
+ .inh
+ .infcx
+ .fulfillment_cx
+ .borrow()
+ .region_obligations(node_id)
+ .to_vec();
for r_o in ®ion_obligations {
debug!("visit_region_obligations: r_o={:?}",
// Processing the region obligations should not cause the list to grow further:
assert_eq!(region_obligations.len(),
- self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len());
+ self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
}
/// This method populates the region map's `free_region_map`. It walks over the transformed
debug!("relate_free_regions(t={:?})", ty);
let body_scope = CodeExtent::from_node_id(body_id);
let body_scope = ty::ReScope(body_scope);
- let implications = implicator::implications(self.fcx.infcx(), self.fcx.infcx(), body_id,
+ let implications = implicator::implications(self.fcx.infcx(), body_id,
ty, body_scope, span);
// Record any relations between free regions that we observe into the free-region-map.
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
/// needed.
-fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
- mc: mc::MemCategorizationContext<InferCtxt<'a, 'tcx>>,
+fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
+ mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
discr_cmt: mc::cmt<'tcx>,
root_pat: &ast::Pat) {
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
ty,
region);
- let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx.infcx(), rcx.body_id,
+ let implications = implicator::implications(rcx.fcx.infcx(), rcx.body_id,
ty, region, origin.span());
for implication in implications {
debug!("implication: {:?}", implication);
let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
let predicates = {
- let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+ let selcx = &mut traits::SelectionContext::new(fcx.infcx());
traits::normalize(selcx, cause.clone(), &predicates)
};
for predicate in predicates.value.predicates {
};
debug!("new_polytype={:?}", new_polytype);
- tcx.tcache.borrow_mut().insert(new_did, new_polytype);
+ tcx.register_item_type(new_did, new_polytype);
tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
tcx.impl_or_trait_items
.borrow_mut()
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
source, target);
- let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+ let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true);
let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
}
};
- let mut fulfill_cx = traits::FulfillmentContext::new(true);
+ let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
// Register an obligation for `A: Trait<B>`.
let cause = traits::ObligationCause::misc(span, impl_did.node);
fulfill_cx.register_predicate_obligation(&infcx, predicate);
// Check that all transitive obligations are satisfied.
- if let Err(errors) = fulfill_cx.select_all_or_error(&infcx,
- &infcx.parameter_environment) {
+ if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
traits::report_fulfillment_errors(&infcx, &errors);
}
pub fn check_coherence(crate_context: &CrateCtxt) {
CoherenceChecker {
crate_context: crate_context,
- inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None),
+ inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true),
inherent_impls: RefCell::new(FnvHashMap()),
}.check(crate_context.tcx.map.krate());
unsafety::check(crate_context.tcx);
impl1_def_id,
impl2_def_id);
- let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
}
ty: result_ty
};
- tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
+ tcx.register_item_type(variant_def_id, variant_scheme.clone());
tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
write_ty_to_tcx(tcx, variant.node.id, result_ty);
}
ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
debug!("method {} (id {}) has type {:?}",
ident, id, fty);
- ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
+ ccx.tcx.register_item_type(def_id, TypeScheme {
generics: ty_method.generics.clone(),
ty: fty
});
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
/* add the field to the tcache */
- ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
- ty::TypeScheme {
- generics: struct_generics.clone(),
- ty: tt
- });
+ ccx.tcx.register_item_type(local_def(v.node.id),
+ ty::TypeScheme {
+ generics: struct_generics.clone(),
+ ty: tt
+ });
ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
struct_predicates.clone());
let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
write_ty_to_tcx(tcx, it.id, selfty);
- tcx.tcache.borrow_mut().insert(local_def(it.id),
- TypeScheme { generics: ty_generics.clone(),
- ty: selfty });
+ tcx.register_item_type(local_def(it.id),
+ TypeScheme { generics: ty_generics.clone(),
+ ty: selfty });
tcx.predicates.borrow_mut().insert(local_def(it.id),
ty_predicates.clone());
if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
let ty = ccx.icx(&ty_predicates)
.to_ty(&ExplicitRscope, &*ty);
- tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
- TypeScheme {
- generics: ty_generics.clone(),
- ty: ty,
- });
+ tcx.register_item_type(local_def(impl_item.id),
+ TypeScheme {
+ generics: ty_generics.clone(),
+ ty: ty,
+ });
convert_associated_const(ccx, ImplContainer(local_def(it.id)),
impl_item.ident, impl_item.id,
impl_item.vis.inherit_from(parent_visibility),
ast::ConstTraitItem(ref ty, ref default) => {
let ty = ccx.icx(&trait_predicates)
.to_ty(&ExplicitRscope, ty);
- tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
- TypeScheme {
- generics: trait_def.generics.clone(),
- ty: ty,
- });
+ tcx.register_item_type(local_def(trait_item.id),
+ TypeScheme {
+ generics: trait_def.generics.clone(),
+ ty: ty,
+ });
convert_associated_const(ccx, TraitContainer(local_def(it.id)),
trait_item.ident, trait_item.id,
ast::Public, ty, default.as_ref().map(|d| &**d));
// Enum-like.
write_ty_to_tcx(tcx, ctor_id, selfty);
- tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
+ tcx.register_item_type(local_def(ctor_id), scheme);
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
} else if struct_def.fields[0].node.kind.is_unnamed() {
// Tuple-like.
let inputs: Vec<_> =
struct_def.fields
.iter()
- .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
- .unwrap()
- .ty)
+ .map(|field| tcx.lookup_item_type(
+ local_def(field.node.id)).ty)
.collect();
let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
&inputs[..],
selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
- tcx.tcache.borrow_mut().insert(local_def(ctor_id),
- TypeScheme {
- generics: scheme.generics,
- ty: ctor_fn_ty
- });
+ tcx.register_item_type(local_def(ctor_id),
+ TypeScheme {
+ generics: scheme.generics,
+ ty: ctor_fn_ty
+ });
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
}
}
base_type,
base_type_free);
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
drop(::require_same_types(tcx,
Some(&infcx),
false,
```
"##,
+E0124: r##"
+You declared two fields of a struct with the same name. Erroneous code
+example:
+
+```
+struct Foo {
+ field1: i32,
+ field1: i32 // error: field is already declared
+}
+```
+
+Please verify that the field names have been correctly spelled. Example:
+
+```
+struct Foo {
+ field1: i32,
+ field2: i32 // ok!
+}
+```
+"##,
+
E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
E0120,
E0122,
E0123,
- E0124,
E0127,
E0128,
E0129,
{
let result = match maybe_infcx {
None => {
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
}
Some(infcx) => {
#[cfg(any(target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod os {
use libc;
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
fn test_errors_do_not_crash() {
// Open /dev/null as a library to get an error, and make sure
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod dl {
use prelude::v1::*;
/// - freebsd
/// - dragonfly
/// - bitrig
+ /// - netbsd
/// - openbsd
/// - android
/// - windows
pub const EXE_EXTENSION: &'static str = "";
}
+#[cfg(target_os = "netbsd")]
+mod os {
+ pub const FAMILY: &'static str = "unix";
+ pub const OS: &'static str = "netbsd";
+ pub const DLL_PREFIX: &'static str = "lib";
+ pub const DLL_SUFFIX: &'static str = ".so";
+ pub const DLL_EXTENSION: &'static str = "so";
+ pub const EXE_SUFFIX: &'static str = "";
+ pub const EXE_EXTENSION: &'static str = "";
+}
+
#[cfg(target_os = "openbsd")]
mod os {
pub const FAMILY: &'static str = "unix";
// FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
// no longer has rounding errors.
- #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+ #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
#[test]
fn timeouts() {
let addr = next_test_ip4();
assert_eq!(format!("{:?}", udpsock), compare);
}
- // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
+ // FIXME: re-enabled bitrig/openbsd/netbsd tests once their socket timeout code
// no longer has rounding errors.
- #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+ #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
#[test]
fn timeouts() {
let addr = next_test_ip4();
#[cfg(target_os = "linux")] pub mod linux;
#[cfg(target_os = "macos")] pub mod macos;
#[cfg(target_os = "nacl")] pub mod nacl;
+#[cfg(target_os = "netbsd")] pub mod netbsd;
#[cfg(target_os = "openbsd")] pub mod openbsd;
pub mod raw;
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! OpenBSD-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+
+pub mod fs {
+ #![stable(feature = "raw_ext", since = "1.1.0")]
+ pub use sys::fs::MetadataExt;
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! NetBSD/OpenBSD-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t};
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+#[repr(C)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mode: mode_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_dev: dev_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ino: ino_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_nlink: nlink_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_uid: uid_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_gid: gid_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_rdev: dev_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_atime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_atime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mtime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mtime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ctime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ctime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_size: off_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blocks: blkcnt_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blksize: blksize_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_flags: fflags_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_gen: u32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_birthtime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_birthtime_nsec: c_long,
+}
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod imp {
use prelude::v1::*;
#[link(name = "unwind", kind = "static")]
extern {}
-#[cfg(any(target_os = "android", target_os = "openbsd"))]
+#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
#[link(name = "gcc")]
extern {}
#[cfg(any(target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
#[link(name = "pthread")]
extern {}
/// If the corresponding `Sender` has disconnected, or it disconnects while
/// this call is blocking, this call will wake up and return `Err` to
/// indicate that no more messages can ever be received on this channel.
+ /// However, since channels are buffered, messages sent before the disconnect
+ /// will still be properly received.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::sync::mpsc;
+ /// use std::thread;
+ ///
+ /// let (send, recv) = mpsc::channel();
+ /// let handle = thread::spawn(move || {
+ /// send.send(1u8).unwrap();
+ /// });
+ ///
+ /// handle.join().unwrap();
+ ///
+ /// assert_eq!(Ok(1), recv.recv());
+ /// ```
+ ///
+ /// Buffering behavior:
+ ///
+ /// ```
+ /// use std::sync::mpsc;
+ /// use std::thread;
+ /// use std::sync::mpsc::RecvError;
+ ///
+ /// let (send, recv) = mpsc::channel();
+ /// let handle = thread::spawn(move || {
+ /// send.send(1u8).unwrap();
+ /// send.send(2).unwrap();
+ /// send.send(3).unwrap();
+ /// drop(send);
+ /// });
+ ///
+ /// // wait for the thread to join so we ensure the sender is dropped
+ /// handle.join().unwrap();
+ ///
+ /// assert_eq!(Ok(1), recv.recv());
+ /// assert_eq!(Ok(2), recv.recv());
+ /// assert_eq!(Ok(3), recv.recv());
+ /// assert_eq!(Err(RecvError), recv.recv());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn recv(&self) -> Result<T, RecvError> {
loop {
target_arch = "powerpc",
all(target_arch = "arm", target_os = "ios"),
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
unsafe fn target_record_sp_limit(_: usize) {
}
target_arch = "powerpc",
all(target_arch = "arm", target_os = "ios"),
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
#[inline(always)]
unsafe fn target_get_sp_limit() -> usize {
let selfname = if cfg!(target_os = "freebsd") ||
cfg!(target_os = "dragonfly") ||
cfg!(target_os = "bitrig") ||
+ cfg!(target_os = "netbsd") ||
cfg!(target_os = "openbsd") {
env::current_exe().ok()
} else {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub const FIOCLEX: libc::c_ulong = 0x20006601;
target_os = "dragonfly"))]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
#[cfg(any(target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101;
#[cfg(target_os = "android")]
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub struct passwd {
pub pw_name: *mut libc::c_char,
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod signal_os {
use libc;
pub struct sigset_t {
bits: [u32; 4],
}
- #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+ #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
pub type sigset_t = libc::c_uint;
// This structure has more fields, but we're not all that interested in
pub _status: libc::c_int,
pub si_addr: *mut libc::c_void
}
- #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+ #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
#[repr(C)]
pub struct siginfo {
pub si_signo: libc::c_int,
}
#[cfg(any(target_os = "macos", target_os = "ios",
- target_os = "bitrig", target_os = "openbsd"))]
+ target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
#[repr(C)]
pub struct sigaction {
pub sa_sigaction: sighandler_t,
#[cfg(target_os = "linux")] pub use os::linux as platform;
#[cfg(target_os = "macos")] pub use os::macos as platform;
#[cfg(target_os = "nacl")] pub use os::nacl as platform;
+#[cfg(target_os = "netbsd")] pub use os::netbsd as platform;
#[cfg(target_os = "openbsd")] pub use os::openbsd as platform;
pub mod backtrace;
__error()
}
- #[cfg(target_os = "bitrig")]
- fn errno_location() -> *const c_int {
- extern {
- fn __errno() -> *const c_int;
- }
- unsafe {
- __errno()
- }
- }
-
#[cfg(target_os = "dragonfly")]
unsafe fn errno_location() -> *const c_int {
extern { fn __dfly_error() -> *const c_int; }
__dfly_error()
}
- #[cfg(target_os = "openbsd")]
+ #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
unsafe fn errno_location() -> *const c_int {
extern { fn __errno() -> *const c_int; }
__errno()
::fs::read_link("/proc/curproc/file")
}
-#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+#[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
pub fn current_exe() -> io::Result<PathBuf> {
use sync::StaticMutex;
static LOCK: StaticMutex = StaticMutex::new();
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub fn args() -> Args {
use rt;
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod imp {
pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod imp {
use sys_common::stack;
#[cfg(not(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd")))]
mod imp {
use libc;
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod os {
use libc;
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
pub fn set_name(name: &str) {
extern {
#[cfg(all(not(target_os = "linux"),
not(target_os = "macos"),
not(target_os = "bitrig"),
+ not(target_os = "netbsd"),
not(target_os = "openbsd")))]
pub mod guard {
pub unsafe fn current() -> usize { 0 }
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
#[cfg(any(target_os = "macos",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
unsafe fn get_stack_start() -> *mut libc::c_void {
current() as *mut libc::c_void
pthread_get_stacksize_np(pthread_self())) as usize
}
- #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
+ #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
pub unsafe fn current() -> usize {
#[repr(C)]
struct stack_t {
#[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd"))]
type pthread_key_t = ::libc::c_int;
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd")))]
type pthread_key_t = ::libc::c_uint;
// OpenBSD provide it via libc
#[cfg(not(any(target_os = "android",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_env = "musl")))]
#[link(name = "rt")]
pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD;
+pub const HANDLE_FLAG_INHERIT: libc::DWORD = 0x00000001;
+
#[repr(C)]
#[cfg(target_arch = "x86")]
pub struct WSADATA {
pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
lpProfileDir: libc::LPCWSTR,
lpcchSize: *mut libc::DWORD) -> libc::BOOL;
+ pub fn SetHandleInformation(hObject: libc::HANDLE,
+ dwMask: libc::DWORD,
+ dwFlags: libc::DWORD) -> libc::BOOL;
}
// Functions that aren't available on Windows XP, but we still use them and just
SocketAddr::V4(..) => libc::AF_INET,
SocketAddr::V6(..) => libc::AF_INET6,
};
- let socket = unsafe {
- c::WSASocketW(fam, ty, 0, 0 as *mut _, 0,
- c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT)
- };
- match socket {
- INVALID_SOCKET => Err(last_error()),
- n => Ok(Socket(n)),
- }
+ let socket = try!(unsafe {
+ match c::WSASocketW(fam, ty, 0, 0 as *mut _, 0,
+ c::WSA_FLAG_OVERLAPPED) {
+ INVALID_SOCKET => Err(last_error()),
+ n => Ok(Socket(n)),
+ }
+ });
+ try!(socket.set_no_inherit());
+ Ok(socket)
}
pub fn accept(&self, storage: *mut libc::sockaddr,
len: *mut libc::socklen_t) -> io::Result<Socket> {
- match unsafe { libc::accept(self.0, storage, len) } {
- INVALID_SOCKET => Err(last_error()),
- n => Ok(Socket(n)),
- }
+ let socket = try!(unsafe {
+ match libc::accept(self.0, storage, len) {
+ INVALID_SOCKET => Err(last_error()),
+ n => Ok(Socket(n)),
+ }
+ });
+ try!(socket.set_no_inherit());
+ Ok(socket)
}
pub fn duplicate(&self) -> io::Result<Socket> {
- unsafe {
+ let socket = try!(unsafe {
let mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
try!(cvt(c::WSADuplicateSocketW(self.0,
c::GetCurrentProcessId(),
info.iSocketType,
info.iProtocol,
&mut info, 0,
- c::WSA_FLAG_OVERLAPPED |
- c::WSA_FLAG_NO_HANDLE_INHERIT) {
+ c::WSA_FLAG_OVERLAPPED) {
INVALID_SOCKET => Err(last_error()),
n => Ok(Socket(n)),
}
- }
+ });
+ try!(socket.set_no_inherit());
+ Ok(socket)
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
Ok(Some(Duration::new(secs as u64, nsec as u32)))
}
}
+
+ fn set_no_inherit(&self) -> io::Result<()> {
+ sys::cvt(unsafe {
+ c::SetHandleInformation(self.0 as libc::HANDLE,
+ c::HANDLE_FLAG_INHERIT, 0)
+ }).map(|_| ())
+ }
}
impl Drop for Socket {
#[cfg_attr(not(any(windows,
target_os = "android",
target_os = "ios",
+ target_os = "netbsd",
target_os = "openbsd",
target_arch = "aarch64")),
thread_local)]
#[cfg(not(any(windows,
target_os = "android",
target_os = "ios",
+ target_os = "netbsd",
target_os = "openbsd",
target_arch = "aarch64",
no_elf_tls)))]
#[cfg(any(windows,
target_os = "android",
target_os = "ios",
+ target_os = "netbsd",
target_os = "openbsd",
target_arch = "aarch64",
no_elf_tls))]
OsiOS,
OsDragonfly,
OsBitrig,
+ OsNetbsd,
OsOpenbsd,
}
OsFreebsd => "freebsd".fmt(f),
OsDragonfly => "dragonfly".fmt(f),
OsBitrig => "bitrig".fmt(f),
+ OsNetbsd => "netbsd".fmt(f),
OsOpenbsd => "openbsd".fmt(f),
}
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(unused_imports)]
+
+mod foo {
+ use baz::bar;
+ //~^ ERROR import `bar` conflicts with existing submodule
+ mod bar {}
+}
+mod baz { pub mod bar {} }
+
+fn main() {}
// ignore-windows
// ignore-freebsd
// ignore-openbsd
+// ignore-netbsd
// ignore-bitrig
// compile-flags: -Z parse-only
// Test a very simple custom DST coercion.
-#![feature(core)]
+#![feature(core, rc_weak)]
use std::cell::RefCell;
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
trait Baz {
fn get(&self) -> i32;
let b: Rc<Baz> = a.clone();
assert_eq!(b.get(), 42);
+ let c: Weak<i32> = a.downgrade();
+ let d: Weak<Baz> = c.clone();
+
let _c = b.clone();
let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
let b: Rc<RefCell<Baz>> = a.clone();
assert_eq!(b.borrow().get(), 42);
+ let c: Weak<RefCell<Baz>> = a.downgrade();
}
target_os = "macos",
target_os = "freebsd",
target_os = "dragonfly",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod m {
#[main]
target_os = "macos",
target_os = "freebsd",
target_os = "dragonfly",
+ target_os = "netbsd",
target_os = "openbsd"))]
mod m {
#[cfg(target_arch = "x86")]
// except according to those terms.
// ignore-android needs extra network permissions
-// ignore-openbsd system ulimit (Too many open files)
// ignore-bitrig system ulimit (Too many open files)
+// ignore-netbsd system ulimit (Too many open files)
+// ignore-openbsd system ulimit (Too many open files)
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
target_os = "freebsd",
target_os = "dragonfly",
target_os = "bitrig",
+ target_os = "netbsd",
target_os = "openbsd",
target_os = "android"))]
pub fn main() { }