diff --git a/.gitignore b/.gitignore index 487867c375d45..1428ee6c9bc23 100644 --- a/.gitignore +++ b/.gitignore @@ -55,5 +55,6 @@ config.mk config.stamp Session.vim .cargo +!/src/test/run-make/thumb-none-qemu/example/.cargo no_llvm_build # Before adding new lines, see the comment at the top. diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index 6932c7fe221d0..570fc4ab93390 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -11,4 +11,5 @@ mod hash; mod iter; mod num; mod ops; +mod pattern; mod slice; diff --git a/src/libcore/benches/pattern.rs b/src/libcore/benches/pattern.rs new file mode 100644 index 0000000000000..a49490cec1219 --- /dev/null +++ b/src/libcore/benches/pattern.rs @@ -0,0 +1,43 @@ +use test::black_box; +use test::Bencher; + +#[bench] +fn starts_with_char(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.starts_with('k')); + } + }) +} + +#[bench] +fn starts_with_str(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.starts_with("k")); + } + }) +} + + +#[bench] +fn ends_with_char(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.ends_with('k')); + } + }) +} + +#[bench] +fn ends_with_str(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.ends_with("k")); + } + }) +} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 2db55508ad546..1b586c3e5fe30 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -97,7 +97,7 @@ pub trait Sized { /// Types that can be "unsized" to a dynamically-sized type. /// /// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and -/// `Unsize`. +/// `Unsize`. /// /// All implementations of `Unsize` are provided automatically by the compiler. /// diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 33715418ffd73..d091a8d86ea49 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -67,7 +67,7 @@ assert_eq!(size_of::>(), size_of::<", s )] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { - $Ty(n) + Self(n) } /// Creates a non-zero if the given value is not zero. @@ -76,7 +76,7 @@ assert_eq!(size_of::>(), size_of::<", s pub fn new(n: $Int) -> Option { if n != 0 { // SAFETY: we just checked that there's no `0` - Some(unsafe { $Ty(n) }) + Some(unsafe { Self(n) }) } else { None } diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 1037da14b5f62..b7ebd5f88b589 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -445,21 +445,13 @@ impl<'a> Pattern<'a> for char { #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - if let Some(ch) = haystack.chars().next() { - self == ch - } else { - false - } + self.encode_utf8(&mut [0u8; 4]).is_prefix_of(haystack) } #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a> { - if let Some(ch) = haystack.chars().next_back() { - self == ch - } else { - false - } + self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack) } } @@ -710,16 +702,13 @@ impl<'a, 'b> Pattern<'a> for &'b str { /// Checks whether the pattern matches at the front of the haystack #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - haystack.is_char_boundary(self.len()) && - self == &haystack[..self.len()] + haystack.as_bytes().starts_with(self.as_bytes()) } /// Checks whether the pattern matches at the back of the haystack #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool { - self.len() <= haystack.len() && - haystack.is_char_boundary(haystack.len() - self.len()) && - self == &haystack[haystack.len() - self.len()..] + haystack.as_bytes().ends_with(self.as_bytes()) } } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 7756335ee207d..d5b0bc420382f 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1263,7 +1263,7 @@ let atomic_forty_two = ", stringify!($atomic_type), "::new(42); #[$stable] #[cfg_attr(not(bootstrap), $const_stable)] pub const fn new(v: $int_type) -> Self { - $atomic_type {v: UnsafeCell::new(v)} + Self {v: UnsafeCell::new(v)} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e13f6cabb5296..ec9d6802defa3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2852,19 +2852,23 @@ impl<'a> LoweringContext<'a> { let mut rest = None; let mut iter = pats.iter().enumerate(); - while let Some((idx, pat)) = iter.next() { - // Interpret the first `..` pattern as a subtuple pattern. + for (idx, pat) in iter.by_ref() { + // Interpret the first `..` pattern as a sub-tuple pattern. + // Note that unlike for slice patterns, + // where `xs @ ..` is a legal sub-slice pattern, + // it is not a legal sub-tuple pattern. if pat.is_rest() { rest = Some((idx, pat.span)); break; } - // It was not a subslice pattern so lower it normally. + // It was not a sub-tuple pattern so lower it normally. elems.push(self.lower_pat(pat)); } - while let Some((_, pat)) = iter.next() { - // There was a previous subtuple pattern; make sure we don't allow more. + for (_, pat) in iter { + // There was a previous sub-tuple pattern; make sure we don't allow more... if pat.is_rest() { + // ...but there was one again, so error. self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx); } else { elems.push(self.lower_pat(pat)); @@ -2874,6 +2878,12 @@ impl<'a> LoweringContext<'a> { (elems.into(), rest.map(|(ddpos, _)| ddpos)) } + /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into + /// `hir::PatKind::Slice(before, slice, after)`. + /// + /// When encountering `($binding_mode $ident @)? ..` (`slice`), + /// this is interpreted as a sub-slice pattern semantically. + /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`. fn lower_pat_slice(&mut self, pats: &[AstP]) -> hir::PatKind { let mut before = Vec::new(); let mut after = Vec::new(); @@ -2881,14 +2891,17 @@ impl<'a> LoweringContext<'a> { let mut prev_rest_span = None; let mut iter = pats.iter(); - while let Some(pat) = iter.next() { - // Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern. + // Lower all the patterns until the first occurence of a sub-slice pattern. + for pat in iter.by_ref() { match pat.kind { + // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here. PatKind::Rest => { prev_rest_span = Some(pat.span); slice = Some(self.pat_wild_with_node_id_of(pat)); break; }, + // Found a sub-slice pattern `$binding_mode $ident @ ..`. + // Record, lower it to `$binding_mode $ident @ _`, and stop here. PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); @@ -2896,14 +2909,13 @@ impl<'a> LoweringContext<'a> { slice = Some(self.pat_with_node_id_of(pat, node)); break; }, - _ => {} + // It was not a subslice pattern so lower it normally. + _ => before.push(self.lower_pat(pat)), } - - // It was not a subslice pattern so lower it normally. - before.push(self.lower_pat(pat)); } - while let Some(pat) = iter.next() { + // Lower all the patterns after the first sub-slice pattern. + for pat in iter { // There was a previous subslice pattern; make sure we don't allow more. let rest_span = match pat.kind { PatKind::Rest => Some(pat.span), @@ -2915,8 +2927,10 @@ impl<'a> LoweringContext<'a> { _ => None, }; if let Some(rest_span) = rest_span { + // We have e.g., `[a, .., b, ..]`. That's no good, error! self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice"); } else { + // Lower the pattern normally. after.push(self.lower_pat(pat)); } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 66bb3a8d883a4..6b354b01518ea 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1048,8 +1048,15 @@ pub enum PatKind { /// A range pattern (e.g., `1..=2` or `1..2`). Range(P, P, RangeEnd), - /// `[a, b, ..i, y, z]` is represented as: - /// `PatKind::Slice(box [a, b], Some(i), box [y, z])`. + /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`. + /// + /// Here, `slice` is lowered from the syntax `($binding_mode $ident @)? ..`. + /// If `slice` exists, then `after` can be non-empty. + /// + /// The representation for e.g., `[a, b, .., c, d]` is: + /// ``` + /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) + /// ``` Slice(HirVec>, Option>, HirVec>), } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 43e7bbcf0c0dc..09771bb762536 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2330,7 +2330,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d ); let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); err.span_label(sp, &msg); - if let &[ref start @ .., ref end] = &variant_spans[..] { + if let [start @ .., end] = &*variant_spans { for variant_span in start { err.span_label(*variant_span, ""); } @@ -2372,23 +2372,14 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { } let sp = tcx.sess.source_map().def_span(sp); - if adt.is_enum() { - if !tcx.features().transparent_enums { - feature_err( - &tcx.sess.parse_sess, - sym::transparent_enums, - sp, - "transparent enums are unstable", - ) - .emit(); - } - if adt.variants.len() != 1 { - bad_variant_count(tcx, adt, sp, def_id); - if adt.variants.is_empty() { - // Don't bother checking the fields. No variants (and thus no fields) exist. - return; - } - } + if adt.is_enum() && !tcx.features().transparent_enums { + feature_err( + &tcx.sess.parse_sess, + sym::transparent_enums, + sp, + "transparent enums are unstable", + ) + .emit(); } if adt.is_union() && !tcx.features().transparent_unions { @@ -2401,6 +2392,14 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { .emit(); } + if adt.variants.len() != 1 { + bad_variant_count(tcx, adt, sp, def_id); + if adt.variants.is_empty() { + // Don't bother checking the fields. No variants (and thus no fields) exist. + return; + } + } + // For each field, figure out if it's known to be a ZST and align(1) let field_infos = adt.all_fields().map(|field| { let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did)); @@ -5351,9 +5350,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { directly, not through a function pointer"); } - // Resolves `typ` by a single level if `typ` is a type variable. - // If no resolution is possible, then an error is reported. - // Numeric inference variables may be left unresolved. + /// Resolves `typ` by a single level if `typ` is a type variable. + /// If no resolution is possible, then an error is reported. + /// Numeric inference variables may be left unresolved. pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = self.resolve_vars_with_obligations(ty); if !ty.is_ty_var() { diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 71d1cd869a6a2..4fb57a6562574 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1154,6 +1154,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.mk_ref(region, mt) } + /// Type check a slice pattern. + /// + /// Syntactically, these look like `[pat_0, ..., pat_n]`. + /// Semantically, we are type checking a pattern with structure: + /// ``` + /// [before_0, ..., before_n, (slice, after_0, ... after_n)?] + /// ``` + /// The type of `slice`, if it is present, depends on the `expected` type. + /// If `slice` is missing, then so is `after_i`. + /// If `slice` is present, it can still represent 0 elements. fn check_pat_slice( &self, span: Span, @@ -1167,27 +1177,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let expected_ty = self.structurally_resolved_type(span, expected); let (inner_ty, slice_ty) = match expected_ty.kind { + // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`. ty::Array(inner_ty, size) => { let slice_ty = if let Some(size) = size.try_eval_usize(tcx, self.param_env) { + // Now we know the length... let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { + // ...and since there is no variable-length pattern, + // we require an exact match between the number of elements + // in the array pattern and as provided by the matched type. if min_len != size { self.error_scrutinee_inconsistent_length(span, min_len, size) } tcx.types.err } else if let Some(rest) = size.checked_sub(min_len) { + // The variable-length pattern was there, + // so it has an array type with the remaining elements left as its size... tcx.mk_array(inner_ty, rest) } else { + // ...however, in this case, there were no remaining elements. + // That is, the slice pattern requires more than the array type offers. self.error_scrutinee_with_rest_inconsistent_length(span, min_len, size); tcx.types.err } } else { + // No idea what the length is, which happens if we have e.g., + // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`. self.error_scrutinee_unfixed_length(span); tcx.types.err }; (inner_ty, slice_ty) } ty::Slice(inner_ty) => (inner_ty, expected_ty), + // The expected type must be an array or slice, but was neither, so error. _ => { if !expected_ty.references_error() { self.error_expected_array_or_slice(span, expected_ty); @@ -1196,12 +1218,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; + // Type check all the patterns before `slice`. for elt in before { self.check_pat(&elt, inner_ty, def_bm, discrim_span); } + // Type check the `slice`, if present, against its expected type. if let Some(slice) = slice { self.check_pat(&slice, slice_ty, def_bm, discrim_span); } + // Type check the elements after `slice`, if present. for elt in after { self.check_pat(&elt, inner_ty, def_bm, discrim_span); } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 49a9cb093da2a..1459e8f37cd32 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2683,7 +2683,7 @@ function getSearchElement() { insertAfter(popup, getSearchElement()); } - onHashChange(); + onHashChange(null); window.onhashchange = onHashChange; buildHelperPopup(); diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 5c02215997088..c33f98bdd8329 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1312,21 +1312,6 @@ mod tests { }) } - #[test] - fn fast_rebind() { - each_ip(&mut |addr| { - let acceptor = t!(TcpListener::bind(&addr)); - - let _t = thread::spawn(move || { - t!(TcpStream::connect(&addr)); - }); - - t!(acceptor.accept()); - drop(acceptor); - t!(TcpListener::bind(&addr)); - }); - } - #[test] fn tcp_clone_smoke() { each_ip(&mut |addr| {