Run the `run-make` tests last, so more tests run on Windows when `make` is unavailable
[[package]]
name = "rls"
-version = "0.124.0"
+version = "0.125.0"
dependencies = [
"cargo 0.26.0",
"env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.3.6",
+ "rustfmt-nightly 0.3.8",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_data_structures"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_errors"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-serialize"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-ap-syntax"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
-version = "12.0.0"
+version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustfmt-nightly"
-version = "0.3.6"
+version = "0.3.8"
dependencies = [
"cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85cfb9dde19e313da3e47738008f8a472e470cc42d910b71595a9238494701f2"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
-"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e"
-"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc"
-"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0"
-"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604"
-"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c"
-"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b"
+"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
+"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
+"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
+"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
+"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
+"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
p
}
-#[lang = "exchange_free"]
-unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
- libc::free(ptr as *mut libc::c_void)
-}
-
#[lang = "box_free"]
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
- deallocate(ptr as *mut u8, ::core::mem::size_of_val(&*ptr), ::core::mem::align_of_val(&*ptr));
+ libc::free(ptr as *mut libc::c_void)
}
#[start]
-fn main(argc: isize, argv: *const *const u8) -> isize {
- let x = box 1;
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _x = box 1;
0
}
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } }
-# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
-# #[no_mangle] pub extern fn rust_eh_register_frames () {}
-# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
+#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
+#[no_mangle] pub extern fn rust_eh_register_frames () {}
+#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
```
Note the use of `abort`: the `exchange_malloc` lang item is assumed to
Lang items are loaded lazily by the compiler; e.g. if one never uses
`Box` then there is no need to define functions for `exchange_malloc`
-and `exchange_free`. `rustc` will emit an error when an item is needed
+and `box_free`. `rustc` will emit an error when an item is needed
but not found in the current crate or any that it depends on.
Most lang items are defined by `libcore`, but if you're trying to build
- `phantom_data`: `libcore/marker.rs`
- `freeze`: `libcore/marker.rs`
- `debug_trait`: `libcore/fmt/mod.rs`
- - `non_zero`: `libcore/nonzero.rs`
\ No newline at end of file
+ - `non_zero`: `libcore/nonzero.rs`
+++ /dev/null
-# `match_beginning_vert`
-
-The tracking issue for this feature is [#44101].
-
-With this feature enabled, you are allowed to add a '|' to the beginning of a
-match arm:
-
-```rust
-#![feature(match_beginning_vert)]
-
-enum Foo { A, B, C }
-
-fn main() {
- let x = Foo::A;
- match x {
- | Foo::A
- | Foo::B => println!("AB"),
- | Foo::C => println!("C"),
- }
-}
-```
-
-[#44101]: https://github.com/rust-lang/rust/issues/44101
\ No newline at end of file
/// ptr::copy_nonoverlapping(y, x, 1);
/// ptr::copy_nonoverlapping(&t, y, 1);
///
- /// // y and t now point to the same thing, but we need to completely forget `tmp`
+ /// // y and t now point to the same thing, but we need to completely forget `t`
/// // because it's no longer relevant.
/// mem::forget(t);
/// }
/// Type | size_of::\<Type>()
/// ---- | ---------------
/// () | 0
+/// bool | 1
/// u8 | 1
/// u16 | 2
/// u32 | 4
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f32 {
- self * (180.0f32 / consts::PI)
+ // Use a constant for better precision.
+ const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
+ self * PIS_IN_180
}
/// Converts to radians, assuming the number is in degrees.
/// Converts to degrees, assuming the number is in radians.
#[inline]
fn to_degrees(self) -> f64 {
+ // The division here is correctly rounded with respect to the true
+ // value of 180/π. (This differs from f32, where a constant must be
+ // used to ensure a correctly rounded result.)
self * (180.0f64 / consts::PI)
}
ty::ReEarlyBound(_) |
ty::ReFree(_) => {
let scope = region.free_region_binding_scope(self);
- let prefix = match *region {
- ty::ReEarlyBound(ref br) => {
- format!("the lifetime {} as defined on", br.name)
- }
- ty::ReFree(ref fr) => {
- match fr.bound_region {
- ty::BrAnon(idx) => {
- format!("the anonymous lifetime #{} defined on", idx + 1)
- }
- ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
- _ => {
- format!("the lifetime {} as defined on",
- fr.bound_region)
- }
- }
- }
- _ => bug!()
- };
-
let node = self.hir.as_local_node_id(scope)
.unwrap_or(DUMMY_NODE_ID);
let unknown;
&unknown
}
};
- let (msg, opt_span) = explain_span(self, tag, self.hir.span(node));
+ let (prefix, span) = match *region {
+ ty::ReEarlyBound(ref br) => {
+ (format!("the lifetime {} as defined on", br.name),
+ self.sess.codemap().def_span(self.hir.span(node)))
+ }
+ ty::ReFree(ref fr) => {
+ match fr.bound_region {
+ ty::BrAnon(idx) => {
+ (format!("the anonymous lifetime #{} defined on", idx + 1),
+ self.hir.span(node))
+ }
+ ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(),
+ self.hir.span(node)),
+ _ => (format!("the lifetime {} as defined on", fr.bound_region),
+ self.sess.codemap().def_span(self.hir.span(node))),
+ }
+ }
+ _ => bug!()
+ };
+ let (msg, opt_span) = explain_span(self, tag, span);
(format!("{} {}", prefix, msg), opt_span)
}
}
};
- let span = cause.span;
+ let span = cause.span(&self.tcx);
diag.span_label(span, terr.to_string());
if let Some((sp, msg)) = secondary_span {
"did you mean `{}(/* fields */)`?",
self.tcx.item_path_str(def_id)
);
- diag.span_label(cause.span, message);
+ diag.span_label(span, message);
}
}
}
trace,
terr);
- let span = trace.cause.span;
+ let span = trace.cause.span(&self.tcx);
let failure_code = trace.cause.as_failure_code(terr);
let mut diag = match failure_code {
FailureCode::Error0317(failure_str) => {
sup_region,
"...");
+ match (&sup_origin, &sub_origin) {
+ (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => {
+ if let (Some((sup_expected, sup_found)),
+ Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values),
+ self.values_str(&sub_trace.values)) {
+ if sub_expected == sup_expected && sub_found == sup_found {
+ self.tcx.note_and_explain_region(
+ region_scope_tree,
+ &mut err,
+ "...but the lifetime must also be valid for ",
+ sub_region,
+ "...",
+ );
+ err.note(&format!("...so that the {}:\nexpected {}\n found {}",
+ sup_trace.cause.as_requirement_str(),
+ sup_expected.content(),
+ sup_found.content()));
+ err.emit();
+ return;
+ }
+ }
+ }
+ _ => {}
+ }
+
self.note_region_origin(&mut err, &sup_origin);
self.tcx.note_and_explain_region(region_scope_tree, &mut err,
if let Some((expected, found)) = self.values_str(&trace.values) {
let expected = expected.content();
let found = found.content();
- // FIXME: do we want a "the" here?
- err.span_note(trace.cause.span,
- &format!("...so that {} (expected {}, found {})",
- trace.cause.as_requirement_str(),
- expected,
- found));
+ err.note(&format!("...so that the {}:\nexpected {}\n found {}",
+ trace.cause.as_requirement_str(),
+ expected,
+ found));
} else {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
"raw pointer to an inference variable"
}
+declare_lint! {
+ pub ELIDED_LIFETIME_IN_PATH,
+ Allow,
+ "hidden lifetime parameters are deprecated, try `Foo<'_>`"
+}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
UNUSED_MUT,
COERCE_NEVER,
SINGLE_USE_LIFETIME,
- TYVAR_BEHIND_RAW_POINTER
+ TYVAR_BEHIND_RAW_POINTER,
+ ELIDED_LIFETIME_IN_PATH
+
)
}
}
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- (self.tcx, self.param_env.reveal_all()).layout_of(ty)
+ self.tcx.layout_of(self.param_env.and(ty))
}
}
}
fn visit_pat(&mut self, pat: &'tcx Pat) {
+ intravisit::walk_pat(self, pat);
+
self.expr_and_pat_count += 1;
- intravisit::walk_pat(self, pat);
+ if pat.id == self.id {
+ self.result = Some(self.expr_and_pat_count);
+ }
}
fn visit_expr(&mut self, expr: &'tcx Expr) {
/// Checks whether the given scope contains a `yield`. If so,
/// returns `Some((span, expr_count))` with the span of a yield we found and
- /// the number of expressions appearing before the `yield` in the body.
+ /// the number of expressions and patterns appearing before the `yield` in the body + 1.
+ /// If there a are multiple yields in a scope, the one with the highest number is returned.
pub fn yield_in_scope(&self, scope: Scope) -> Option<(Span, usize)> {
self.yield_in_scope.get(&scope).cloned()
}
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if lifetime_ref.is_elided() {
- self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref));
+ self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false);
return;
}
if lifetime_ref.is_static() {
}
if params.lifetimes.iter().all(|l| l.is_elided()) {
- self.resolve_elided_lifetimes(¶ms.lifetimes);
+ self.resolve_elided_lifetimes(¶ms.lifetimes, true);
} else {
for l in ¶ms.lifetimes {
self.visit_lifetime(l);
}
}
- fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime]) {
+ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) {
if lifetime_refs.is_empty() {
return;
}
let span = lifetime_refs[0].span;
+ let id = lifetime_refs[0].id;
let mut late_depth = 0;
let mut scope = self.scope;
+ if deprecated {
+ self.tcx
+ .struct_span_lint_node(
+ lint::builtin::ELIDED_LIFETIME_IN_PATH,
+ id,
+ span,
+ &format!("hidden lifetime parameters are deprecated, try `Foo<'_>`"))
+ .emit();
+ }
let error = loop {
match *scope {
// Do not assign any resolution, it will be inferred.
err.note("the return type of a function must have a \
statically known size");
}
+ ObligationCauseCode::SizedYieldType => {
+ err.note("the yield type of a generator must have a \
+ statically known size");
+ }
ObligationCauseCode::AssignmentLhsSized => {
err.note("the left-hand-side of an assignment must have a statically known size");
}
pub code: ObligationCauseCode<'tcx>
}
+impl<'tcx> ObligationCause<'tcx> {
+ pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
+ match self.code {
+ ObligationCauseCode::CompareImplMethodObligation { .. } |
+ ObligationCauseCode::MainFunctionType |
+ ObligationCauseCode::StartFunctionType => {
+ tcx.sess.codemap().def_span(self.span)
+ }
+ _ => self.span,
+ }
+ }
+}
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from span.
VariableType(ast::NodeId),
/// Return type must be Sized
SizedReturnType,
+ /// Yield type must be Sized
+ SizedYieldType,
/// [T,..n] --> T must be Copy
RepeatVec,
super::VariableType(id) => Some(super::VariableType(id)),
super::ReturnType(id) => Some(super::ReturnType(id)),
super::SizedReturnType => Some(super::SizedReturnType),
+ super::SizedYieldType => Some(super::SizedYieldType),
super::RepeatVec => Some(super::RepeatVec),
super::FieldSized(item) => Some(super::FieldSized(item)),
super::ConstSized => Some(super::ConstSized),
super::VariableType(_) |
super::ReturnType(_) |
super::SizedReturnType |
+ super::SizedYieldType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized(_) |
super::VariableType(_) |
super::ReturnType(_) |
super::SizedReturnType |
+ super::SizedYieldType |
super::ReturnNoExpression |
super::RepeatVec |
super::FieldSized(_) |
}
tcx.layout_depth.set(depth+1);
- let layout = LayoutDetails::compute_uncached(tcx, param_env, ty);
+ let cx = LayoutCx { tcx, param_env };
+ let layout = cx.layout_raw_uncached(ty);
tcx.layout_depth.set(depth);
layout
};
}
-impl<'a, 'tcx> LayoutDetails {
- fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ty: Ty<'tcx>)
- -> Result<&'tcx Self, LayoutError<'tcx>> {
- let cx = (tcx, param_env);
- let dl = cx.data_layout();
+#[derive(Copy, Clone)]
+pub struct LayoutCx<'tcx, C> {
+ pub tcx: C,
+ pub param_env: ty::ParamEnv<'tcx>
+}
+
+impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
+ fn layout_raw_uncached(self, ty: Ty<'tcx>)
+ -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> {
+ let tcx = self.tcx;
+ let param_env = self.param_env;
+ let dl = self.data_layout();
let scalar_unit = |value: Primitive| {
let bits = value.size(dl).bits();
assert!(bits <= 128);
}
};
let scalar = |value: Primitive| {
- tcx.intern_layout(LayoutDetails::scalar(cx, scalar_unit(value)))
+ tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value)))
};
let scalar_pair = |a: Scalar, b: Scalar| {
let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align);
Ok(match ty.sty {
// Basic scalars.
ty::TyBool => {
- tcx.intern_layout(LayoutDetails::scalar(cx, Scalar {
+ tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
value: Int(I8, false),
valid_range: 0..=1
}))
}
ty::TyChar => {
- tcx.intern_layout(LayoutDetails::scalar(cx, Scalar {
+ tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
value: Int(I32, false),
valid_range: 0..=0x10FFFF
}))
ty::TyFnPtr(_) => {
let mut ptr = scalar_unit(Pointer);
ptr.valid_range.start = 1;
- tcx.intern_layout(LayoutDetails::scalar(cx, ptr))
+ tcx.intern_layout(LayoutDetails::scalar(self, ptr))
}
// The never type.
let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
if pointee.is_sized(tcx, param_env, DUMMY_SP) {
- return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr)));
+ return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
}
let unsized_part = tcx.struct_tail(pointee);
let metadata = match unsized_part.sty {
ty::TyForeign(..) => {
- return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr)));
+ return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
}
ty::TySlice(_) | ty::TyStr => {
scalar_unit(Int(dl.ptr_sized_integer(), false))
}
}
- let element = cx.layout_of(element)?;
+ let element = self.layout_of(element)?;
let count = count.val.to_const_int().unwrap().to_u64().unwrap();
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;
})
}
ty::TySlice(element) => {
- let element = cx.layout_of(element)?;
+ let element = self.layout_of(element)?;
tcx.intern_layout(LayoutDetails {
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Array {
// Tuples, generators and closures.
ty::TyGenerator(def_id, ref substs, _) => {
let tys = substs.field_tys(def_id, tcx);
- univariant(&tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized)?
}
ty::TyClosure(def_id, ref substs) => {
let tys = substs.upvar_tys(def_id, tcx);
- univariant(&tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized)?
}
StructKind::MaybeUnsized
};
- univariant(&tys.iter().map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(), kind)?
}
// SIMD vector types.
ty::TyAdt(def, ..) if def.repr.simd() => {
- let element = cx.layout_of(ty.simd_type(tcx))?;
+ let element = self.layout_of(ty.simd_type(tcx))?;
let count = ty.simd_size(tcx) as u64;
assert!(count > 0);
let scalar = match element.abi {
// Cache the field layouts.
let variants = def.variants.iter().map(|v| {
v.fields.iter().map(|field| {
- cx.layout_of(field.ty(tcx, substs))
+ self.layout_of(field.ty(tcx, substs))
}).collect::<Result<Vec<_>, _>>()
}).collect::<Result<Vec<_>, _>>()?;
let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
st.variants = Variants::Single { index: v };
// Exclude 0 from the range of a newtype ABI NonZero<T>.
- if Some(def.did) == cx.tcx().lang_items().non_zero() {
+ if Some(def.did) == self.tcx.lang_items().non_zero() {
match st.abi {
Abi::Scalar(ref mut scalar) |
Abi::ScalarPair(ref mut scalar, _) => {
let count = (niche_variants.end - niche_variants.start + 1) as u128;
for (field_index, field) in variants[i].iter().enumerate() {
let (offset, niche, niche_start) =
- match field.find_niche(cx, count)? {
+ match field.find_niche(self, count)? {
Some(niche) => niche,
None => continue
};
/// This is invoked by the `layout_raw` query to record the final
/// layout of each type.
#[inline]
- fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- ty: Ty<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- layout: TyLayout<'tcx>) {
+ fn record_layout_for_printing(self, layout: TyLayout<'tcx>) {
// If we are running with `-Zprint-type-sizes`, record layouts for
// dumping later. Ignore layouts that are done with non-empty
// environments or non-monomorphic layouts, as the user only wants
// to see the stuff resulting from the final trans session.
if
- !tcx.sess.opts.debugging_opts.print_type_sizes ||
- ty.has_param_types() ||
- ty.has_self_ty() ||
- !param_env.caller_bounds.is_empty()
+ !self.tcx.sess.opts.debugging_opts.print_type_sizes ||
+ layout.ty.has_param_types() ||
+ layout.ty.has_self_ty() ||
+ !self.param_env.caller_bounds.is_empty()
{
return;
}
- Self::record_layout_for_printing_outlined(tcx, ty, param_env, layout)
+ self.record_layout_for_printing_outlined(layout)
}
- fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- ty: Ty<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- layout: TyLayout<'tcx>) {
- let cx = (tcx, param_env);
+ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
// (delay format until we actually need it)
let record = |kind, opt_discr_size, variants| {
- let type_desc = format!("{:?}", ty);
- tcx.sess.code_stats.borrow_mut().record_type_size(kind,
- type_desc,
- layout.align,
- layout.size,
- opt_discr_size,
- variants);
+ let type_desc = format!("{:?}", layout.ty);
+ self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
+ type_desc,
+ layout.align,
+ layout.size,
+ opt_discr_size,
+ variants);
};
- let adt_def = match ty.sty {
+ let adt_def = match layout.ty.sty {
ty::TyAdt(ref adt_def, _) => {
- debug!("print-type-size t: `{:?}` process adt", ty);
+ debug!("print-type-size t: `{:?}` process adt", layout.ty);
adt_def
}
ty::TyClosure(..) => {
- debug!("print-type-size t: `{:?}` record closure", ty);
+ debug!("print-type-size t: `{:?}` record closure", layout.ty);
record(DataTypeKind::Closure, None, vec![]);
return;
}
_ => {
- debug!("print-type-size t: `{:?}` skip non-nominal", ty);
+ debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
return;
}
};
layout: TyLayout<'tcx>| {
let mut min_size = Size::from_bytes(0);
let field_info: Vec<_> = flds.iter().enumerate().map(|(i, &name)| {
- match layout.field(cx, i) {
+ match layout.field(self, i) {
Err(err) => {
bug!("no layout found for field {}: `{:?}`", name, err);
}
Variants::NicheFilling { .. } |
Variants::Tagged { .. } => {
debug!("print-type-size `{:#?}` adt general variants def {}",
- ty, adt_def.variants.len());
+ layout.ty, adt_def.variants.len());
let variant_infos: Vec<_> =
adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
let fields: Vec<_> =
variant_def.fields.iter().map(|f| f.name).collect();
build_variant_info(Some(variant_def.name),
&fields,
- layout.for_variant(cx, i))
+ layout.for_variant(self, i))
})
.collect();
record(adt_kind.into(), match layout.variants {
- Variants::Tagged { ref discr, .. } => Some(discr.value.size(tcx)),
+ Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)),
_ => None
}, variant_infos);
}
assert!(!ty.has_infer_types());
// First try computing a static layout.
- let err = match (tcx, param_env).layout_of(ty) {
+ let err = match tcx.layout_of(param_env.and(ty)) {
Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size));
}
}
}
-impl<'a, 'gcx, 'tcx, T: Copy> HasDataLayout for (TyCtxt<'a, 'gcx, 'tcx>, T) {
+impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
fn data_layout(&self) -> &TargetDataLayout {
- self.0.data_layout()
+ self.tcx.data_layout()
}
}
-impl<'a, 'gcx, 'tcx, T: Copy> HasTyCtxt<'gcx> for (TyCtxt<'a, 'gcx, 'tcx>, T) {
+impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
- self.0.tcx()
+ self.tcx.tcx()
}
}
fn layout_of(self, ty: T) -> Self::TyLayout;
}
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
- #[inline]
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- let (tcx, param_env) = self;
-
- let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
- let details = tcx.layout_raw(param_env.reveal_all().and(ty))?;
+ let param_env = self.param_env.reveal_all();
+ let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
+ let details = self.tcx.layout_raw(param_env.and(ty))?;
let layout = TyLayout {
ty,
details
// completed, to avoid problems around recursive structures
// and the like. (Admitedly, I wasn't able to reproduce a problem
// here, but it seems like the right thing to do. -nmatsakis)
- LayoutDetails::record_layout_for_printing(tcx, ty, param_env, layout);
+ self.record_layout_for_printing(layout);
Ok(layout)
}
}
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
- ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
- #[inline]
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- let (tcx_at, param_env) = self;
-
- let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
- let details = tcx_at.layout_raw(param_env.reveal_all().and(ty))?;
+ let param_env = self.param_env.reveal_all();
+ let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
+ let details = self.tcx.layout_raw(param_env.reveal_all().and(ty))?;
let layout = TyLayout {
ty,
details
// completed, to avoid problems around recursive structures
// and the like. (Admitedly, I wasn't able to reproduce a problem
// here, but it seems like the right thing to do. -nmatsakis)
- LayoutDetails::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
+ let cx = LayoutCx {
+ tcx: *self.tcx,
+ param_env: self.param_env
+ };
+ cx.record_layout_for_printing(layout);
Ok(layout)
}
}
+// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+ /// Computes the layout of a type. Note that this implicitly
+ /// executes in "reveal all" mode.
+ #[inline]
+ pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
+ let cx = LayoutCx {
+ tcx: self,
+ param_env: param_env_and_ty.param_env
+ };
+ cx.layout_of(param_env_and_ty.value)
+ }
+}
+
+impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> {
+ /// Computes the layout of a type. Note that this implicitly
+ /// executes in "reveal all" mode.
+ #[inline]
+ pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
+ let cx = LayoutCx {
+ tcx: self,
+ param_env: param_env_and_ty.param_env
+ };
+ cx.layout_of(param_env_and_ty.value)
+ }
+}
+
impl<'a, 'tcx> TyLayout<'tcx> {
pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
state.map(move |d| d.ty.subst(tcx, self.substs))
}
+ /// This is the types of the fields of a generate which
+ /// is available before the generator transformation.
+ /// It includes the upvars and the state discriminant which is u32.
+ pub fn pre_transforms_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
+ impl Iterator<Item=Ty<'tcx>> + 'a
+ {
+ self.upvar_tys(def_id, tcx).chain(iter::once(tcx.types.u32))
+ }
+
/// This is the types of all the fields stored in a generator.
/// It includes the upvars, state types and the state discriminant which is u32.
pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
impl Iterator<Item=Ty<'tcx>> + 'a
{
- let upvars = self.upvar_tys(def_id, tcx);
- let state = self.state_tys(def_id, tcx);
- upvars.chain(iter::once(tcx.types.u32)).chain(state)
+ self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx))
}
}
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::LayoutOf;
use rustc::ty::util::IntTypeExt;
use rustc::ty::subst::{Substs, Subst};
use rustc::util::common::ErrorReported;
if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic {
let layout_of = |ty: Ty<'tcx>| {
let ty = tcx.erase_regions(&ty);
- (tcx.at(e.span), cx.param_env).layout_of(ty).map_err(|err| {
+ tcx.at(e.span).layout_of(cx.param_env.and(ty)).map_err(|err| {
ConstEvalErr { span: e.span, kind: LayoutError(err) }
})
};
// Code for annotating snippets.
-use syntax_pos::{Span, FileMap};
-use CodeMapper;
-use std::rc::Rc;
use Level;
-#[derive(Clone)]
-pub struct SnippetData {
- codemap: Rc<CodeMapper>,
- files: Vec<FileInfo>,
-}
-
-#[derive(Clone)]
-pub struct FileInfo {
- file: Rc<FileMap>,
-
- /// The "primary file", if any, gets a `-->` marker instead of
- /// `>>>`, and has a line-number/column printed and not just a
- /// filename (other files are not guaranteed to have line numbers
- /// or columns). It appears first in the listing. It is known to
- /// contain at least one primary span, though primary spans (which
- /// are designated with `^^^`) may also occur in other files.
- primary_span: Option<Span>,
-
- lines: Vec<Line>,
-}
-
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line {
pub line_index: usize,
// repr(transparent) types are allowed to have arbitrary ZSTs, not just
// PhantomData -- skip checking all ZST fields
if def.repr.transparent() {
- let is_zst = (cx, cx.param_env(field.did))
- .layout_of(field_ty)
+ let is_zst = cx
+ .layout_of(cx.param_env(field.did).and(field_ty))
.map(|layout| layout.is_zst())
.unwrap_or(false);
if is_zst {
Assign(_, ref value) => (value, "assigned value", false),
AssignOp(.., ref value) => (value, "assigned value", false),
InPlace(_, ref value) => (value, "emplacement value", false),
- Call(_, ref args) => {
- for arg in args {
- self.check_unused_parens_core(cx, arg, "function argument", false)
+ // either function/method call, or something this lint doesn't care about
+ ref call_or_other => {
+ let args_to_check;
+ let call_kind;
+ match *call_or_other {
+ Call(_, ref args) => {
+ call_kind = "function";
+ args_to_check = &args[..];
+ },
+ MethodCall(_, ref args) => {
+ call_kind = "method";
+ // first "argument" is self (which sometimes needs parens)
+ args_to_check = &args[1..];
+ }
+ // actual catch-all arm
+ _ => { return; }
}
- return;
- },
- MethodCall(_, ref args) => {
- for arg in &args[1..] { // first "argument" is self (which sometimes needs parens)
- self.check_unused_parens_core(cx, arg, "method argument", false)
+ // Don't lint if this is a nested macro expansion: otherwise, the lint could
+ // trigger in situations that macro authors shouldn't have to care about, e.g.,
+ // when a parenthesized token tree matched in one macro expansion is matched as
+ // an expression in another and used as a fn/method argument (Issue #47775)
+ if e.span.ctxt().outer().expn_info()
+ .map_or(false, |info| info.call_site.ctxt().outer()
+ .expn_info().is_some()) {
+ return;
+ }
+ let msg = format!("{} argument", call_kind);
+ for arg in args_to_check {
+ self.check_unused_parens_core(cx, arg, &msg, false);
}
return;
}
- _ => return,
};
self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
}
self.describe_field_from_ty(&tnm.ty, field)
}
ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field),
- ty::TyClosure(closure_def_id, _) => {
+ ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
// Convert the def-id into a node-id. node-ids are only valid for
// the local code in the current crate, so this returns an `Option` in case
// the closure comes from another crate. But in that case we wouldn't
// be borrowck'ing it, so we can just unwrap:
- let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
+ let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
let freevar = self.tcx.with_freevars(node_id, |fv| fv[field.index()]);
self.tcx.hir.name(freevar.var_id()).to_string()
}
};
if let PlaceContext::Copy = context {
- let ty = place_ty.to_ty(self.tcx());
- if self.cx
- .infcx
- .type_moves_by_default(self.cx.param_env, ty, DUMMY_SP)
- {
- span_mirbug!(self, place, "attempted copy of non-Copy type ({:?})", ty);
- }
+ let tcx = self.tcx();
+ let trait_ref = ty::TraitRef {
+ def_id: tcx.lang_items().copy_trait().unwrap(),
+ substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
+ };
+
+ // In order to have a Copy operand, the type T of the value must be Copy. Note that we
+ // prove that T: Copy, rather than using the type_moves_by_default test. This is
+ // important because type_moves_by_default ignores the resulting region obligations and
+ // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored
+ // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds
+ // fully apply: in effect, the rule is that if a value of some type could implement
+ // Copy, then it must.
+ self.cx.prove_trait_ref(trait_ref, location);
}
place_ty
}
}
}
ty::TyGenerator(def_id, substs, _) => {
- // Try upvars first. `field_tys` requires final optimized MIR.
- if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field.index()) {
+ // Try pre-transform fields first (upvars and current state)
+ if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
return Ok(ty);
}
+ // Then try `field_tys` which contains all the fields, but it
+ // requires the final optimized MIR.
return match substs.field_tys(def_id, tcx).nth(field.index()) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
- field_count: substs.field_tys(def_id, tcx).count() + 1,
+ field_count: substs.field_tys(def_id, tcx).count(),
}),
};
}
}
}
AggregateKind::Generator(def_id, substs, _) => {
- if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field_index) {
+ // Try pre-transform fields first (upvars and current state)
+ if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field_index) {
Ok(ty)
} else {
+ // Then try `field_tys` which contains all the fields, but it
+ // requires the final optimized MIR.
match substs.field_tys(def_id, tcx).nth(field_index) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
- field_count: substs.field_tys(def_id, tcx).count() + 1,
+ field_count: substs.field_tys(def_id, tcx).count(),
}),
}
}
--- /dev/null
+// 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.
+
+pub use super::*;
+
+use rustc::mir::*;
+use rustc::mir::visit::Visitor;
+use dataflow::BitDenotation;
+
+/// This calculates if any part of a MIR local could have previously been borrowed.
+/// This means that once a local has been borrowed, its bit will always be set
+/// from that point and onwards, even if the borrow ends. You could also think of this
+/// as computing the lifetimes of infinite borrows.
+/// This is used to compute which locals are live during a yield expression for
+/// immovable generators.
+#[derive(Copy, Clone)]
+pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
+ mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
+ pub fn new(mir: &'a Mir<'tcx>)
+ -> Self {
+ HaveBeenBorrowedLocals { mir: mir }
+ }
+
+ pub fn mir(&self) -> &Mir<'tcx> {
+ self.mir
+ }
+}
+
+impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
+ type Idx = Local;
+ fn name() -> &'static str { "has_been_borrowed_locals" }
+ fn bits_per_block(&self) -> usize {
+ self.mir.local_decls.len()
+ }
+
+ fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
+ // Nothing is borrowed on function entry
+ }
+
+ fn statement_effect(&self,
+ sets: &mut BlockSets<Local>,
+ loc: Location) {
+ BorrowedLocalsVisitor {
+ sets,
+ }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
+ }
+
+ fn terminator_effect(&self,
+ sets: &mut BlockSets<Local>,
+ loc: Location) {
+ BorrowedLocalsVisitor {
+ sets,
+ }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc);
+ }
+
+ fn propagate_call_return(&self,
+ _in_out: &mut IdxSet<Local>,
+ _call_bb: mir::BasicBlock,
+ _dest_bb: mir::BasicBlock,
+ _dest_place: &mir::Place) {
+ // Nothing to do when a call returns successfully
+ }
+}
+
+impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
+ #[inline]
+ fn join(&self, pred1: usize, pred2: usize) -> usize {
+ pred1 | pred2 // "maybe" means we union effects of both preds
+ }
+}
+
+impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
+ #[inline]
+ fn bottom_value() -> bool {
+ false // bottom = unborrowed
+ }
+}
+
+struct BorrowedLocalsVisitor<'b, 'c: 'b> {
+ sets: &'b mut BlockSets<'c, Local>,
+}
+
+fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
+ match *place {
+ Place::Local(l) => Some(l),
+ Place::Static(..) => None,
+ Place::Projection(ref proj) => {
+ match proj.elem {
+ ProjectionElem::Deref => None,
+ _ => find_local(&proj.base)
+ }
+ }
+ }
+}
+
+impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
+ fn visit_rvalue(&mut self,
+ rvalue: &Rvalue<'tcx>,
+ location: Location) {
+ if let Rvalue::Ref(_, _, ref place) = *rvalue {
+ if let Some(local) = find_local(place) {
+ self.sets.gen(&local);
+ }
+ }
+
+ self.super_rvalue(rvalue, location)
+ }
+}
// Issue #46746: Two-phase borrows handles
// stmts of form `Tmp = &mut Borrow` ...
match lhs {
- Place::Local(..) => {} // okay
- Place::Static(..) => unreachable!(), // (filtered by is_unsafe_place)
+ Place::Local(..) | Place::Static(..) => {} // okay
Place::Projection(..) => {
// ... can assign into projections,
// e.g. `box (&mut _)`. Current
pub use self::storage_liveness::*;
+mod borrowed_locals;
+
+pub use self::borrowed_locals::*;
+
#[allow(dead_code)]
pub(super) mod borrows;
pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
pub use self::impls::EverInitializedPlaces;
pub use self::impls::borrows::{Borrows, BorrowData};
+pub use self::impls::HaveBeenBorrowedLocals;
pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex};
pub use self::at_location::{FlowAtLocation, FlowsAtLocation};
pub(crate) use self::drop_flag_effects::*;
type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- (self.tcx, self.param_env).layout_of(ty)
+ self.tcx.layout_of(self.param_env.and(ty))
.map_err(|layout| EvalErrorKind::Layout(layout).into())
}
}
use transform::{MirPass, MirSource};
use transform::simplify;
use transform::no_landing_pads::no_landing_pads;
-use dataflow::{do_dataflow, DebugFormatted, MaybeStorageLive, state_for_location};
+use dataflow::{do_dataflow, DebugFormatted, state_for_location};
+use dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
pub struct StateTransform;
HashMap<BasicBlock, liveness::LocalSet>) {
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
- let analysis = MaybeStorageLive::new(mir);
+
+ // Calculate when MIR locals have live storage. This gives us an upper bound of their
+ // lifetimes.
+ let storage_live_analysis = MaybeStorageLive::new(mir);
let storage_live =
- do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+ do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, storage_live_analysis,
|bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
+ // Find the MIR locals which do not use StorageLive/StorageDead statements.
+ // The storage of these locals are always live.
let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
ignored.visit_mir(mir);
- let mut borrowed_locals = BorrowedLocals(IdxSetBuf::new_empty(mir.local_decls.len()));
- borrowed_locals.visit_mir(mir);
+ // Calculate the MIR locals which have been previously
+ // borrowed (even if they are still active).
+ // This is only used for immovable generators.
+ let borrowed_locals = if !movable {
+ let analysis = HaveBeenBorrowedLocals::new(mir);
+ let result =
+ do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+ |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
+ Some((analysis, result))
+ } else {
+ None
+ };
+ // Calculate the liveness of MIR locals ignoring borrows.
let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
let mut liveness = liveness::liveness_of_locals(mir, LivenessMode {
include_regular_use: true,
statement_index: data.statements.len(),
};
- let storage_liveness = state_for_location(loc, &analysis, &storage_live, mir);
+ if let Some((ref analysis, ref result)) = borrowed_locals {
+ let borrowed_locals = state_for_location(loc,
+ analysis,
+ result,
+ mir);
+ // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
+ // This is correct for movable generators since borrows cannot live across
+ // suspension points. However for immovable generators we need to account for
+ // borrows, so we conseratively assume that all borrowed locals live forever.
+ // To do this we just union our `liveness` result with `borrowed_locals`, which
+ // contains all the locals which has been borrowed before this suspension point.
+ // If a borrow is converted to a raw reference, we must also assume that it lives
+ // forever. Note that the final liveness is still bounded by the storage liveness
+ // of the local, which happens using the `intersect` operation below.
+ liveness.outs[block].union(&borrowed_locals);
+ }
+
+ let mut storage_liveness = state_for_location(loc,
+ &storage_live_analysis,
+ &storage_live,
+ mir);
+ // Store the storage liveness for later use so we can restore the state
+ // after a suspension point
storage_liveness_map.insert(block, storage_liveness.clone());
- let mut live_locals = storage_liveness;
-
// Mark locals without storage statements as always having live storage
- live_locals.union(&ignored.0);
+ storage_liveness.union(&ignored.0);
- if !movable {
- // For immovable generators we consider borrowed locals to always be live.
- // This effectively makes those locals use just the storage liveness.
- liveness.outs[block].union(&borrowed_locals.0);
- }
+ // Locals live are live at this point only if they are used across
+ // suspension points (the `liveness` variable)
+ // and their storage is live (the `storage_liveness` variable)
+ storage_liveness.intersect(&liveness.outs[block]);
- // Locals live are live at this point only if they are used across suspension points
- // and their storage is live
- live_locals.intersect(&liveness.outs[block]);
+ let live_locals = storage_liveness;
// Add the locals life at this suspension point to the set of locals which live across
// any suspension points
use rustc::mir::*;
use rustc::mir::visit::*;
use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::layout::LayoutOf;
use rustc::ty::subst::{Subst,Substs};
use std::collections::VecDeque;
fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>) -> Option<u64> {
- (tcx, param_env).layout_of(ty).ok().map(|layout| layout.size.bytes())
+ tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
}
fn subst_and_normalize<'a, 'tcx: 'a>(
kind.name())
.span_label(e.span,
"can only break with a value inside `loop`")
+ .span_suggestion(e.span,
+ &format!("instead, use `break` on its own \
+ without a value inside this `{}` loop",
+ kind.name()),
+ "break".to_string())
.emit();
}
}
type TyLayout = TyLayout<'tcx>;
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
- (self.tcx, ty::ParamEnv::empty(traits::Reveal::All))
- .layout_of(ty)
+ self.tcx.layout_of(ty::ParamEnv::empty(traits::Reveal::All).and(ty))
.unwrap_or_else(|e| match e {
LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
_ => bug!("failed to get layout for `{}`: {}", ty, e)
debug!("compare_impl_method(impl_trait_ref={:?})",
impl_trait_ref);
+ let impl_m_span = tcx.sess.codemap().def_span(impl_m_span);
+
if let Err(ErrorReported) = compare_self_type(tcx,
impl_m,
impl_m_span,
check_region_bounds_on_impl_method(tcx,
impl_m_span,
impl_m,
+ trait_m,
&trait_m_generics,
&impl_m_generics,
trait_to_skol_substs)?;
};
let mut diag = struct_span_err!(tcx.sess,
- cause.span,
+ cause.span(&tcx),
E0053,
"method `{}` has an incompatible type for trait",
trait_m.name);
fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span: Span,
impl_m: &ty::AssociatedItem,
+ trait_m: &ty::AssociatedItem,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
trait_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> {
+ let span = tcx.sess.codemap().def_span(span);
let trait_params = &trait_generics.regions[..];
let impl_params = &impl_generics.regions[..];
// are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message.
if trait_params.len() != impl_params.len() {
- struct_span_err!(tcx.sess,
- span,
- E0195,
- "lifetime parameters or bounds on method `{}` do not match the \
- trait declaration",
- impl_m.name)
- .span_label(span, "lifetimes do not match trait")
- .emit();
+ let mut err = struct_span_err!(tcx.sess,
+ span,
+ E0195,
+ "lifetime parameters or bounds on method `{}` do not match \
+ the trait declaration",
+ impl_m.name);
+ err.span_label(span, "lifetimes do not match method in trait");
+ if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) {
+ err.span_label(tcx.sess.codemap().def_span(sp),
+ "lifetimes in impl do not match this method in trait");
+ }
+ err.emit();
return Err(ErrorReported);
}
}).map(|(ref impl_arg, ref trait_arg)| {
(impl_arg.span, Some(trait_arg.span))
})
- .unwrap_or_else(|| (cause.span, tcx.hir.span_if_local(trait_m.def_id)))
+ .unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)))
} else {
- (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+ (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
}
}
TypeError::Sorts(ExpectedFound { .. }) => {
{
(impl_m_output.span(), Some(trait_m_output.span()))
} else {
- (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+ (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
}
})
} else {
- (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+ (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
}
}
- _ => (cause.span, tcx.hir.span_if_local(trait_m.def_id)),
+ _ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)),
}
}
}
fn visit_pat(&mut self, pat: &'tcx Pat) {
+ intravisit::walk_pat(self, pat);
+
+ self.expr_count += 1;
+
if let PatKind::Binding(..) = pat.node {
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
let ty = self.fcx.tables.borrow().pat_ty(pat);
self.record(ty, Some(scope), None, pat.span);
}
-
- self.expr_count += 1;
-
- intravisit::walk_pat(self, pat);
}
fn visit_expr(&mut self, expr: &'tcx Expr) {
use rustc::ty::fold::TypeFoldable;
use rustc::ty::maps::Providers;
use rustc::ty::util::{Representability, IntTypeExt};
-use rustc::ty::layout::LayoutOf;
use errors::{DiagnosticBuilder, DiagnosticId};
use require_c_abi_if_variadic;
let span = body.value.span;
if body.is_generator && can_be_generator.is_some() {
- fcx.yield_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)));
+ let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
+ fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+ fcx.yield_ty = Some(yield_ty);
}
GatherLocalsVisitor { fcx: &fcx, }.visit_body(body);
let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| {
let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
- let layout = (tcx, param_env).layout_of(ty);
+ let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir.span_if_local(field.did).unwrap();
let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
let def_id = cx.tcx.hir.body_owner_def_id(n);
let param_env = cx.tcx.param_env(def_id);
let substs = Substs::identity_for_item(cx.tcx, def_id);
- let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap();
+ let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap_or_else(|_| {
+ cx.tcx.mk_const(ty::Const {
+ val: ConstVal::Unevaluated(def_id, substs),
+ ty: cx.tcx.types.usize
+ })
+ });
let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
n.to_string()
} else if let ConstVal::Unevaluated(def_id, _) = n.val {
let mut n = cx.tcx.lift(&n).unwrap();
if let ConstVal::Unevaluated(def_id, substs) = n.val {
let param_env = cx.tcx.param_env(def_id);
- n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap()
+ if let Ok(new_n) = cx.tcx.const_eval(param_env.and((def_id, substs))) {
+ n = new_n;
+ }
};
let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
n.to_string()
overflow: auto;
}
-.sidebar .current {
+.sidebar .block > ul > li {
margin-right: -20px;
}
-.content, nav { max-width: 960px; }
+.content, nav {
+ max-width: 960px;
+}
/* Everything else */
-.js-only, .hidden { display: none !important; }
+.js-only, .hidden {
+ display: none !important;
+}
.sidebar img {
margin: 20px auto;
border: none;
}
-.location a:first-child { font-weight: 500; }
+.location a:first-child {
+ font-weight: 500;
+}
.block {
padding: 0;
-ms-user-select: none;
user-select: none;
}
-.line-numbers span { cursor: pointer; }
+.line-numbers span {
+ cursor: pointer;
+}
.docblock-short p {
display: inline;
text-overflow: ellipsis;
margin: 0;
}
-.docblock-short code { white-space: nowrap; }
+.docblock-short code {
+ white-space: nowrap;
+}
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
border-bottom: 1px solid;
display: inline-block;
}
-#main { position: relative; }
+#main {
+ position: relative;
+}
#main > .since {
top: inherit;
font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 0;
}
-.content .item-list li { margin-bottom: 1em; }
+.content .item-list li {
+ margin-bottom: 1em;
+}
.content .multi-column {
-moz-column-count: 5;
assert!(nan.to_degrees().is_nan());
assert_eq!(inf.to_degrees(), inf);
assert_eq!(neg_inf.to_degrees(), neg_inf);
+ assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
}
#[test]
self.inner.file_attr().map(Metadata)
}
- /// Creates a new independently owned handle to the underlying file.
- ///
- /// The returned `File` is a reference to the same state that this object
- /// references. Both handles will read and write with the same cursor
- /// position.
+ /// Create a new `File` instance that shares the same underlying file handle
+ /// as the existing `File` instance. Reads, writes, and seeks will affect
+ /// both `File` instances simultaneously.
///
/// # Examples
///
+ /// Create two handles for a file named `foo.txt`:
+ ///
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let file_copy = f.try_clone()?;
+ /// let mut file = File::open("foo.txt")?;
+ /// let file_copy = file.try_clone()?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create
+ /// two handles, seek one of them, and read the remaining bytes from the
+ /// other handle:
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// use std::io::SeekFrom;
+ /// use std::io::prelude::*;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
+ /// let mut file_copy = file.try_clone()?;
+ ///
+ /// file.seek(SeekFrom::Start(3))?;
+ ///
+ /// let mut contents = vec![];
+ /// file_copy.read_to_end(&mut contents)?;
+ /// assert_eq!(contents, b"def\n");
/// # Ok(())
/// # }
/// ```
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> {
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> {
None
}
- pub unsafe fn init() -> Option<usize> {
+ pub unsafe fn init() -> Option<Guard> {
None
}
}
}
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
use sys_common::thread_info;
- // This is initialized in init() and only read from after
- static mut PAGE_SIZE: usize = 0;
-
#[cfg(any(target_os = "linux", target_os = "android"))]
unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
#[repr(C)]
_data: *mut libc::c_void) {
use sys_common::util::report_overflow;
- let guard = thread_info::stack_guard().unwrap_or(0);
+ let guard = thread_info::stack_guard().unwrap_or(0..0);
let addr = siginfo_si_addr(info);
// If the faulting address is within the guard page, then we print a
// message saying so and abort.
- if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard {
+ if guard.start <= addr && addr < guard.end {
report_overflow();
rtabort!("stack overflow");
} else {
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
pub unsafe fn init() {
- PAGE_SIZE = ::sys::os::page_size();
-
let mut action: sigaction = mem::zeroed();
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
action.sa_sigaction = signal_handler as sighandler_t;
not(target_os = "solaris")))]
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ use ops::Range;
+ pub type Guard = Range<usize>;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
use libc;
use libc::mmap;
use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
+ use ops::Range;
use sys::os;
- #[cfg(any(target_os = "macos",
- target_os = "bitrig",
- target_os = "openbsd",
- target_os = "solaris"))]
+ // This is initialized in init() and only read from after
+ static mut PAGE_SIZE: usize = 0;
+
+ pub type Guard = Range<usize>;
+
+ #[cfg(target_os = "solaris")]
+ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+ let mut current_stack: libc::stack_t = ::mem::zeroed();
+ assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
+ Some(current_stack.ss_sp)
+ }
+
+ #[cfg(target_os = "macos")]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
- current().map(|s| s as *mut libc::c_void)
+ let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+ libc::pthread_get_stacksize_np(libc::pthread_self());
+ Some(stackaddr as *mut libc::c_void)
+ }
+
+ #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
+ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+ let mut current_stack: libc::stack_t = ::mem::zeroed();
+ assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
+ &mut current_stack), 0);
+
+ let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE;
+ let stackaddr = if libc::pthread_main_np() == 1 {
+ // main thread
+ current_stack.ss_sp as usize - current_stack.ss_size + extra
+ } else {
+ // new thread
+ current_stack.ss_sp as usize - current_stack.ss_size
+ };
+ Some(stackaddr as *mut libc::c_void)
}
#[cfg(any(target_os = "android", target_os = "freebsd",
ret
}
- pub unsafe fn init() -> Option<usize> {
- let psize = os::page_size();
+ pub unsafe fn init() -> Option<Guard> {
+ PAGE_SIZE = os::page_size();
+
let mut stackaddr = get_stack_start()?;
// Ensure stackaddr is page aligned! A parent process might
// stackaddr < stackaddr + stacksize, so if stackaddr is not
// page-aligned, calculate the fix such that stackaddr <
// new_page_aligned_stackaddr < stackaddr + stacksize
- let remainder = (stackaddr as usize) % psize;
+ let remainder = (stackaddr as usize) % PAGE_SIZE;
if remainder != 0 {
- stackaddr = ((stackaddr as usize) + psize - remainder)
+ stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
as *mut libc::c_void;
}
// Instead, we'll just note where we expect rlimit to start
// faulting, so our handler can report "stack overflow", and
// trust that the kernel's own stack guard will work.
- Some(stackaddr as usize)
+ let stackaddr = stackaddr as usize;
+ Some(stackaddr - PAGE_SIZE..stackaddr)
} else {
// Reallocate the last page of the stack.
// This ensures SIGBUS will be raised on
// stack overflow.
- let result = mmap(stackaddr, psize, PROT_NONE,
+ let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE,
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
if result != stackaddr || result == MAP_FAILED {
panic!("failed to allocate a guard page");
}
+ let guardaddr = stackaddr as usize;
let offset = if cfg!(target_os = "freebsd") {
2
} else {
1
};
- Some(stackaddr as usize + offset * psize)
+ Some(guardaddr..guardaddr + offset * PAGE_SIZE)
}
}
- #[cfg(target_os = "solaris")]
- pub unsafe fn current() -> Option<usize> {
- let mut current_stack: libc::stack_t = ::mem::zeroed();
- assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
- Some(current_stack.ss_sp as usize)
- }
-
- #[cfg(target_os = "macos")]
- pub unsafe fn current() -> Option<usize> {
- Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
- libc::pthread_get_stacksize_np(libc::pthread_self()))
- }
-
- #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
- pub unsafe fn current() -> Option<usize> {
- let mut current_stack: libc::stack_t = ::mem::zeroed();
- assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
- &mut current_stack), 0);
-
- let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
- Some(if libc::pthread_main_np() == 1 {
- // main thread
- current_stack.ss_sp as usize - current_stack.ss_size + extra
- } else {
- // new thread
- current_stack.ss_sp as usize - current_stack.ss_size
- })
+ #[cfg(any(target_os = "macos",
+ target_os = "bitrig",
+ target_os = "openbsd",
+ target_os = "solaris"))]
+ pub unsafe fn current() -> Option<Guard> {
+ let stackaddr = get_stack_start()? as usize;
+ Some(stackaddr - PAGE_SIZE..stackaddr)
}
#[cfg(any(target_os = "android", target_os = "freebsd",
target_os = "linux", target_os = "netbsd", target_os = "l4re"))]
- pub unsafe fn current() -> Option<usize> {
+ pub unsafe fn current() -> Option<Guard> {
let mut ret = None;
let mut attr: libc::pthread_attr_t = ::mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
&mut size), 0);
+ let stackaddr = stackaddr as usize;
ret = if cfg!(target_os = "freebsd") {
- Some(stackaddr as usize - guardsize)
+ // FIXME does freebsd really fault *below* the guard addr?
+ let guardaddr = stackaddr - guardsize;
+ Some(guardaddr - PAGE_SIZE..guardaddr)
} else if cfg!(target_os = "netbsd") {
- Some(stackaddr as usize)
+ Some(stackaddr - guardsize..stackaddr)
+ } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
+ // glibc used to include the guard area within the stack, as noted in the BUGS
+ // section of `man pthread_attr_getguardsize`. This has been corrected starting
+ // with glibc 2.27, and in some distro backports, so the guard is now placed at the
+ // end (below) the stack. There's no easy way for us to know which we have at
+ // runtime, so we'll just match any fault in the range right above or below the
+ // stack base to call that fault a stack overflow.
+ Some(stackaddr - guardsize..stackaddr + guardsize)
} else {
- Some(stackaddr as usize + guardsize)
+ Some(stackaddr..stackaddr + guardsize)
};
}
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
}
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- pub unsafe fn current() -> Option<usize> { None }
- pub unsafe fn init() -> Option<usize> { None }
+ pub type Guard = !;
+ pub unsafe fn current() -> Option<Guard> { None }
+ pub unsafe fn init() -> Option<Guard> { None }
}
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
use cell::RefCell;
+use sys::thread::guard::Guard;
use thread::Thread;
struct ThreadInfo {
- stack_guard: Option<usize>,
+ stack_guard: Option<Guard>,
thread: Thread,
}
ThreadInfo::with(|info| info.thread.clone())
}
-pub fn stack_guard() -> Option<usize> {
- ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
+pub fn stack_guard() -> Option<Guard> {
+ ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
}
-pub fn set(stack_guard: Option<usize>, thread: Thread) {
+pub fn set(stack_guard: Option<Guard>, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
stack_guard,
pub pats: Vec<P<Pat>>,
pub guard: Option<P<Expr>>,
pub body: P<Expr>,
- pub beginning_vert: Option<Span>, // For RFC 1925 feature gate
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pats,
guard: None,
body: expr,
- beginning_vert: None,
}
}
// allow `#[must_use]` on functions and comparison operators (RFC 1940)
(active, fn_must_use, "1.21.0", Some(43302)),
- // allow '|' at beginning of match arms (RFC 1925)
- (active, match_beginning_vert, "1.21.0", Some(44101)),
-
// Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
(active, non_exhaustive, "1.22.0", Some(44109)),
(accepted, abi_sysv64, "1.24.0", Some(36167)),
// Allows `repr(align(16))` struct attribute (RFC 1358)
(accepted, repr_align, "1.24.0", Some(33626)),
+ // allow '|' at beginning of match arms (RFC 1925)
+ (accepted, match_beginning_vert, "1.25.0", Some(44101)),
);
// If you change this, please modify src/doc/unstable-book as well. You must
}
fn visit_arm(&mut self, arm: &'a ast::Arm) {
- if let Some(span) = arm.beginning_vert {
- gate_feature_post!(&self, match_beginning_vert,
- span,
- "Use of a '|' at the beginning of a match arm is experimental")
- }
visit::walk_arm(self, arm)
}
fold_attrs(attrs.into(), fld).into()
}
-pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body, beginning_vert}: Arm,
+pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm,
fld: &mut T) -> Arm {
Arm {
attrs: fold_attrs(attrs, fld),
pats: pats.move_map(|x| fld.fold_pat(x)),
guard: guard.map(|x| fld.fold_expr(x)),
body: fld.fold_expr(body),
- beginning_vert,
}
}
self.err_span(self.mk_sp(from_pos, to_pos), m)
}
+ /// Pushes a character to a message string for error reporting
+ fn push_escaped_char_for_msg(m: &mut String, c: char) {
+ match c {
+ '\u{20}'...'\u{7e}' => {
+ // Don't escape \, ' or " for user-facing messages
+ m.push(c);
+ }
+ _ => {
+ for c in c.escape_default() {
+ m.push(c);
+ }
+ }
+ }
+ }
+
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
/// escaped character to the error message
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
let mut m = m.to_string();
m.push_str(": ");
- for c in c.escape_default() {
- m.push(c)
- }
+ Self::push_escaped_char_for_msg(&mut m, c);
self.fatal_span_(from_pos, to_pos, &m[..])
}
fn struct_fatal_span_char(&self,
-> DiagnosticBuilder<'a> {
let mut m = m.to_string();
m.push_str(": ");
- for c in c.escape_default() {
- m.push(c)
- }
+ Self::push_escaped_char_for_msg(&mut m, c);
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
}
fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
let mut m = m.to_string();
m.push_str(": ");
- for c in c.escape_default() {
- m.push(c)
- }
+ Self::push_escaped_char_for_msg(&mut m, c);
self.err_span_(from_pos, to_pos, &m[..]);
}
fn struct_err_span_char(&self,
-> DiagnosticBuilder<'a> {
let mut m = m.to_string();
m.push_str(": ");
- for c in c.escape_default() {
- m.push(c)
- }
+ Self::push_escaped_char_for_msg(&mut m, c);
self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
}
let attrs = self.parse_outer_attributes()?;
// Allow a '|' before the pats (RFC 1925)
- let beginning_vert = if self.eat(&token::BinOp(token::Or)) {
- Some(self.prev_span)
- } else {
- None
- };
+ self.eat(&token::BinOp(token::Or));
let pats = self.parse_pats()?;
let guard = if self.eat_keyword(keywords::If) {
Some(self.parse_expr()?)
pats,
guard,
body: expr,
- beginning_vert,
})
}
keywords::Unsafe.name(),
keywords::While.name(),
keywords::Yield.name(),
+ keywords::Static.name(),
].contains(&ident.name)
}
/// Return a `Span` that would enclose both `self` and `end`.
pub fn to(self, end: Span) -> Span {
- let span = self.data();
- let end = end.data();
+ let span_data = self.data();
+ let end_data = end.data();
+ // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
+ // Return the macro span on its own to avoid weird diagnostic output. It is preferable to
+ // have an incomplete span than a completely nonsensical one.
+ if span_data.ctxt != end_data.ctxt {
+ if span_data.ctxt == SyntaxContext::empty() {
+ return end;
+ } else if end_data.ctxt == SyntaxContext::empty() {
+ return self;
+ }
+ // both span fall within a macro
+ // FIXME(estebank) check if it is the *same* macro
+ }
Span::new(
- cmp::min(span.lo, end.lo),
- cmp::max(span.hi, end.hi),
- // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
- if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
+ cmp::min(span_data.lo, end_data.lo),
+ cmp::max(span_data.hi, end_data.hi),
+ if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt },
)
}
// ignore-wasm
// ignore-emscripten
// ignore-windows
-// no-system-llvm
+// min-system-llvm-version 5.0
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
trait Trait {
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
+ //~^ NOTE lifetimes in impl do not match this method in trait
}
struct Foo;
impl Trait for Foo {
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
- //~^ lifetimes do not match trait
+ //~^ NOTE lifetimes do not match method in trait
}
}
trait NoLifetime {
fn get<'p, T : Test<'p>>(&self) -> T;
+ //~^ NOTE lifetimes in impl do not match this method in trait
}
trait Test<'p> {
impl<'a> NoLifetime for Foo<'a> {
fn get<'p, T : Test<'a>>(&self) -> T {
-//~^ ERROR E0195
-//~| lifetimes do not match trait
+ //~^ ERROR E0195
+ //~| NOTE lifetimes do not match method in trait
return *self as T;
}
}
--- /dev/null
+// Copyright 2012 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.
+
+// Test that the 'static bound from the Copy impl is respected. Regression test for #29149.
+
+#![feature(nll)]
+
+#[derive(Clone)] struct Foo<'a>(&'a u32);
+impl Copy for Foo<'static> {}
+
+fn main() {
+ let s = 2;
+ let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597]
+ drop(a);
+ drop(a);
+}
+++ /dev/null
-// Copyright 2014 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.
-
-// Check that explicit region bounds are allowed on the various
-// nominal types (but not on other types) and that they are type
-// checked.
-
-struct Inv<'a> { // invariant w/r/t 'a
- x: &'a mut &'a isize
-}
-
-pub trait Foo<'a, 't> {
- fn no_bound<'b>(self, b: Inv<'b>);
- fn has_bound<'b:'a>(self, b: Inv<'b>);
- fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
- fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
- fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
-}
-
-impl<'a, 't> Foo<'a, 't> for &'a isize {
- fn no_bound<'b:'a>(self, b: Inv<'b>) {
- //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
- }
-
- fn has_bound<'b>(self, b: Inv<'b>) {
- //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
- }
-
- fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
- //~^ ERROR method not compatible with trait
- //
- // Note: This is a terrible error message. It is caused
- // because, in the trait, 'b is early bound, and in the impl,
- // 'c is early bound, so -- after substitution -- the
- // lifetimes themselves look isomorphic. We fail because the
- // lifetimes that appear in the types are in the wrong
- // order. This should really be fixed by keeping more
- // information about the lifetime declarations in the trait so
- // that we can compare better to the impl, even in cross-crate
- // cases.
- }
-
- fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
- }
-
- fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
- //~^ ERROR E0276
- }
-}
-
-fn main() { }
fn main() {
// these literals are just silly.
''';
- //~^ ERROR: character constant must be escaped: \'
+ //~^ ERROR: character constant must be escaped: '
// note that this is a literal "\n" byte
'
--- /dev/null
+// Copyright 2014 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.
+
+// compile-flags: -Z parse-only
+
+\ //~ ERROR: unknown start of token: \
--- /dev/null
+// Copyright 2018 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.
+
+#![feature(generators)]
+
+fn main() {
+ unsafe {
+ static move || {
+ // Tests that the generator transformation finds out that `a` is not live
+ // during the yield expression. Type checking will also compute liveness
+ // and it should also find out that `a` is not live.
+ // The compiler will panic if the generator transformation finds that
+ // `a` is live and type checking finds it dead.
+ let a = {
+ yield ();
+ 4i32
+ };
+ &a;
+ };
+ }
+}
--- /dev/null
+// Copyright 2018 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.
+
+
+#![feature(nll)]
+
+static mut x: &'static u32 = &0;
+
+fn foo() {
+ unsafe { x = &1; }
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2018 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.
+
+enum Foo {
+ A,
+ B,
+ C,
+ D,
+ E,
+}
+use Foo::*;
+
+fn main() {
+ for foo in &[A, B, C, D, E] {
+ match *foo {
+ | A => println!("A"),
+ | B | C if 1 < 2 => println!("BC!"),
+ | _ => {},
+ }
+ }
+}
// ignore-emscripten no processes
// ignore-musl FIXME #31506
// ignore-pretty
-// no-system-llvm
+// min-system-llvm-version 5.0
// compile-flags: -C lto
// no-prefer-dynamic
// ignore-cloudabi no processes
// ignore-emscripten no processes
// ignore-musl FIXME #31506
-// no-system-llvm
+// min-system-llvm-version 5.0
use std::mem;
use std::process::Command;
--- /dev/null
+// Copyright 2018 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.
+
+// Just check if we don't get an ICE for the _S type.
+
+#![feature(const_size_of)]
+
+use std::cell::Cell;
+use std::mem;
+
+pub struct S {
+ s: Cell<usize>
+}
+
+pub type _S = [usize; 0 - (mem::size_of::<S>() != 4) as usize];
note: the lifetime 'a as defined on the impl at 17:1...
--> $DIR/associated-const-impl-wrong-lifetime.rs:17:1
|
-17 | / impl<'a> Foo for &'a () {
-18 | | const NAME: &'a str = "unit";
-19 | | //~^ ERROR mismatched types [E0308]
-20 | | }
- | |_^
+17 | impl<'a> Foo for &'a () {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
= note: ...does not necessarily outlive the static lifetime
error: aborting due to previous error
--- /dev/null
+// Copyright 2014 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.
+
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Inv<'a> { // invariant w/r/t 'a
+ x: &'a mut &'a isize
+}
+
+pub trait Foo<'a, 't> {
+ fn no_bound<'b>(self, b: Inv<'b>);
+ fn has_bound<'b:'a>(self, b: Inv<'b>);
+ fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+ fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+ fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+}
+
+impl<'a, 't> Foo<'a, 't> for &'a isize {
+ fn no_bound<'b:'a>(self, b: Inv<'b>) {
+ //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
+ }
+
+ fn has_bound<'b>(self, b: Inv<'b>) {
+ //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
+ }
+
+ fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+ //~^ ERROR method not compatible with trait
+ //
+ // Note: This is a terrible error message. It is caused
+ // because, in the trait, 'b is early bound, and in the impl,
+ // 'c is early bound, so -- after substitution -- the
+ // lifetimes themselves look isomorphic. We fail because the
+ // lifetimes that appear in the types are in the wrong
+ // order. This should really be fixed by keeping more
+ // information about the lifetime declarations in the trait so
+ // that we can compare better to the impl, even in cross-crate
+ // cases.
+ }
+
+ fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
+ }
+
+ fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+ //~^ ERROR E0276
+ }
+}
+
+fn main() { }
--- /dev/null
+error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:28:5
+ |
+20 | fn no_bound<'b>(self, b: Inv<'b>);
+ | ---------------------------------- lifetimes in impl do not match this method in trait
+...
+28 | fn no_bound<'b:'a>(self, b: Inv<'b>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:32:5
+ |
+21 | fn has_bound<'b:'a>(self, b: Inv<'b>);
+ | -------------------------------------- lifetimes in impl do not match this method in trait
+...
+32 | fn has_bound<'b>(self, b: Inv<'b>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error[E0308]: method not compatible with trait
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+ |
+36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ |
+ = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
+ found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`
+note: the lifetime 'c as defined on the method body at 36:5...
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+ |
+36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 36:5
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+ |
+36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0276]: impl has stricter requirements than trait
+ --> $DIR/regions-bound-missing-bound-in-impl.rs:53:5
+ |
+24 | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+ | ------------------------------------------------------- definition of `another_bound` from trait
+...
+53 | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`
+
+error: aborting due to 4 previous errors
+
note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1
--> $DIR/expect-region-supply-region.rs:42:1
|
-42 | / fn expect_bound_supply_named<'x>() {
-43 | | let mut f: Option<&u32> = None;
-44 | |
-45 | | // Here we give a type annotation that `x` should be free. We get
-... |
-54 | | });
-55 | | }
- | |_^
+42 | fn expect_bound_supply_named<'x>() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/expect-region-supply-region.rs:47:33
note: the lifetime 'x as defined on the function body at 42:1...
--> $DIR/expect-region-supply-region.rs:42:1
|
-42 | / fn expect_bound_supply_named<'x>() {
-43 | | let mut f: Option<&u32> = None;
-44 | |
-45 | | // Here we give a type annotation that `x` should be free. We get
-... |
-54 | | });
-55 | | }
- | |_^
+42 | fn expect_bound_supply_named<'x>() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29
--> $DIR/expect-region-supply-region.rs:47:29
|
+++ /dev/null
-// 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.
-
-#[allow(dead_code)]
-enum Foo {
- A,
- B,
- C,
- D,
- E,
-}
-use Foo::*;
-
-fn main() {
- let x = Foo::A;
- match x {
- | A => println!("A"),
- //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- | B | C => println!("BC!"),
- //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- | _ => {},
- //~^ ERROR: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- };
- match x {
- A | B | C => println!("ABC!"),
- _ => {},
- };
-}
-
+++ /dev/null
-error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- --> $DIR/feature-gate-match_beginning_vert.rs:24:9
- |
-24 | | A => println!("A"),
- | ^
- |
- = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
-
-error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- --> $DIR/feature-gate-match_beginning_vert.rs:26:9
- |
-26 | | B | C => println!("BC!"),
- | ^
- |
- = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
-
-error[E0658]: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
- --> $DIR/feature-gate-match_beginning_vert.rs:28:9
- |
-28 | | _ => {},
- | ^
- |
- = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-error[E0626]: borrow may still be in use when generator yields (Mir)
- --> $DIR/generator-with-nll.rs:20:17
- |
-20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
- | ^^^^^^^^^
-21 | //~^ borrow may still be in use when generator yields (Mir)
-22 | yield ();
- | -------- possible yield occurs here
-
error[E0626]: borrow may still be in use when generator yields (Ast)
--> $DIR/generator-with-nll.rs:19:23
|
22 | yield ();
| -------- possible yield occurs here
+error[E0626]: borrow may still be in use when generator yields (Mir)
+ --> $DIR/generator-with-nll.rs:20:17
+ |
+20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+ | ^^^^^^^^^
+21 | //~^ borrow may still be in use when generator yields (Mir)
+22 | yield ();
+ | -------- possible yield occurs here
+
error: aborting due to 3 previous errors
--- /dev/null
+// Copyright 2018 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.
+
+#![feature(generators)]
+
+enum Test { A(i32), B, }
+
+fn main() { }
+
+fn fun(test: Test) {
+ move || {
+ if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+ yield ();
+ }
+ };
+}
--- /dev/null
+error[E0626]: borrow may still be in use when generator yields
+ --> $DIR/pattern-borrow.rs:19:24
+ |
+19 | if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+ | ^^^^^^
+20 | yield ();
+ | -------- possible yield occurs here
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 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.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn main() {
+ let s = String::from("foo");
+ let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ yield s[..];
+ };
+ gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/sized-yield.rs:17:26
+ |
+17 | let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ | __________________________^
+18 | | yield s[..];
+19 | | };
+ | |____^ `str` does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: the yield type of a generator must have a statically known size
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/sized-yield.rs:20:8
+ |
+20 | gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ | ^^^^^^ `str` does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+
+error: aborting due to 2 previous errors
+
-error[E0626]: borrow may still be in use when generator yields (Mir)
- --> $DIR/yield-while-local-borrowed.rs:24:17
- |
-24 | let a = &mut 3;
- | ^^^^^^
-...
-27 | yield();
- | ------- possible yield occurs here
-
error[E0626]: borrow may still be in use when generator yields (Ast)
--> $DIR/yield-while-local-borrowed.rs:24:22
|
55 | yield();
| ------- possible yield occurs here
+error[E0626]: borrow may still be in use when generator yields (Mir)
+ --> $DIR/yield-while-local-borrowed.rs:24:17
+ |
+24 | let a = &mut 3;
+ | ^^^^^^
+...
+27 | yield();
+ | ------- possible yield occurs here
+
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/yield-while-local-borrowed.rs:52:21
|
--> $DIR/trait_type.rs:17:4
|
17 | fn fmt(&self, x: &str) -> () { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
|
= note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
found type `fn(&MyType, &str)`
--> $DIR/trait_type.rs:27:4
|
27 | fn fmt() -> () { }
- | ^^^^^^^^^^^^^^^^^^ expected `&self` in impl
+ | ^^^^^^^^^^^^^^ expected `&self` in impl
|
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
--- /dev/null
+// Copyright 2018 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(warnings)]
+#![allow(unused_variables, dead_code, unused, bad_style)]
+#![deny(elided_lifetime_in_path)]
+
+struct Foo<'a> { x: &'a u32 }
+fn foo(x: &Foo) {
+ //~^ ERROR: hidden lifetime parameters are deprecated, try `Foo<'_>`
+}
+
+fn main() {}
--- /dev/null
+error: hidden lifetime parameters are deprecated, try `Foo<'_>`
+ --> $DIR/ellided-lifetimes.rs:15:12
+ |
+15 | fn foo(x: &Foo) {
+ | ^^^
+ |
+note: lint level defined here
+ --> $DIR/ellided-lifetimes.rs:12:9
+ |
+12 | #![deny(elided_lifetime_in_path)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 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 std::ops::Deref;
+trait Trait {}
+
+struct Struct;
+
+impl Deref for Struct {
+ type Target = Trait;
+ fn deref(&self) -> &Trait {
+ unimplemented!();
+ }
+}
+//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
--- /dev/null
+error[E0601]: main function not found
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
+ --> $DIR/mismatched_trait_impl-2.rs:18:5
+ |
+18 | fn deref(&self) -> &Trait {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
+ --> $DIR/mismatched_trait_impl-2.rs:18:5
+ |
+18 | / fn deref(&self) -> &Trait {
+19 | | unimplemented!();
+20 | | }
+ | |_____^
+ = note: ...but the lifetime must also be valid for the static lifetime...
+ = note: ...so that the method type is compatible with trait:
+ expected fn(&Struct) -> &Trait + 'static
+ found fn(&Struct) -> &Trait
+
+error: aborting due to 2 previous errors
+
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl.rs:19:5
|
-19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | | x
-21 | | }
- | |_____^
+19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5...
--> $DIR/mismatched_trait_impl.rs:19:5
20 | | x
21 | | }
| |_____^
-note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
- --> $DIR/mismatched_trait_impl.rs:19:5
- |
-19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | | x
-21 | | }
- | |_____^
-note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 19:5...
+note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 19:5...
--> $DIR/mismatched_trait_impl.rs:19:5
|
-19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | | x
-21 | | }
- | |_____^
-note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
- --> $DIR/mismatched_trait_impl.rs:19:5
- |
-19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | | x
-21 | | }
- | |_____^
+19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...so that the method type is compatible with trait:
+ expected fn(&i32, &'a u32, &u32) -> &'a u32
+ found fn(&i32, &u32, &u32) -> &u32
error: aborting due to previous error
note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1
--> $DIR/issue-27942.rs:13:1
|
-13 | / pub trait Buffer<'a, R: Resources<'a>> {
-14 | |
-15 | | fn select(&self) -> BufferViewHandle<R>;
-16 | | //~^ ERROR mismatched types
-... |
-19 | | //~| lifetime mismatch
-20 | | }
- | |_^
+13 | pub trait Buffer<'a, R: Resources<'a>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/issue-27942.rs:15:5
note: the lifetime 'a as defined on the trait at 13:1...
--> $DIR/issue-27942.rs:13:1
|
-13 | / pub trait Buffer<'a, R: Resources<'a>> {
-14 | |
-15 | | fn select(&self) -> BufferViewHandle<R>;
-16 | | //~^ ERROR mismatched types
-... |
-19 | | //~| lifetime mismatch
-20 | | }
- | |_^
+13 | pub trait Buffer<'a, R: Resources<'a>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5
--> $DIR/issue-27942.rs:15:5
|
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1
--> $DIR/issue-37884.rs:13:1
|
-13 | / impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
-14 | |
-15 | | type Item = &'a mut T;
-16 | | fn next(&'a mut self) -> Option<Self::Item>
-... |
-21 | | }
-22 | | }
- | |_^
+13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
--> $DIR/issue-46472.rs:13:1
|
-13 | / fn bar<'a>() -> &'a mut u32 {
-14 | | &mut 4
-15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
-16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
-17 | | }
- | |_^
+13 | fn bar<'a>() -> &'a mut u32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0597]: borrowed value does not live long enough (Mir)
--> $DIR/issue-46472.rs:14:10
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
--> $DIR/issue-46472.rs:13:1
|
-13 | / fn bar<'a>() -> &'a mut u32 {
-14 | | &mut 4
-15 | | //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
-16 | | //~| ERROR borrowed value does not live long enough (Mir) [E0597]
-17 | | }
- | |_^
+13 | fn bar<'a>() -> &'a mut u32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
--- /dev/null
+// Copyright 2018 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.
+
+// must-compile-successfully
+
+#![warn(unused_parens)]
+
+macro_rules! the_worship_the_heart_lifts_above {
+ ( @as_expr, $e:expr) => { $e };
+ ( @generate_fn, $name:tt) => {
+ #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> {
+ Some(the_worship_the_heart_lifts_above!( @as_expr, $name ))
+ }
+ };
+ ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); }
+ // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in
+ // function/method arguments inside of nested macros because of situations
+ // like those reported in Issue #47775
+}
+
+macro_rules! and_the_heavens_reject_not {
+ () => {
+ // ↓ But let's test that we still lint for unused parens around
+ // function args inside of simple, one-deep macros.
+ #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+ //~^ WARN unnecessary parentheses around function argument
+ }
+}
+
+the_worship_the_heart_lifts_above!(rah);
+and_the_heavens_reject_not!();
+
+fn main() {}
--- /dev/null
+warning: unnecessary parentheses around function argument
+ --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:32:83
+ |
+32 | #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+ | ^^^ help: remove these parentheses
+...
+38 | and_the_heavens_reject_not!();
+ | ------------------------------ in this macro invocation
+ |
+note: lint level defined here
+ --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:13:9
+ |
+13 | #![warn(unused_parens)]
+ | ^^^^^^^^^^^^^
+
|
22 | break 22 //~ ERROR `break` with value from a `for` loop
| ^^^^^^^^ can only break with a value inside `loop`
+help: instead, use `break` on its own without a value inside this `for` loop
+ |
+22 | break //~ ERROR `break` with value from a `for` loop
+ | ^^^^^
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 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.
+
+macro_rules! bad {
+ ($s:ident whatever) => {
+ {
+ let $s = 0;
+ *&mut $s = 0;
+ //~^ ERROR cannot borrow immutable local variable `foo` as mutable [E0596]
+ }
+ }
+}
+
+fn main() {
+ bad!(foo whatever);
+}
--- /dev/null
+error[E0596]: cannot borrow immutable local variable `foo` as mutable
+ --> $DIR/span-covering-argument-1.rs:15:19
+ |
+14 | let $s = 0;
+ | -- consider changing this to `mut $s`
+15 | *&mut $s = 0;
+ | ^^ cannot borrow mutably
+...
+22 | bad!(foo whatever);
+ | ------------------- in this macro invocation
+
+error: aborting due to previous error
+
warning: struct is never used: `S`
- --> $DIR/macro-span-replacement.rs:17:9
+ --> $DIR/macro-span-replacement.rs:17:14
|
17 | $b $a; //~ WARN struct is never used
- | ^^^^^^
+ | ^
...
22 | m!(S struct);
| ------------- in this macro invocation
--> $DIR/static-lifetime.rs:13:1
|
13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but lifetime parameter must outlive the static lifetime
error: aborting due to previous error
.expect("Malformed llvm version directive");
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
- !(config.system_llvm && &actual_version[..] < min_version)
+ config.system_llvm && &actual_version[..] < min_version
} else {
false
}
let mut results = Vec::new();
let mut mismatch = Mismatch::new(0);
- for result in diff::lines(actual, expected) {
+ for result in diff::lines(expected, actual) {
match result {
diff::Result::Left(str) => {
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
mismatch.lines.push(DiffLine::Context(line.to_owned()));
}
- mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
+ mismatch.lines.push(DiffLine::Expected(str.to_owned()));
+ line_number += 1;
lines_since_mismatch = 0;
}
diff::Result::Right(str) => {
mismatch.lines.push(DiffLine::Context(line.to_owned()));
}
- mismatch.lines.push(DiffLine::Expected(str.to_owned()));
- line_number += 1;
+ mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
lines_since_mismatch = 0;
}
diff::Result::Both(str, _) => {
-Subproject commit 511321ae1c2fa3f0e334885fecf406dd6c882836
+Subproject commit dee42bda8156a28ead609080e27b02173bb9c29e
-Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
+Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7