diff options
| author | Glyne J. Gittens <Jgit121@gmail.com> | 2017-02-19 17:32:21 -0500 |
|---|---|---|
| committer | Glyne J. Gittens <Jgit121@gmail.com> | 2017-02-19 17:32:21 -0500 |
| commit | 9a6a72b81837bed367de38297479ad554537d70c (patch) | |
| tree | a9fc17869c699ea448d458d2194dec241e410099 /src | |
| parent | b3f61ce538862e58d4d3cb02960fe6e9a8ccc4e4 (diff) | |
| parent | 0e77277950aafd38ce3e52b7b1cd9bcc6664de3c (diff) | |
Merge branch 'master' of https://github.com/rust-lang/rust
Diffstat (limited to 'src')
47 files changed, 390 insertions, 222 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 90fd31ecbdd..62e476bd737 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -205,6 +205,11 @@ fn main() { } } } + + if target.contains("pc-windows-msvc") { + cmd.arg("-Z").arg("unstable-options"); + cmd.arg("-C").arg("target-feature=+crt-static"); + } } if verbose > 1 { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ee3f663dbd5..7ca7ef4bd72 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -173,6 +173,8 @@ class RustBuild(object): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/rustc") + self.fix_executable(self.bin_root() + "/bin/rustdoc") with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_rustc_date()) @@ -185,9 +187,63 @@ class RustBuild(object): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/cargo") with open(self.cargo_stamp(), 'w') as f: f.write(self.stage0_cargo_rev()) + def fix_executable(self, fname): + # If we're on NixOS we need to change the path to the dynamic loader + + default_encoding = sys.getdefaultencoding() + try: + ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding) + except (subprocess.CalledProcessError, WindowsError): + return + + if ostype != "Linux": + return + + if not os.path.exists("/etc/NIXOS"): + return + if os.path.exists("/lib"): + return + + # At this point we're pretty sure the user is running NixOS + print("info: you seem to be running NixOS. Attempting to patch " + fname) + + try: + interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname]) + interpreter = interpreter.strip().decode(default_encoding) + except subprocess.CalledProcessError as e: + print("warning: failed to call patchelf: %s" % e) + return + + loader = interpreter.split("/")[-1] + + try: + ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh']) + ldd_output = ldd_output.strip().decode(default_encoding) + except subprocess.CalledProcessError as e: + print("warning: unable to call ldd: %s" % e) + return + + for line in ldd_output.splitlines(): + libname = line.split()[0] + if libname.endswith(loader): + loader_path = libname[:len(libname) - len(loader)] + break + else: + print("warning: unable to find the path to the dynamic linker") + return + + correct_interpreter = loader_path + loader + + try: + subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname]) + except subprocess.CalledProcessError as e: + print("warning: failed to call patchelf: %s" % e) + return + def stage0_cargo_rev(self): return self._cargo_rev diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 21fc61cc814..f16fc2092f6 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -99,6 +99,12 @@ pub fn llvm(build: &Build, target: &str) { .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + if target.contains("msvc") { + cfg.define("LLVM_USE_CRT_DEBUG", "MT"); + cfg.define("LLVM_USE_CRT_RELEASE", "MT"); + cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT"); + } + if target.starts_with("i686") { cfg.define("LLVM_BUILD_32_BITS", "ON"); } diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md index 6c4700f9305..079324d56d1 100644 --- a/src/doc/book/src/procedural-macros.md +++ b/src/doc/book/src/procedural-macros.md @@ -169,7 +169,7 @@ So this is where quotes comes in. The `ast` argument is a struct that gives us a representation of our type (which can be either a `struct` or an `enum`). Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html), there is some useful information there. We are able to get the name of the -type using `ast.ident`. The `quote!` macro let's us write up the Rust code +type using `ast.ident`. The `quote!` macro lets us write up the Rust code that we wish to return and convert it into `Tokens`. `quote!` let's us use some really cool templating mechanics; we simply write `#name` and `quote!` will replace it with the variable named `name`. You can even do some repetition diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 4c82e2e2e7e..e92eb4ff7bd 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1250,17 +1250,17 @@ impl String { self.len() == 0 } - /// Divide one string into two at an index. + /// Splits the string into two at the given index. /// - /// The argument, `mid`, should be a byte offset from the start of the string. It must also - /// be on the boundary of a UTF-8 code point. + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. /// - /// The two strings returned go from the start of the string to `mid`, and from `mid` to the end - /// of the string. + /// Note that the capacity of `self` does not change. /// /// # Panics /// - /// Panics if `mid` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last /// code point of the string. /// /// # Examples @@ -1275,9 +1275,9 @@ impl String { /// ``` #[inline] #[stable(feature = "string_split_off", since = "1.16.0")] - pub fn split_off(&mut self, mid: usize) -> String { - assert!(self.is_char_boundary(mid)); - let other = self.vec.split_off(mid); + pub fn split_off(&mut self, at: usize) -> String { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); unsafe { String::from_utf8_unchecked(other) } } diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index d41767cce18..3785bbe9bb0 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1603,12 +1603,12 @@ pub trait Iterator { let mut i = self.len(); while let Some(v) = self.next_back() { - if predicate(v) { - return Some(i - 1); - } // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. i -= 1; + if predicate(v) { + return Some(i); + } } None } diff --git a/src/liblibc b/src/liblibc -Subproject 8d8264b967a31a1a8cebe2a05110564106b6e90 +Subproject 7a3754f2bb5e65eb39adacb189c362617303217 diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 006de1c06e2..96d1a925425 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -131,7 +131,37 @@ pub enum DepNode<D: Clone + Debug> { // which would yield an overly conservative dep-graph. TraitItems(D), ReprHints(D), - TraitSelect(Vec<D>), + + // Trait selection cache is a little funny. Given a trait + // reference like `Foo: SomeTrait<Bar>`, there could be + // arbitrarily many def-ids to map on in there (e.g., `Foo`, + // `SomeTrait`, `Bar`). We could have a vector of them, but it + // requires heap-allocation, and trait sel in general can be a + // surprisingly hot path. So instead we pick two def-ids: the + // trait def-id, and the first def-id in the input types. If there + // is no def-id in the input types, then we use the trait def-id + // again. So for example: + // + // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` + // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` + // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // + // You can see that we map many trait refs to the same + // trait-select node. This is not a problem, it just means + // imprecision in our dep-graph tracking. The important thing is + // that for any given trait-ref, we always map to the **same** + // trait-select node. + TraitSelect { trait_def_id: D, input_def_id: D }, + + // For proj. cache, we just keep a list of all def-ids, since it is + // not a hotspot. + ProjectionCache { def_ids: Vec<D> }, } impl<D: Clone + Debug> DepNode<D> { @@ -236,9 +266,17 @@ impl<D: Clone + Debug> DepNode<D> { TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), - TraitSelect(ref type_ds) => { - let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect()); - Some(TraitSelect(type_ds)) + TraitSelect { ref trait_def_id, ref input_def_id } => { + op(trait_def_id).and_then(|trait_def_id| { + op(input_def_id).and_then(|input_def_id| { + Some(TraitSelect { trait_def_id: trait_def_id, + input_def_id: input_def_id }) + }) + }) + } + ProjectionCache { ref def_ids } => { + let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect(); + def_ids.map(|d| ProjectionCache { def_ids: d }) } } } diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b6fce2d6ca0..53b7be74f85 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -59,32 +59,45 @@ pub enum Def { Err, } -/// The result of resolving a path. -/// Before type checking completes, `depth` represents the number of -/// trailing segments which are yet unresolved. Afterwards, if there -/// were no errors, all paths should be fully resolved, with `depth` -/// set to `0` and `base_def` representing the final resolution. -/// +/// The result of resolving a path before lowering to HIR. +/// `base_def` is definition of resolved part of the +/// path, `unresolved_segments` is the number of unresolved +/// segments. /// module::Type::AssocX::AssocY::MethodOrAssocType /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_def depth = 3 +/// base_def unresolved_segments = 3 /// /// <T as Trait>::AssocX::AssocY::MethodOrAssocType /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_def depth = 2 +/// base_def unresolved_segments = 2 #[derive(Copy, Clone, Debug)] pub struct PathResolution { - pub base_def: Def, - pub depth: usize + base_def: Def, + unresolved_segments: usize, } impl PathResolution { - pub fn new(def: Def) -> PathResolution { - PathResolution { base_def: def, depth: 0 } + pub fn new(def: Def) -> Self { + PathResolution { base_def: def, unresolved_segments: 0 } + } + + pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self { + if def == Def::Err { unresolved_segments = 0 } + PathResolution { base_def: def, unresolved_segments: unresolved_segments } + } + + #[inline] + pub fn base_def(&self) -> Def { + self.base_def + } + + #[inline] + pub fn unresolved_segments(&self) -> usize { + self.unresolved_segments } pub fn kind_name(&self) -> &'static str { - if self.depth != 0 { + if self.unresolved_segments != 0 { "associated item" } else { self.base_def.kind_name() diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8a4acb3d038..c87ce6505fc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -217,10 +217,10 @@ impl<'a> LoweringContext<'a> { fn expect_full_def(&mut self, id: NodeId) -> Def { self.resolver.get_resolution(id).map_or(Def::Err, |pr| { - if pr.depth != 0 { + if pr.unresolved_segments() != 0 { bug!("path not fully resolved: {:?}", pr); } - pr.base_def + pr.base_def() }) } @@ -421,9 +421,9 @@ impl<'a> LoweringContext<'a> { let resolution = self.resolver.get_resolution(id) .unwrap_or(PathResolution::new(Def::Err)); - let proj_start = p.segments.len() - resolution.depth; + let proj_start = p.segments.len() - resolution.unresolved_segments(); let path = P(hir::Path { - def: resolution.base_def, + def: resolution.base_def(), segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| { let param_mode = match (qself_position, param_mode) { (Some(j), ParamMode::Optional) if i < j => { @@ -443,7 +443,7 @@ impl<'a> LoweringContext<'a> { index: this.def_key(def_id).parent.expect("missing parent") } }; - let type_def_id = match resolution.base_def { + let type_def_id = match resolution.base_def() { Def::AssociatedTy(def_id) if i + 2 == proj_start => { Some(parent_def_id(self, def_id)) } @@ -474,7 +474,7 @@ impl<'a> LoweringContext<'a> { // Simple case, either no projections, or only fully-qualified. // E.g. `std::mem::size_of` or `<I as Iterator>::Item`. - if resolution.depth == 0 { + if resolution.unresolved_segments() == 0 { return hir::QPath::Resolved(qself, path); } @@ -749,7 +749,7 @@ impl<'a> LoweringContext<'a> { bound_pred.bound_lifetimes.is_empty() => { if let Some(Def::TyParam(def_id)) = self.resolver.get_resolution(bound_pred.bounded_ty.id) - .map(|d| d.base_def) { + .map(|d| d.base_def()) { if let Some(node_id) = self.resolver.definitions().as_local_node_id(def_id) { for ty_param in &g.ty_params { @@ -1295,7 +1295,7 @@ impl<'a> LoweringContext<'a> { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, pth1, ref sub) => { self.with_parent_def(p.id, |this| { - match this.resolver.get_resolution(p.id).map(|d| d.base_def) { + match this.resolver.get_resolution(p.id).map(|d| d.base_def()) { // `None` can occur in body-less function signatures def @ None | def @ Some(Def::Local(_)) => { let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d8212807eb2..3403cf04774 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> { /// End the current live range for the storage of the local. StorageDead(Lvalue<'tcx>), + InlineAsm { + asm: InlineAsm, + outputs: Vec<Lvalue<'tcx>>, + inputs: Vec<Operand<'tcx>> + }, + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } @@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> { StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv), SetDiscriminant{lvalue: ref lv, variant_index: index} => { write!(fmt, "discriminant({:?}) = {:?}", lv, index) - } + }, + InlineAsm { ref asm, ref outputs, ref inputs } => { + write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) + }, Nop => write!(fmt, "nop"), } } @@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> { /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>), - - InlineAsm { - asm: InlineAsm, - outputs: Vec<Lvalue<'tcx>>, - inputs: Vec<Operand<'tcx>> - } } #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] @@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a), Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval), Box(ref t) => write!(fmt, "Box({:?})", t), - InlineAsm { ref asm, ref outputs, ref inputs } => { - write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) - } - Ref(_, borrow_kind, ref lv) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 7b0863b4c42..5c8d031caf6 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> { } } } - Rvalue::InlineAsm { .. } => None } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index be3c43db7ba..7cdbd5cae06 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -333,6 +333,16 @@ macro_rules! make_mir_visitor { StatementKind::StorageDead(ref $($mutability)* lvalue) => { self.visit_lvalue(lvalue, LvalueContext::StorageDead, location); } + StatementKind::InlineAsm { ref $($mutability)* outputs, + ref $($mutability)* inputs, + asm: _ } => { + for output in & $($mutability)* outputs[..] { + self.visit_lvalue(output, LvalueContext::Store, location); + } + for input in & $($mutability)* inputs[..] { + self.visit_operand(input, location); + } + } StatementKind::Nop => {} } } @@ -526,17 +536,6 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } } - - Rvalue::InlineAsm { ref $($mutability)* outputs, - ref $($mutability)* inputs, - asm: _ } => { - for output in & $($mutability)* outputs[..] { - self.visit_lvalue(output, LvalueContext::Store, location); - } - for input in & $($mutability)* inputs[..] { - self.visit_operand(input, location); - } - } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 4893e240911..58ab713ef27 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -628,6 +628,11 @@ pub fn get_vtable_methods<'a, 'tcx>( |_, _| tcx.mk_region(ty::ReErased), |def, _| trait_ref.substs().type_for_def(def)); + // the trait type may have higher-ranked lifetimes in it; + // so erase them if they appear, so that we get the type + // at some particular call site + let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); + // It's possible that the method relies on where clauses that // do not hold for this particular set of type parameters. // Note that this method could then never be called, so we diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 41f3f825c3d..40c62762c3c 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2547,7 +2547,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // TyError and ensure they do not affect any other fields. // This could be checked after type collection for any struct // with a potentially unsized trailing field. - let params = substs_a.params().iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(tcx.types.err) } else { @@ -2567,7 +2567,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source structure with the target's // type parameters is a subtype of the target. - let params = substs_a.params().iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(substs_b.type_at(i)) } else { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 411e14531fa..7937d2ccfe4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -34,7 +34,6 @@ use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; use std::cell::{Cell, RefCell, Ref}; use std::hash::{Hash, Hasher}; -use std::iter; use std::ops::Deref; use std::rc::Rc; use std::slice; @@ -843,27 +842,22 @@ impl<'tcx> TraitPredicate<'tcx> { /// Creates the dep-node for selecting/evaluating this trait reference. fn dep_node(&self) -> DepNode<DefId> { - // Ideally, the dep-node would just have all the input types - // in it. But they are limited to including def-ids. So as an - // approximation we include the def-ids for all nominal types - // found somewhere. This means that we will e.g. conflate the - // dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we - // would have distinct dep-nodes for `Vec<u32>: SomeTrait`, - // `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`. - // Note that it's always sound to conflate dep-nodes, it just - // leads to more recompilation. - let def_ids: Vec<_> = + // Extact the trait-def and first def-id from inputs. See the + // docs for `DepNode::TraitSelect` for more information. + let trait_def_id = self.def_id(); + let input_def_id = self.input_types() .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => - Some(adt_def.did), - _ => - None + ty::TyAdt(adt_def, _) => Some(adt_def.did), + _ => None }) - .chain(iter::once(self.def_id())) - .collect(); - DepNode::TraitSelect(def_ids) + .next() + .unwrap_or(trait_def_id); + DepNode::TraitSelect { + trait_def_id: trait_def_id, + input_def_id: input_def_id + } } pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index adedf78bba7..2e3009b4ed6 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -143,7 +143,7 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, { let tcx = relation.tcx(); - let params = a_subst.params().iter().zip(b_subst.params()).enumerate().map(|(i, (a, b))| { + let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) { Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?)) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index d6f61a12a3c..c0a529b936b 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -255,12 +255,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } #[inline] - pub fn params(&self) -> &[Kind<'tcx>] { - // FIXME (dikaiosune) this should be removed, and corresponding compilation errors fixed - self - } - - #[inline] pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { self.iter().filter_map(|k| k.as_type()) } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index 1fa4da94dd6..7888a56d39d 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -473,6 +473,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index ea6ef423c92..940dd5433a0 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -104,6 +104,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 0c7e922c48a..35ace6628cf 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -412,6 +412,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck"); } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } @@ -436,8 +437,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } Rvalue::Ref(..) | Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::InlineAsm { .. } => {} + Rvalue::Len(..) => {} Rvalue::Box(..) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index a0c36139ddc..d9283e7037f 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -378,6 +378,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} }, None => { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index dad1d713168..7adcc0e730b 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -49,21 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Scope { extent, value } => { this.in_scope(extent, block, |this| this.as_rvalue(block, value)) } - ExprKind::InlineAsm { asm, outputs, inputs } => { - let outputs = outputs.into_iter().map(|output| { - unpack!(block = this.as_lvalue(block, output)) - }).collect(); - - let inputs = inputs.into_iter().map(|input| { - unpack!(block = this.as_operand(block, input)) - }).collect(); - - block.and(Rvalue::InlineAsm { - asm: asm.clone(), - outputs: outputs, - inputs: inputs - }) - } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); block.and(Rvalue::Repeat(value_operand, count)) @@ -238,6 +223,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } | + ExprKind::InlineAsm { .. } | ExprKind::StaticRef { .. } => { // these do not have corresponding `Rvalue` variants, // so make an operand and then return that diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 35841c2cbdf..e66f2b4e2bf 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -232,6 +232,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::AssignOp { .. } | ExprKind::Continue { .. } | ExprKind::Break { .. } | + ExprKind::InlineAsm { .. } | ExprKind::Return {.. } => { this.stmt_expr(block, expr) } @@ -257,7 +258,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Literal { .. } | - ExprKind::InlineAsm { .. } | ExprKind::Field { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { Category::Rvalue(RvalueFunc::Into) => false, diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index f04d630379a..c577aab40db 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -117,6 +117,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.exit_scope(expr_span, extent, block, return_block); this.cfg.start_new_block().unit() } + ExprKind::InlineAsm { asm, outputs, inputs } => { + let outputs = outputs.into_iter().map(|output| { + unpack!(block = this.as_lvalue(block, output)) + }).collect(); + let inputs = inputs.into_iter().map(|input| { + unpack!(block = this.as_operand(block, input)) + }).collect(); + this.cfg.push(block, Statement { + source_info: source_info, + kind: StatementKind::InlineAsm { + asm: asm.clone(), + outputs: outputs, + inputs: inputs + }, + }); + block.unit() + } _ => { let expr_ty = expr.ty; let temp = this.temp(expr.ty.clone()); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 922521726c6..4459142cfb2 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -774,10 +774,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } } - - Rvalue::InlineAsm {..} => { - self.not_const(); - } } } @@ -933,6 +929,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | + StatementKind::InlineAsm {..} | StatementKind::Nop => {} } }); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 8ede7aaab5f..8d108815e0f 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -361,9 +361,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}", lv_ty, rv_ty, terr); } - // FIXME: rvalue with undeterminable type - e.g. inline - // asm. } + // FIXME: rvalue with undeterminable type - e.g. AggregateKind::Array branch that + // returns `None`. } StatementKind::SetDiscriminant{ ref lvalue, variant_index } => { let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx); @@ -392,6 +392,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 517a4720563..33b7089c382 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -128,6 +128,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", + StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", StatementKind::Nop => "StatementKind::Nop", }, &statement.kind); self.super_statement(block, statement, location); @@ -198,7 +199,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { "Rvalue::Aggregate" } - Rvalue::InlineAsm { .. } => "Rvalue::InlineAsm", }; self.record(rvalue_kind, rvalue); self.super_rvalue(rvalue, location); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fa3c12624c6..c9e870188aa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1195,7 +1195,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect(); match self.resolve_path(&path, Some(namespace), Some(span)) { PathResult::Module(module) => *def = module.def().unwrap(), - PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def, + PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => + *def = path_res.base_def(), PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) { PathResult::Failed(msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -1718,7 +1719,7 @@ impl<'a> Resolver<'a> { let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { let def = self.smart_resolve_path(trait_ref.ref_id, None, - &trait_ref.path, PathSource::Trait).base_def; + &trait_ref.path, PathSource::Trait).base_def(); if def != Def::Err { new_val = Some((def.def_id(), trait_ref.clone())); new_id = Some(def.def_id()); @@ -1849,8 +1850,8 @@ impl<'a> Resolver<'a> { pat.walk(&mut |pat| { if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { - if sub_pat.is_some() || match self.def_map.get(&pat.id) { - Some(&PathResolution { base_def: Def::Local(..), .. }) => true, + if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) { + Some(Def::Local(..)) => true, _ => false, } { let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; @@ -2248,14 +2249,14 @@ impl<'a> Resolver<'a> { let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span, source.defer_to_typeck(), source.global_by_default()) { - Some(resolution) if resolution.depth == 0 => { - if is_expected(resolution.base_def) || resolution.base_def == Def::Err { + Some(resolution) if resolution.unresolved_segments() == 0 => { + if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err { resolution } else { // Add a temporary hack to smooth the transition to new struct ctor // visibility rules. See #38932 for more details. let mut res = None; - if let Def::Struct(def_id) = resolution.base_def { + if let Def::Struct(def_id) = resolution.base_def() { if let Some((ctor_def, ctor_vis)) = self.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_def) && self.is_accessible(ctor_vis) { @@ -2268,7 +2269,7 @@ impl<'a> Resolver<'a> { } } - res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def))) + res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def()))) } } Some(resolution) if source.defer_to_typeck() => { @@ -2321,7 +2322,8 @@ impl<'a> Resolver<'a> { match self.resolve_qpath(id, qself, path, ns, span, global_by_default) { // If defer_to_typeck, then resolution > no resolution, // otherwise full resolution > partial resolution > no resolution. - Some(res) if res.depth == 0 || defer_to_typeck => return Some(res), + Some(res) if res.unresolved_segments() == 0 || defer_to_typeck => + return Some(res), res => if fin_res.is_none() { fin_res = res }, }; } @@ -2346,19 +2348,17 @@ impl<'a> Resolver<'a> { if let Some(qself) = qself { if qself.position == 0 { // FIXME: Create some fake resolution that can't possibly be a type. - return Some(PathResolution { - base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)), - depth: path.len(), - }); + return Some(PathResolution::with_unresolved_segments( + Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len() + )); } // Make sure `A::B` in `<T as A>::B::C` is a trait item. let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; - let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], - span, PathSource::TraitItem(ns)); - if res.base_def != Def::Err { - res.depth += path.len() - qself.position - 1; - } - return Some(res); + let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], + span, PathSource::TraitItem(ns)); + return Some(PathResolution::with_unresolved_segments( + res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 + )); } let result = match self.resolve_path(&path, Some(ns), Some(span)) { @@ -2393,10 +2393,7 @@ impl<'a> Resolver<'a> { } _ => {} } - PathResolution { - base_def: Def::PrimTy(prim), - depth: path.len() - 1, - } + PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), PathResult::Failed(msg, false) => { @@ -2407,16 +2404,16 @@ impl<'a> Resolver<'a> { PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; - if path.len() > 1 && !global_by_default && result.base_def != Def::Err && + if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { - PathResult::NonModule(path_res) => path_res.base_def, + PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), } }; - if result.base_def == unqualified_result { + if result.base_def() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; self.session.add_lint(lint, id, span, "unnecessary qualification".to_string()); } @@ -2470,10 +2467,9 @@ impl<'a> Resolver<'a> { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { - return PathResult::NonModule(PathResolution { - base_def: def, - depth: path.len() - 1, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + def, path.len() - 1 + )); } _ => Err(if record_used.is_some() { Determined } else { Undetermined }), } @@ -2488,10 +2484,9 @@ impl<'a> Resolver<'a> { } else if def == Def::Err { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { - return PathResult::NonModule(PathResolution { - base_def: def, - depth: path.len() - i - 1, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + def, path.len() - i - 1 + )); } else { return PathResult::Failed(format!("Not a module `{}`", ident), is_last); } @@ -2500,10 +2495,9 @@ impl<'a> Resolver<'a> { Err(Determined) => { if let Some(module) = module { if opt_ns.is_some() && !module.is_normal() { - return PathResult::NonModule(PathResolution { - base_def: module.def().unwrap(), - depth: path.len() - i, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + module.def().unwrap(), path.len() - i + )); } } let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { @@ -2672,8 +2666,9 @@ impl<'a> Resolver<'a> { if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { // Look for a field with the same name in the current self_type. if let Some(resolution) = self.def_map.get(&node_id) { - match resolution.base_def { - Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => { + match resolution.base_def() { + Def::Struct(did) | Def::Union(did) + if resolution.unresolved_segments() == 0 => { if let Some(field_names) = self.field_names.get(&did) { if field_names.iter().any(|&field_name| name == field_name) { return Some(AssocSuggestion::Field); @@ -3057,7 +3052,6 @@ impl<'a> Resolver<'a> { fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { debug!("(recording def) recording {:?} for {}", resolution, node_id); - assert!(resolution.depth == 0 || resolution.base_def != Def::Err); if let Some(prev_res) = self.def_map.insert(node_id, resolution) { panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); } @@ -3071,7 +3065,8 @@ impl<'a> Resolver<'a> { ty::Visibility::Restricted(self.current_module.normal_ancestor_id) } ast::Visibility::Restricted { ref path, id } => { - let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def; + let def = self.smart_resolve_path(id, None, path, + PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public } else { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 880f5f388d0..8d563d20549 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -262,7 +262,7 @@ impl<'a> base::Resolver for Resolver<'a> { } let ext = match self.resolve_path(&path, Some(MacroNS), None) { - PathResult::NonModule(path_res) => match path_res.base_def { + PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => Ok(self.get_macro(def)), }, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 89f5c00e9c1..b5f948442b7 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1090,13 +1090,16 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, trait_ty: ty::Ty<'tcx>, impl_ty: ty::Ty<'tcx>, output: &mut Vec<TransItem<'tcx>>) { - assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); + assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() && + !impl_ty.needs_subst() && !impl_ty.has_escaping_regions()); if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty { if let Some(principal) = trait_ty.principal() { let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty); let param_substs = scx.tcx().intern_substs(&[]); + assert!(!poly_trait_ref.has_escaping_regions()); + // Walk all methods of the trait, including those of its supertraits let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); let methods = methods.filter_map(|method| method) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 5efdd129a32..799f502aadb 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -208,7 +208,8 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { _ => None, }) .collect(); - DepNode::TraitSelect(def_ids) + + DepNode::ProjectionCache { def_ids: def_ids } } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 19139301bb0..7e17ae5f1d3 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -287,8 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::Nop => {} + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant{ .. } => { - span_bug!(span, "SetDiscriminant should not appear in constants?"); + span_bug!(span, "{:?} should not appear in constants?", statement.kind); } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 38ee67796c6..7d4f542addb 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -16,7 +16,6 @@ use rustc::mir::tcx::LvalueTy; use rustc::mir; use middle::lang_items::ExchangeMallocFnLangItem; -use asm; use base; use builder::Builder; use callee::Callee; @@ -156,20 +155,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { bcx } - mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => { - let outputs = outputs.iter().map(|output| { - let lvalue = self.trans_lvalue(&bcx, output); - (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) - }).collect(); - - let input_vals = inputs.iter().map(|input| { - self.trans_operand(&bcx, input).immediate() - }).collect(); - - asm::trans_inline_asm(&bcx, asm, outputs, input_vals); - bcx - } - _ => { assert!(rvalue_creates_operand(rvalue)); let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); @@ -468,8 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { (bcx, operand) } mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => { + mir::Rvalue::Aggregate(..) => { bug!("cannot generate operand from rvalue {:?}", rvalue); } @@ -669,8 +653,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool { mir::Rvalue::Use(..) => true, mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => + mir::Rvalue::Aggregate(..) => false, } diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 48fc9720e4b..29a0648c8f8 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -11,6 +11,7 @@ use rustc::mir; use base; +use asm; use common; use builder::Builder; @@ -73,6 +74,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::StatementKind::StorageDead(ref lvalue) => { self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End) } + mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { + let outputs = outputs.iter().map(|output| { + let lvalue = self.trans_lvalue(&bcx, output); + (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) + }).collect(); + + let input_vals = inputs.iter().map(|input| { + self.trans_operand(&bcx, input).immediate() + }).collect(); + + asm::trans_inline_asm(&bcx, asm, outputs, input_vals); + bcx + } mir::StatementKind::Nop => bcx, } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index fb6d28448a0..ab1897101eb 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -918,7 +918,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + // FIXME: Self type is not always computed when we are here because type parameter + // bounds may affect Self type and have to be converted before it. + let trait_ref = if impl_def_id.is_local() { + tcx.impl_trait_refs.borrow().get(&impl_def_id).cloned().and_then(|x| x) + } else { + tcx.impl_trait_ref(impl_def_id) + }; + let trait_ref = if let Some(trait_ref) = trait_ref { + trait_ref + } else { + tcx.sess.span_err(span, "`Self` type is used before it's determined"); + return (tcx.types.err, Def::Err); + }; let trait_ref = if let Some(free_substs) = self.get_free_substs() { trait_ref.subst(tcx, free_substs) } else { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index ff9eaa012ba..2d90394025d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -309,17 +309,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let supplied_start = substs.params().len() + method_generics.regions.len(); + let supplied_start = substs.len() + method_generics.regions.len(); Substs::for_item(self.tcx, pick.item.def_id, |def, _| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.region_at(i) } else { self.region_var_for_def(self.span, def) } }, |def, cur_substs| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.type_at(i) } else if supplied_method_types.is_empty() { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 201a223c15f..fd29ff0be43 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1326,7 +1326,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } else { let substs = Substs::for_item(self.tcx, method, |def, _| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.region_at(i) } else { // In general, during probe we erase regions. See @@ -1335,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } }, |def, cur_substs| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.type_at(i) } else { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 28156dd616b..a2922270583 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let gcx = fcx.tcx.global_tcx(); let free_substs = fcx.parameter_environment.free_substs; - for (i, k) in free_substs.params().iter().enumerate() { + for (i, k) in free_substs.iter().enumerate() { let r = if let Some(r) = k.as_region() { r } else { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 1ef2cb4ed15..dd4f1ff4f5e 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -96,7 +96,9 @@ pub struct VarsOs { inner: os_imp::Env } /// /// While iterating, the returned iterator will panic if any key or value in the /// environment is not valid unicode. If this is not desired, consider using the -/// `env::vars_os` function. +/// [`env::vars_os`] function. +/// +/// [`env::vars_os`]: fn.vars_os.html /// /// # Examples /// @@ -171,9 +173,12 @@ impl fmt::Debug for VarsOs { /// Fetches the environment variable `key` from the current process. /// -/// The returned result is `Ok(s)` if the environment variable is present and is +/// The returned result is [`Ok(s)`] if the environment variable is present and is /// valid unicode. If the environment variable is not present, or it is not -/// valid unicode, then `Err` will be returned. +/// valid unicode, then [`Err`] will be returned. +/// +/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok +/// [`Err`]: ../result/enum.Result.html#variant.Err /// /// # Examples /// @@ -199,7 +204,9 @@ fn _var(key: &OsStr) -> Result<String, VarError> { } /// Fetches the environment variable `key` from the current process, returning -/// `None` if the variable isn't set. +/// [`None`] if the variable isn't set. +/// +/// [`None`]: ../option/enum.Option.html#variant.None /// /// # Examples /// diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index ba993751391..1e7394c0b09 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -316,7 +316,7 @@ impl Once { } // Once we've enqueued ourselves, wait in a loop. - // Aftewards reload the state and continue with what we + // Afterwards reload the state and continue with what we // were doing from before. while !node.signaled.load(Ordering::SeqCst) { thread::park(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 6992a17832e..e78928c2667 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -483,41 +483,21 @@ pub fn home_dir() -> Option<PathBuf> { target_os = "nacl", target_os = "emscripten")))] unsafe fn fallback() -> Option<OsString> { - #[cfg(not(target_os = "solaris"))] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec<c_char>) -> Option<()> { - let mut result = ptr::null_mut(); - match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity(), - &mut result) { - 0 if !result.is_null() => Some(()), - _ => None - } - } - - #[cfg(target_os = "solaris")] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec<c_char>) -> Option<()> { - // getpwuid_r semantics is different on Illumos/Solaris: - // http://illumos.org/man/3c/getpwuid_r - let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity()); - if result.is_null() { None } else { Some(()) } - } - let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; let mut buf = Vec::with_capacity(amt); let mut passwd: libc::passwd = mem::zeroed(); - - if getpwduid_r(libc::getuid(), &mut passwd, &mut buf).is_some() { - let ptr = passwd.pw_dir as *const _; - let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); - Some(OsStringExt::from_vec(bytes)) - } else { - None + let mut result = ptr::null_mut(); + match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(), + buf.capacity(), &mut result) { + 0 if !result.is_null() => { + let ptr = passwd.pw_dir as *const _; + let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); + Some(OsStringExt::from_vec(bytes)) + }, + _ => None, } } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 5166ddf8a21..66f09a7069c 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -28,8 +28,8 @@ use mem; /// # Initialization and Destruction /// /// Initialization is dynamically performed on the first call to `with()` -/// within a thread, and values support destructors which will be run when a -/// thread exits. +/// within a thread, and values that implement `Drop` get destructed when a +/// thread exits. Some caveats apply, which are explained below. /// /// # Examples /// diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index b74f4913858..ab36e9a2c2b 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2016-12-19 +2017-02-15 diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs new file mode 100644 index 00000000000..a56a5e85489 --- /dev/null +++ b/src/test/compile-fail/issue-39559.rs @@ -0,0 +1,31 @@ +// Copyright 2017 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. + +trait Dim { + fn dim() -> usize; +} + +enum Dim3 {} + +impl Dim for Dim3 { + fn dim() -> usize { + 3 + } +} + +pub struct Vector<T, D: Dim> { + entries: [T; D::dim()] + //~^ ERROR cannot use an outer type parameter in this context + //~| ERROR constant evaluation error +} + +fn main() { + let array: [usize; Dim3::dim()] = [0; Dim3::dim()]; +} diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs index 82037b6c9ed..04f98c7ab32 100644 --- a/src/test/compile-fail/resolve-self-in-impl.rs +++ b/src/test/compile-fail/resolve-self-in-impl.rs @@ -18,9 +18,12 @@ impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's deter impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined +impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined + //~^ ERROR `Self` type is used before it's determined impl Tr for Self {} //~ ERROR `Self` type is used before it's determined impl Tr for S<Self> {} //~ ERROR `Self` type is used before it's determined impl Self {} //~ ERROR `Self` type is used before it's determined impl S<Self> {} //~ ERROR `Self` type is used before it's determined +impl Tr<Self::Assoc> for S {} //~ ERROR `Self` type is used before it's determined fn main() {} diff --git a/src/test/run-pass/issue-39292.rs b/src/test/run-pass/issue-39292.rs new file mode 100644 index 00000000000..dc2b21f3470 --- /dev/null +++ b/src/test/run-pass/issue-39292.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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. + +// Regression test for issue #39292. The object vtable was being +// incorrectly left with a null pointer. + +trait Foo<T> { + fn print<'a>(&'a self) where T: 'a { println!("foo"); } +} + +impl<'a> Foo<&'a ()> for () { } + +trait Bar: for<'a> Foo<&'a ()> { } + +impl Bar for () {} + +fn main() { + (&() as &Bar).print(); // Segfault +} |
