name = "build_helper"
version = "0.1.0"
+[[package]]
+name = "bump-stage0"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "curl",
+ "indexmap",
+ "serde",
+ "serde_json",
+ "toml",
+]
+
[[package]]
name = "byte-tools"
version = "0.3.1"
dependencies = [
"cargo_metadata 0.12.0",
"clippy_lints",
- "compiletest_rs",
+ "compiletest_rs 0.6.0",
"derive-new",
"filetime",
"quote",
"winapi",
]
+[[package]]
+name = "compiletest_rs"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
+dependencies = [
+ "diff",
+ "filetime",
+ "getopts",
+ "lazy_static",
+ "libc",
+ "log",
+ "miow",
+ "regex",
+ "rustfix 0.5.1",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tempfile",
+ "tester",
+ "winapi",
+]
+
[[package]]
name = "core"
version = "0.0.0"
dependencies = [
"autocfg",
"hashbrown",
+ "serde",
]
[[package]]
version = "0.1.0"
dependencies = [
"colored",
- "compiletest_rs",
+ "compiletest_rs 0.7.0",
"env_logger 0.8.1",
"getrandom 0.2.0",
"hex 0.4.2",
"src/tools/expand-yaml-anchors",
"src/tools/jsondocck",
"src/tools/html-checker",
+ "src/tools/bump-stage0",
]
exclude = [
use super::{ImplTraitContext, ImplTraitPosition};
use crate::Arena;
-use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::*;
generics: &Generics,
itctx: ImplTraitContext<'_, 'hir>,
) -> GenericsCtor<'hir> {
- // Collect `?Trait` bounds in where clause and move them to parameter definitions.
- let mut add_bounds: NodeMap<Vec<_>> = Default::default();
+ // Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
+ // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
+ // these into hir when we lower thee where clauses), but this makes it quite difficult to
+ // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
+ // where clauses for `?Sized`.
for pred in &generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
'next_bound: for bound in &bound_pred.bounds {
{
for param in &generics.params {
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
- add_bounds.entry(param.id).or_default().push(bound.clone());
continue 'next_bound;
}
}
}
GenericsCtor {
- params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
+ params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
where_clause: self.lower_where_clause(&generics.where_clause),
span: self.lower_span(generics.span),
}
ref bounded_ty,
ref bounds,
span,
- }) => {
- self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
- hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
- bound_generic_params: this.lower_generic_params(
- bound_generic_params,
- &NodeMap::default(),
- ImplTraitContext::disallowed(),
- ),
- bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
- bounds: this.arena.alloc_from_iter(bounds.iter().map(
- |bound| match bound {
- // We used to ignore `?Trait` bounds, as they were copied into type
- // parameters already, but we need to keep them around only for
- // diagnostics when we suggest removal of `?Sized` bounds. See
- // `suggest_constraining_type_param`. This will need to change if
- // we ever allow something *other* than `?Sized`.
- GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
- hir::GenericBound::Unsized(this.lower_span(p.span))
- }
- _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
- },
- )),
- span: this.lower_span(span),
- })
+ }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
+ hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ bound_generic_params: this
+ .lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
+ bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
+ bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
+ this.lower_param_bound(bound, ImplTraitContext::disallowed())
+ })),
+ span: this.lower_span(span),
})
- }
+ }),
WherePredicate::RegionPredicate(WhereRegionPredicate {
ref lifetime,
ref bounds,
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
generic_params: this.lower_generic_params(
&f.generic_params,
- &NodeMap::default(),
ImplTraitContext::disallowed(),
),
unsafety: this.lower_unsafety(f.unsafety),
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
- add_bounds: &'s NodeMap<Vec<GenericBound>>,
mut itctx: ImplTraitContext<'s, 'hir>,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
- params
- .iter()
- .map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
+ params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
}
fn lower_generic_params(
&mut self,
params: &[GenericParam],
- add_bounds: &NodeMap<Vec<GenericBound>>,
itctx: ImplTraitContext<'_, 'hir>,
) -> &'hir [hir::GenericParam<'hir>] {
- self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
+ self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
}
fn lower_generic_param(
&mut self,
param: &GenericParam,
- add_bounds: &NodeMap<Vec<GenericBound>>,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::GenericParam<'hir> {
- let mut bounds: Vec<_> = self
+ let bounds: Vec<_> = self
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
this.lower_param_bounds_mut(¶m.bounds, itctx.reborrow()).collect()
});
(param_name, kind)
}
GenericParamKind::Type { ref default, .. } => {
- let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x);
- if !add_bounds.is_empty() {
- let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
- bounds.extend(params);
- }
-
let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| {
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
p: &PolyTraitRef,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::PolyTraitRef<'hir> {
- let bound_generic_params = self.lower_generic_params(
- &p.bound_generic_params,
- &NodeMap::default(),
- itctx.reborrow(),
- );
+ let bound_generic_params =
+ self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
// Any impl Trait types defined within this scope can capture
use tempfile::Builder as TempFileBuilder;
use std::ffi::OsString;
+use std::lazy::OnceCell;
use std::path::{Path, PathBuf};
use std::process::{ExitStatus, Output, Stdio};
use std::{ascii, char, env, fmt, fs, io, mem, str};
// metadata of the rlib we're generating somehow.
for lib in codegen_results.crate_info.used_libraries.iter() {
match lib.kind {
+ NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) }
+ if flavor == RlibFlavor::Normal =>
+ {
+ // Don't allow mixing +bundle with +whole_archive since an rlib may contain
+ // multiple native libs, some of which are +whole-archive and some of which are
+ // -whole-archive and it isn't clear how we can currently handle such a
+ // situation correctly.
+ // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
+ sess.err(
+ "the linking modifiers `+bundle` and `+whole-archive` are not compatible \
+ with each other when generating rlibs",
+ );
+ }
NativeLibKind::Static { bundle: None | Some(true), .. } => {}
NativeLibKind::Static { bundle: Some(false), .. }
| NativeLibKind::Dylib { .. }
sess.target_filesearch(PathKind::Native).search_path_dirs()
}
+#[derive(PartialEq)]
enum RlibFlavor {
Normal,
StaticlibBase,
let relevant_libs =
codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
- let search_path = archive_search_paths(sess);
+ let search_path = OnceCell::new();
let mut last = (NativeLibKind::Unspecified, None);
for lib in relevant_libs {
let name = match lib.name {
}
NativeLibKind::Static { bundle: None | Some(true), .. }
| NativeLibKind::Static { whole_archive: Some(true), .. } => {
- cmd.link_whole_staticlib(name, verbatim, &search_path);
+ cmd.link_whole_staticlib(
+ name,
+ verbatim,
+ &search_path.get_or_init(|| archive_search_paths(sess)),
+ );
}
NativeLibKind::Static { .. } => cmd.link_staticlib(name, verbatim),
NativeLibKind::RawDylib => {
}
let mut compiler_builtins = None;
+ let search_path = OnceCell::new();
for &cnum in deps.iter() {
if group_start == Some(cnum) {
// external build system already has the native dependencies defined, and it
// will provide them to the linker itself.
if sess.opts.debugging_opts.link_native_libraries {
- // Skip if this library is the same as the last.
let mut last = None;
for lib in &codegen_results.crate_info.native_libraries[&cnum] {
- if lib.name.is_some()
- && relevant_lib(sess, lib)
- && matches!(lib.kind, NativeLibKind::Static { bundle: Some(false), .. })
- && last != lib.name
- {
- cmd.link_staticlib(lib.name.unwrap(), lib.verbatim.unwrap_or(false));
- last = lib.name;
+ if !relevant_lib(sess, lib) {
+ // Skip libraries if they are disabled by `#[link(cfg=...)]`
+ continue;
+ }
+
+ // Skip if this library is the same as the last.
+ if last == lib.name {
+ continue;
+ }
+
+ if let Some(static_lib_name) = lib.name {
+ if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
+ lib.kind
+ {
+ let verbatim = lib.verbatim.unwrap_or(false);
+ if whole_archive == Some(true) {
+ cmd.link_whole_staticlib(
+ static_lib_name,
+ verbatim,
+ search_path.get_or_init(|| archive_search_paths(sess)),
+ );
+ } else {
+ cmd.link_staticlib(static_lib_name, verbatim);
+ }
+
+ last = lib.name;
+ }
}
}
}
#![feature(box_patterns)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
+#![feature(once_cell)]
#![feature(nll)]
#![feature(associated_type_bounds)]
#![recursion_limit = "256"]
use std::iter::FromIterator;
-/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
+/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
/// which uses only a single (null) pointer.
#[derive(Clone, Encodable, Decodable, Debug)]
use rustc_serialize::json::Json;
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use std::fmt;
+use std::hash::{Hash, Hasher};
#[must_use]
-#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
pub struct Diagnostic {
pub level: Level,
pub message: Vec<(String, Style)>,
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
/// `span` if there is one. Otherwise, it is `DUMMY_SP`.
pub sort_span: Span,
+
+ /// If diagnostic is from Lint, custom hash function ignores notes
+ /// otherwise hash is based on the all the fields
+ pub is_lint: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
children: vec![],
suggestions: vec![],
sort_span: DUMMY_SP,
+ is_lint: false,
}
}
self
}
+ pub fn set_is_lint(&mut self) -> &mut Self {
+ self.is_lint = true;
+ self
+ }
+
pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
self.code = Some(s);
self
let sub = SubDiagnostic { level, message, span, render_span };
self.children.push(sub);
}
+
+ /// Fields used for Hash, and PartialEq trait
+ fn keys(
+ &self,
+ ) -> (
+ &Level,
+ &Vec<(String, Style)>,
+ &Option<DiagnosticId>,
+ &MultiSpan,
+ &Vec<CodeSuggestion>,
+ Option<&Vec<SubDiagnostic>>,
+ ) {
+ (
+ &self.level,
+ &self.message,
+ &self.code,
+ &self.span,
+ &self.suggestions,
+ (if self.is_lint { None } else { Some(&self.children) }),
+ )
+ }
+}
+
+impl Hash for Diagnostic {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.keys().hash(state);
+ }
+}
+
+impl PartialEq for Diagnostic {
+ fn eq(&self, other: &Self) -> bool {
+ self.keys() == other.keys()
+ }
}
impl SubDiagnostic {
sp: S,
msg: &str,
) -> &mut Self);
+ forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
/// See [`Diagnostic::multipart_suggestion()`].
pub fn multipart_suggestion(
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
- Unsized(Span),
Outlives(Lifetime),
}
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
+
impl GenericBound<'_> {
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
match self {
GenericBound::Trait(t, ..) => t.span,
GenericBound::LangItemTrait(_, span, ..) => *span,
GenericBound::Outlives(l) => l.span,
- GenericBound::Unsized(span) => *span,
}
}
}
//! example generator inference, and possibly also HIR borrowck.
use crate::hir::*;
-use crate::hir_id::CRATE_HIR_ID;
use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
use rustc_ast::walk_list;
use rustc_ast::{Attribute, Label};
}
}
-/// Walks the contents of a crate. See also `Crate::visit_all_items`.
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
- let top_mod = krate.module();
- visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
- for (&id, attrs) in krate.attrs.iter() {
- for a in *attrs {
- visitor.visit_attribute(id, a)
- }
- }
-}
-
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
visitor.visit_id(mod_hir_id);
for &item_id in module.item_ids {
visitor.visit_generic_args(span, args);
}
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
- GenericBound::Unsized(_) => {}
}
}
GenericBound::Outlives(lt) => {
self.print_lifetime(lt);
}
- GenericBound::Unsized(_) => {
- self.s.word("?Sized");
- }
}
}
}
krate.visit_all_item_likes(&mut dirty_clean_visitor);
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
- intravisit::walk_crate(&mut all_attrs, krate);
+ tcx.hir().walk_attributes(&mut all_attrs);
// Note that we cannot use the existing "unused attribute"-infrastructure
// here, since that is running before codegen. This is also the reason why
use std::env;
use std::fs;
use std::io::{self, Read};
-use std::path::Path;
+use std::path::{Path, PathBuf};
+use rustc_data_structures::memmap::Mmap;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
+use rustc_session::Session;
/// The first few bytes of files generated by incremental compilation.
const FILE_MAGIC: &[u8] = b"RSIC";
/// the Git commit hash.
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
+pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
stream.emit_raw_bytes(FILE_MAGIC)?;
stream.emit_raw_bytes(&[
(HEADER_FORMAT_VERSION >> 0) as u8,
stream.emit_raw_bytes(rustc_version.as_bytes())
}
+pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
+where
+ F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
+{
+ debug!("save: storing data in {}", path_buf.display());
+
+ // Delete the old file, if any.
+ // Note: It's important that we actually delete the old file and not just
+ // truncate and overwrite it, since it might be a shared hard-link, the
+ // underlying data of which we don't want to modify.
+ //
+ // We have to ensure we have dropped the memory maps to this file
+ // before performing this removal.
+ match fs::remove_file(&path_buf) {
+ Ok(()) => {
+ debug!("save: remove old file");
+ }
+ Err(err) if err.kind() == io::ErrorKind::NotFound => (),
+ Err(err) => {
+ sess.err(&format!(
+ "unable to delete old {} at `{}`: {}",
+ name,
+ path_buf.display(),
+ err
+ ));
+ return;
+ }
+ }
+
+ let mut encoder = match FileEncoder::new(&path_buf) {
+ Ok(encoder) => encoder,
+ Err(err) => {
+ sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
+ return;
+ }
+ };
+
+ if let Err(err) = write_file_header(&mut encoder, sess.is_nightly_build()) {
+ sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
+ return;
+ }
+
+ if let Err(err) = encode(&mut encoder) {
+ sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
+ return;
+ }
+
+ if let Err(err) = encoder.flush() {
+ sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
+ return;
+ }
+
+ debug!("save: data written to disk successfully");
+}
+
/// Reads the contents of a file with a file header as defined in this module.
///
/// - Returns `Ok(Some(data, pos))` if the file existed and was generated by a
report_incremental_info: bool,
path: &Path,
nightly_build: bool,
-) -> io::Result<Option<(Vec<u8>, usize)>> {
- let data = match fs::read(path) {
- Ok(data) => data,
+) -> io::Result<Option<(Mmap, usize)>> {
+ let file = match fs::File::open(path) {
+ Ok(file) => file,
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
Err(err) => return Err(err),
};
+ // SAFETY: This process must not modify nor remove the backing file while the memory map lives.
+ // For the dep-graph and the work product index, it is as soon as the decoding is done.
+ // For the query result cache, the memory map is dropped in save_dep_graph before calling
+ // save_in and trying to remove the backing file.
+ //
+ // There is no way to prevent another process from modifying this file.
+ let mmap = unsafe { Mmap::map(file) }?;
- let mut file = io::Cursor::new(data);
+ let mut file = io::Cursor::new(&*mmap);
// Check FILE_MAGIC
{
}
let post_header_start_pos = file.position() as usize;
- Ok(Some((file.into_inner(), post_header_start_pos)))
+ Ok(Some((mmap, post_header_start_pos)))
}
fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &str) {
//! Code to save/load the dep-graph from files.
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::memmap::Mmap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::OnDiskCache;
use rustc_serialize::opaque::Decoder;
report_incremental_info: bool,
path: &Path,
nightly_build: bool,
-) -> LoadResult<(Vec<u8>, usize)> {
+) -> LoadResult<(Mmap, usize)> {
match file_format::read_file(report_incremental_info, path, nightly_build) {
Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
Ok(None) => {
use rustc_serialize::Encodable as RustcEncodable;
use rustc_session::Session;
use std::fs;
-use std::io;
-use std::path::PathBuf;
use super::data::*;
use super::dirty_clean;
join(
move || {
sess.time("incr_comp_persist_result_cache", || {
- save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e));
+ // Drop the memory map so that we can remove the file and write to it.
+ if let Some(odc) = &tcx.on_disk_cache {
+ odc.drop_serialized_data(tcx);
+ }
+
+ file_format::save_in(sess, query_cache_path, "query cache", |e| {
+ encode_query_cache(tcx, e)
+ });
});
},
move || {
debug!("save_work_product_index()");
dep_graph.assert_ignored();
let path = work_products_path(sess);
- save_in(sess, path, "work product index", |e| encode_work_product_index(&new_work_products, e));
+ file_format::save_in(sess, path, "work product index", |e| {
+ encode_work_product_index(&new_work_products, e)
+ });
// We also need to clean out old work-products, as not all of them are
// deleted during invalidation. Some object files don't change their
});
}
-pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
-where
- F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
-{
- debug!("save: storing data in {}", path_buf.display());
-
- // Delete the old file, if any.
- // Note: It's important that we actually delete the old file and not just
- // truncate and overwrite it, since it might be a shared hard-link, the
- // underlying data of which we don't want to modify
- match fs::remove_file(&path_buf) {
- Ok(()) => {
- debug!("save: remove old file");
- }
- Err(err) if err.kind() == io::ErrorKind::NotFound => (),
- Err(err) => {
- sess.err(&format!(
- "unable to delete old {} at `{}`: {}",
- name,
- path_buf.display(),
- err
- ));
- return;
- }
- }
-
- let mut encoder = match FileEncoder::new(&path_buf) {
- Ok(encoder) => encoder,
- Err(err) => {
- sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
- return;
- }
- };
-
- if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
- sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
- return;
- }
-
- if let Err(err) = encode(&mut encoder) {
- sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
- return;
- }
-
- if let Err(err) = encoder.flush() {
- sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
- return;
- }
-
- debug!("save: data written to disk successfully");
-}
-
fn encode_work_product_index(
work_products: &FxHashMap<WorkProductId, WorkProduct>,
encoder: &mut FileEncoder,
if self.type_vars.0.contains(&vid) {
// This variable was created during the fudging.
// Recreate it with a fresh variable here.
- let idx = (vid.index - self.type_vars.0.start.index) as usize;
+ let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
let origin = self.type_vars.1[idx];
self.infcx.next_ty_var(origin)
} else {
/// Note that this function does not return care whether
/// `vid` has been unified with something else or not.
pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
- self.storage.values.get(vid.index as usize).diverging
+ self.storage.values.get(vid.index()).diverging
}
/// Returns the origin that was given when `vid` was created.
/// Note that this function does not return care whether
/// `vid` has been unified with something else or not.
pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
- &self.storage.values.get(vid.index as usize).origin
+ &self.storage.values.get(vid.as_usize()).origin
}
/// Records that `a == b`, depending on `dir`.
assert_eq!(eq_key.vid, sub_key);
let index = self.values().push(TypeVariableData { origin, diverging });
- assert_eq!(eq_key.vid.index, index as u32);
+ assert_eq!(eq_key.vid.as_u32(), index as u32);
debug!(
"new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}",
&mut self,
value_count: usize,
) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
- let range = TyVid { index: value_count as u32 }..TyVid { index: self.num_vars() as u32 };
+ let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
(
range.start..range.end,
- (range.start.index..range.end.index)
- .map(|index| self.storage.values.get(index as usize).origin)
+ (range.start.as_usize()..range.end.as_usize())
+ .map(|index| self.storage.values.get(index).origin)
.collect(),
)
}
pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
(0..self.storage.values.len())
.filter_map(|i| {
- let vid = ty::TyVid { index: i as u32 };
+ let vid = ty::TyVid::from_usize(i);
match self.probe(vid) {
TypeVariableValue::Unknown { .. } => Some(vid),
TypeVariableValue::Known { .. } => None,
type Value = TypeVariableValue<'tcx>;
#[inline(always)]
fn index(&self) -> u32 {
- self.vid.index
+ self.vid.as_u32()
}
fn from_index(i: u32) -> Self {
- TyVidEqKey::from(ty::TyVid { index: i })
+ TyVidEqKey::from(ty::TyVid::from_u32(i))
}
fn tag() -> &'static str {
"TyVidEqKey"
arena,
);
- if sess.opts.debugging_opts.hir_stats {
- hir_stats::print_hir_stats(&hir_crate);
- }
-
sess.time("early_lint_checks", || {
rustc_lint::check_ast_crate(
sess,
// since the root module isn't visited as an item (because it isn't an
// item), warn for it here.
lint_callback!(cx, check_crate, krate);
-
- hir_visit::walk_crate(cx, krate);
-
+ tcx.hir().walk_toplevel_module(cx);
+ tcx.hir().walk_attributes(cx);
lint_callback!(cx, check_crate_post, krate);
})
}
let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
builder.levels.register_id(hir::CRATE_HIR_ID);
- intravisit::walk_crate(&mut builder, krate);
+ tcx.hir().walk_toplevel_module(&mut builder);
builder.levels.pop(push);
builder.levels.build_map()
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
-use rustc_hir::intravisit;
+use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::*;
use rustc_index::vec::Idx;
}
}
+ /// Walks the contents of a crate. See also `Crate::visit_all_items`.
+ pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
+ let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
+ visitor.visit_mod(top_mod, span, hir_id);
+ }
+
+ /// Walks the attributes in a crate.
+ pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
+ let krate = self.krate();
+ for (&id, attrs) in krate.attrs.iter() {
+ for a in *attrs {
+ visitor.visit_attribute(id, a)
+ }
+ }
+ }
+
pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
where
V: ItemLikeVisitor<'hir>,
&tcx.untracked_resolutions.definitions,
hcx,
);
- intravisit::walk_crate(&mut collector, tcx.untracked_crate);
+ let top_mod = tcx.untracked_crate.module();
+ collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
let map = collector.finalize_and_compute_crate_hash();
tcx.arena.alloc(map)
/// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
self.0.set_primary_message(msg);
+ self.0.set_is_lint();
self.0
}
desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
}
+ query own_existential_vtable_entries(
+ key: ty::PolyExistentialTraitRef<'tcx>
+ ) -> &'tcx [DefId] {
+ desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
+ }
+
query vtable_entries(key: ty::PolyTraitRef<'tcx>)
-> &'tcx [ty::VtblEntry<'tcx>] {
desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
- fn new(sess: &'tcx Session, data: Vec<u8>, start_pos: usize) -> Self
+ fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
where
Self: Sized;
fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode);
fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash);
+ fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
+
fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
}
use crate::ty::TyKind::*;
use crate::ty::{InferTy, TyCtxt, TyS};
-use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
def_id: Option<DefId>,
) {
// See if there's a `?Sized` bound that can be removed to suggest that.
- // First look at the `where` clause because we can have `where T: ?Sized`, but that
- // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks
- // the spans. Hence the somewhat involved logic that follows.
- let mut where_unsized_bounds = FxHashSet::default();
+ // First look at the `where` clause because we can have `where T: ?Sized`,
+ // then look at params.
for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
match predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate {
}) if segment.ident.as_str() == param_name => {
for (pos, bound) in bounds.iter().enumerate() {
match bound {
- hir::GenericBound::Unsized(_) => {}
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
if poly.trait_ref.trait_def_id() == def_id => {}
_ => continue,
// ^^^^^^^^^
(_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
};
- where_unsized_bounds.insert(bound.span());
err.span_suggestion_verbose(
sp,
"consider removing the `?Sized` bound to make the \
for (pos, bound) in param.bounds.iter().enumerate() {
match bound {
hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
- if poly.trait_ref.trait_def_id() == def_id
- && !where_unsized_bounds.contains(&bound.span()) =>
+ if poly.trait_ref.trait_def_id() == def_id =>
{
let sp = match (param.bounds.len(), pos) {
// T: ?Sized,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
pub proc_macros: Vec<LocalDefId>,
+ /// Mapping from ident span to path span for paths that don't exist as written, but that
+ /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
+ pub confused_type_with_std_module: FxHashMap<Span, Span>,
}
#[derive(Clone, Copy, Debug)]
let then_blk = unpack!(this.then_else_break(
block,
&this.thir[cond],
- condition_scope,
+ Some(condition_scope),
condition_scope,
then_expr.span,
));
&mut self,
mut block: BasicBlock,
expr: &Expr<'tcx>,
- temp_scope: region::Scope,
+ temp_scope_override: Option<region::Scope>,
break_scope: region::Scope,
variable_scope_span: Span,
) -> BlockAnd<()> {
this.then_else_break(
block,
&this.thir[value],
- temp_scope,
+ temp_scope_override,
break_scope,
variable_scope_span,
)
this.lower_let_expr(block, &this.thir[expr], pat, break_scope, variable_scope_span)
}
_ => {
+ let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
let mutability = Mutability::Mut;
let place =
unpack!(block = this.as_temp(block, Some(temp_scope), expr, mutability));
}
let arm_span = arm_span.unwrap();
- let arm_scope = self.local_scope();
let match_scope = match_scope.unwrap();
let mut guard_span = rustc_span::DUMMY_SP;
Guard::If(e) => {
let e = &this.thir[e];
guard_span = e.span;
- this.then_else_break(block, e, arm_scope, match_scope, arm_span)
+ this.then_else_break(block, e, None, match_scope, arm_span)
}
Guard::IfLet(ref pat, scrutinee) => {
let s = &this.thir[scrutinee];
let krate = tcx.hir().krate();
let live_symbols = find_live(tcx, access_levels, krate);
let mut visitor = DeadVisitor { tcx, live_symbols };
- intravisit::walk_crate(&mut visitor, krate);
+ tcx.hir().walk_toplevel_module(&mut visitor);
}
pub fn check_crate(tcx: TyCtxt<'_>) {
tcx.dep_graph.assert_ignored();
+ if tcx.sess.opts.debugging_opts.hir_stats {
+ crate::hir_stats::print_hir_stats(tcx);
+ }
+
let errors = Lock::new(Vec::new());
let hir_map = tcx.hir();
use rustc_hir::intravisit as hir_visit;
use rustc_hir::HirId;
use rustc_middle::hir::map::Map;
+use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str;
use rustc_span::Span;
}
struct StatCollector<'k> {
- krate: Option<&'k hir::Crate<'k>>,
+ krate: Option<Map<'k>>,
data: FxHashMap<&'static str, NodeData>,
seen: FxHashSet<Id>,
}
-pub fn print_hir_stats(krate: &hir::Crate<'_>) {
+pub fn print_hir_stats(tcx: TyCtxt<'_>) {
let mut collector = StatCollector {
- krate: Some(krate),
+ krate: Some(tcx.hir()),
data: FxHashMap::default(),
seen: FxHashSet::default(),
};
- hir_visit::walk_crate(&mut collector, krate);
+ tcx.hir().walk_toplevel_module(&mut collector);
+ tcx.hir().walk_attributes(&mut collector);
collector.print("HIR STATS");
}
use rustc_ast::{Attribute, MetaItem, MetaItemKind};
use rustc_errors::struct_span_err;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_middle::hir::map::Map;
use rustc_middle::middle::lib_features::LibFeatures;
use rustc_middle::ty::query::Providers;
fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
let mut collector = LibFeatureCollector::new(tcx);
- let krate = tcx.hir().krate();
-
- intravisit::walk_crate(&mut collector, krate);
+ tcx.hir().walk_attributes(&mut collector);
collector.lib_features
}
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::map::Map;
.collect();
{
- let krate = tcx.hir().krate();
let mut annotator = Annotator {
tcx,
index: &mut index,
annotator.annotate(
CRATE_DEF_ID,
- krate.module().inner,
+ tcx.hir().span(CRATE_HIR_ID),
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
InheritStability::No,
- |v| intravisit::walk_crate(v, krate),
+ |v| tcx.hir().walk_toplevel_module(v),
);
}
index
if tcx.stability().staged_api[&LOCAL_CRATE] {
let krate = tcx.hir().krate();
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
- missing.check_missing_stability(CRATE_DEF_ID, krate.module().inner);
- intravisit::walk_crate(&mut missing, krate);
+ missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
+ tcx.hir().walk_toplevel_module(&mut missing);
krate.visit_all_item_likes(&mut missing.as_deep_visitor());
}
changed: false,
};
loop {
- intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+ tcx.hir().walk_toplevel_module(&mut visitor);
if visitor.changed {
visitor.changed = false;
} else {
in_variant: false,
old_error_set: Default::default(),
};
- intravisit::walk_crate(&mut visitor, krate);
+ tcx.hir().walk_toplevel_module(&mut visitor);
let has_pub_restricted = {
let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false };
- intravisit::walk_crate(&mut pub_restricted_visitor, krate);
+ tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor);
pub_restricted_visitor.has_pub_restricted
};
}
}
+impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ self.def_id().krate == LOCAL_CRATE
+ }
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ tcx.def_span(self.def_id())
+ }
+}
+
impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
use crate::QueryCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
+use rustc_data_structures::memmap::Mmap;
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell, RwLock};
use rustc_data_structures::unhash::UnhashMap;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
/// any side effects that have been emitted during a query.
pub struct OnDiskCache<'sess> {
// The complete cache data in serialized form.
- serialized_data: Vec<u8>,
+ serialized_data: RwLock<Option<Mmap>>,
// Collects all `QuerySideEffects` created during the current compilation
// session.
}
impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
- fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
+ /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
+ fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
debug_assert!(sess.opts.incremental.is_some());
// Wrap in a scope so we can borrow `data`.
};
Self {
- serialized_data: data,
+ serialized_data: RwLock::new(Some(data)),
file_index_to_stable_id: footer.file_index_to_stable_id,
file_index_to_file: Default::default(),
cnum_map: OnceCell::new(),
fn new_empty(source_map: &'sess SourceMap) -> Self {
Self {
- serialized_data: Vec::new(),
+ serialized_data: RwLock::new(None),
file_index_to_stable_id: Default::default(),
file_index_to_file: Default::default(),
cnum_map: OnceCell::new(),
}
}
- fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult {
+ /// Execute all cache promotions and release the serialized backing Mmap.
+ ///
+ /// Cache promotions require invoking queries, which needs to read the serialized data.
+ /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be
+ /// deleted, hence we won't be able to refer to its memmapped data.
+ fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) {
+ // Register any dep nodes that we reused from the previous session,
+ // but didn't `DepNode::construct` in this session. This ensures
+ // that their `DefPathHash` to `RawDefId` mappings are registered
+ // in 'latest_foreign_def_path_hashes' if necessary, since that
+ // normally happens in `DepNode::construct`.
+ tcx.dep_graph.register_reused_dep_nodes(tcx);
+
+ // Load everything into memory so we can write it out to the on-disk
+ // cache. The vast majority of cacheable query results should already
+ // be in memory, so this should be a cheap operation.
+ // Do this *before* we clone 'latest_foreign_def_path_hashes', since
+ // loading existing queries may cause us to create new DepNodes, which
+ // may in turn end up invoking `store_foreign_def_id_hash`
+ tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
+
+ *self.serialized_data.write() = None;
+ }
+
+ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult {
// Serializing the `DepGraph` should not modify it.
tcx.dep_graph.with_ignore(|| {
// Allocate `SourceFileIndex`es.
(file_to_file_index, file_index_to_stable_id)
};
- // Register any dep nodes that we reused from the previous session,
- // but didn't `DepNode::construct` in this session. This ensures
- // that their `DefPathHash` to `RawDefId` mappings are registered
- // in 'latest_foreign_def_path_hashes' if necessary, since that
- // normally happens in `DepNode::construct`.
- tcx.dep_graph.register_reused_dep_nodes(tcx);
-
- // Load everything into memory so we can write it out to the on-disk
- // cache. The vast majority of cacheable query results should already
- // be in memory, so this should be a cheap operation.
- // Do this *before* we clone 'latest_foreign_def_path_hashes', since
- // loading existing queries may cause us to create new DepNodes, which
- // may in turn end up invoking `store_foreign_def_id_hash`
- tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
-
let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
let hygiene_encode_context = HygieneEncodeContext::default();
})
}
- fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+ fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(
&'sess self,
tcx: TyCtxt<'tcx>,
pos: AbsoluteBytePos,
{
let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
+ let serialized_data = self.serialized_data.read();
let mut decoder = CacheDecoder {
tcx,
- opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
+ opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
source_map: self.source_map,
cnum_map,
file_index_to_file: &self.file_index_to_file,
let item_span =
path.iter().last().map_or(span, |segment| segment.ident.span);
- let mut hm = self.r.session.confused_type_with_std_module.borrow_mut();
- hm.insert(item_span, span);
- hm.insert(span, span);
+ self.r.confused_type_with_std_module.insert(item_span, span);
+ self.r.confused_type_with_std_module.insert(span, span);
}
}
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
+ confused_type_with_std_module: FxHashMap<Span, Span>,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
main_def: Default::default(),
trait_impls: Default::default(),
proc_macros: Default::default(),
+ confused_type_with_std_module: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
let glob_map = self.glob_map;
let main_def = self.main_def;
+ let confused_type_with_std_module = self.confused_type_with_std_module;
ResolverOutputs {
definitions,
cstore: Box::new(self.crate_loader.into_cstore()),
main_def,
trait_impls: self.trait_impls,
proc_macros,
+ confused_type_with_std_module,
}
}
main_def: self.main_def.clone(),
trait_impls: self.trait_impls.clone(),
proc_macros,
+ confused_type_with_std_module: self.confused_type_with_std_module.clone(),
}
}
(Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
}
hir::GenericBound::Outlives(..) => continue,
- hir::GenericBound::Unsized(_) => continue,
};
if let Some(id) = def_id {
attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
},
);
- intravisit::walk_crate(self, krate);
+ self.tcx.hir().walk_toplevel_module(self);
}
fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
/// Cap lint level specified by a driver specifically.
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
- /// Mapping from ident span to path span for paths that don't exist as written, but that
- /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
- pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
-
/// Tracks the current behavior of the CTFE engine when an error occurs.
/// Options range from returning the error without a backtrace to returning an error
/// and immediately printing the backtrace to stderr.
print_fuel,
jobserver: jobserver::client(),
driver_lint_caps,
- confused_type_with_std_module: Lock::new(Default::default()),
ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()),
asm_arch,
let sig = if let ty::Tuple(inputs) = inputs.kind() {
tcx.mk_fn_sig(
inputs.iter().map(|k| k.expect_ty()),
- tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+ tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
false,
hir::Unsafety::Normal,
abi::Abi::Rust,
} else {
tcx.mk_fn_sig(
std::iter::once(inputs),
- tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+ tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
false,
hir::Unsafety::Normal,
abi::Abi::Rust,
tcx.sess.struct_span_err(sp, &msg).emit();
}
+fn own_existential_vtable_entries<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+) -> &'tcx [DefId] {
+ let trait_methods = tcx
+ .associated_items(trait_ref.def_id())
+ .in_definition_order()
+ .filter(|item| item.kind == ty::AssocKind::Fn);
+ // Now list each method's DefId (for within its trait).
+ let own_entries = trait_methods.filter_map(move |trait_method| {
+ debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+ let def_id = trait_method.def_id;
+
+ // Some methods cannot be called on an object; skip those.
+ if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+ debug!("own_existential_vtable_entry: not vtable safe");
+ return None;
+ }
+
+ Some(def_id)
+ });
+
+ tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
/// Given a trait `trait_ref`, iterates the vtable entries
/// that come from `trait_ref`, including its supertraits.
fn vtable_entries<'tcx>(
entries.extend(COMMON_VTABLE_ENTRIES);
}
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- let trait_methods = tcx
- .associated_items(trait_ref.def_id())
- .in_definition_order()
- .filter(|item| item.kind == ty::AssocKind::Fn);
- // Now list each method's DefId and InternalSubsts (for within its trait).
- // If the method can never be called from this object, produce `Vacant`.
- let own_entries = trait_methods.map(move |trait_method| {
- debug!("vtable_entries: trait_method={:?}", trait_method);
- let def_id = trait_method.def_id;
-
- // Some methods cannot be called on an object; skip those.
- if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
- debug!("vtable_entries: not vtable safe");
- return VtblEntry::Vacant;
- }
+ let existential_trait_ref = trait_ref
+ .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+ // Lookup the shape of vtable for the trait.
+ let own_existential_entries =
+ tcx.own_existential_vtable_entries(existential_trait_ref);
+
+ let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+ debug!("vtable_entries: trait_method={:?}", def_id);
// The method may have some early-bound lifetimes; add regions for those.
let substs = trait_ref.map_bound(|trait_ref| {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+ own_existential_vtable_entries,
vtable_entries,
vtable_trait_upcasting_coercion_new_vptr_slot,
subst_and_check_impossible_predicates,
/// that come from `trait_ref`, excluding its supertraits. Used in
/// computing the vtable base for an upcast trait of a trait object.
pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
- let mut entries = 0;
- // Count number of methods and add them to the total offset.
- // Skip over associated types and constants.
- for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
- if trait_item.kind == ty::AssocKind::Fn {
- entries += 1;
- }
- }
- entries
+ let existential_trait_ref =
+ trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+ let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
+ tcx.own_existential_vtable_entries(existential_trait_ref).len()
}
/// Given an upcast trait object described by `object`, returns the
object: &super::ImplSourceObjectData<'tcx, N>,
method_def_id: DefId,
) -> usize {
+ let existential_trait_ref = object
+ .upcast_trait_ref
+ .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+ let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
// Count number of methods preceding the one we are selecting and
// add them to the total offset.
- // Skip over associated types and constants, as those aren't stored in the vtable.
- let mut entries = object.vtable_base;
- for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
- if trait_item.def_id == method_def_id {
- // The item with the ID we were given really ought to be a method.
- assert_eq!(trait_item.kind, ty::AssocKind::Fn);
- return entries;
- }
- if trait_item.kind == ty::AssocKind::Fn {
- entries += 1;
- }
- }
-
- bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+ let index = tcx
+ .own_existential_vtable_entries(existential_trait_ref)
+ .iter()
+ .copied()
+ .position(|def_id| def_id == method_def_id)
+ .unwrap_or_else(|| {
+ bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+ });
+ object.vtable_base + index
}
pub fn closure_trait_ref_and_return_type(
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct FloatVarValue(pub FloatTy);
-/// A **ty**pe **v**ariable **ID**.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-pub struct TyVid {
- pub index: u32,
+rustc_index::newtype_index! {
+ /// A **ty**pe **v**ariable **ID**.
+ pub struct TyVid {
+ DEBUG_FORMAT = "_#{}t"
+ }
}
/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
impl UnifyKey for TyVid {
type Value = ();
fn index(&self) -> u32 {
- self.index
+ self.as_u32()
}
fn from_index(i: u32) -> TyVid {
- TyVid { index: i }
+ TyVid::from_u32(i)
}
fn tag() -> &'static str {
"TyVid"
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
use InferTy::*;
match self {
- TyVar(v) => v.index.hash_stable(ctx, hasher),
+ TyVar(v) => v.as_u32().hash_stable(ctx, hasher),
IntVar(v) => v.index.hash_stable(ctx, hasher),
FloatVar(v) => v.index.hash_stable(ctx, hasher),
FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
}
}
-impl fmt::Debug for TyVid {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "_#{}t", self.index)
- }
-}
-
impl fmt::Debug for IntVid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "_#{}i", self.index)
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
}
-pub enum SizedByDefault {
- Yes,
- No,
-}
-
#[derive(Debug)]
struct ConvertedBinding<'a, 'tcx> {
hir_id: hir::HirId,
)
}
+ fn instantiate_poly_trait_ref_inner(
+ &self,
+ hir_id: hir::HirId,
+ span: Span,
+ binding_span: Option<Span>,
+ constness: ty::BoundConstness,
+ bounds: &mut Bounds<'tcx>,
+ speculative: bool,
+ trait_ref_span: Span,
+ trait_def_id: DefId,
+ trait_segment: &hir::PathSegment<'_>,
+ args: &GenericArgs<'_>,
+ infer_args: bool,
+ self_ty: Ty<'tcx>,
+ ) -> GenericArgCountResult {
+ let (substs, arg_count) = self.create_substs_for_ast_path(
+ trait_ref_span,
+ trait_def_id,
+ &[],
+ trait_segment,
+ args,
+ infer_args,
+ Some(self_ty),
+ );
+
+ let tcx = self.tcx();
+ let bound_vars = tcx.late_bound_vars(hir_id);
+ debug!(?bound_vars);
+
+ let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
+
+ let poly_trait_ref =
+ ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+
+ debug!(?poly_trait_ref, ?assoc_bindings);
+ bounds.trait_bounds.push((poly_trait_ref, span, constness));
+
+ let mut dup_bindings = FxHashMap::default();
+ for binding in &assoc_bindings {
+ // Specify type to assert that error was already reported in `Err` case.
+ let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+ hir_id,
+ poly_trait_ref,
+ binding,
+ bounds,
+ speculative,
+ &mut dup_bindings,
+ binding_span.unwrap_or(binding.span),
+ );
+ // Okay to ignore `Err` because of `ErrorReported` (see above).
+ }
+
+ arg_count
+ }
+
/// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
/// a full trait reference. The resulting trait reference is returned. This may also generate
/// auxiliary bounds, which are added to `bounds`.
/// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
/// however.
#[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
- pub fn instantiate_poly_trait_ref(
+ pub(crate) fn instantiate_poly_trait_ref(
&self,
trait_ref: &hir::TraitRef<'_>,
span: Span,
bounds: &mut Bounds<'tcx>,
speculative: bool,
) -> GenericArgCountResult {
+ let hir_id = trait_ref.hir_ref_id;
+ let binding_span = None;
+ let trait_ref_span = trait_ref.path.span;
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+ let trait_segment = trait_ref.path.segments.last().unwrap();
+ let args = trait_segment.args();
+ let infer_args = trait_segment.infer_args;
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+ self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
- let tcx = self.tcx();
- let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
- debug!(?bound_vars);
-
- let (substs, arg_count) = self.create_substs_for_ast_trait_ref(
- trait_ref.path.span,
+ self.instantiate_poly_trait_ref_inner(
+ hir_id,
+ span,
+ binding_span,
+ constness,
+ bounds,
+ speculative,
+ trait_ref_span,
trait_def_id,
+ trait_segment,
+ args,
+ infer_args,
self_ty,
- trait_ref.path.segments.last().unwrap(),
- );
- let assoc_bindings = self
- .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args());
-
- let poly_trait_ref =
- ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-
- debug!(?poly_trait_ref, ?assoc_bindings);
- bounds.trait_bounds.push((poly_trait_ref, span, constness));
-
- let mut dup_bindings = FxHashMap::default();
- for binding in &assoc_bindings {
- // Specify type to assert that error was already reported in `Err` case.
- let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
- trait_ref.hir_ref_id,
- poly_trait_ref,
- binding,
- bounds,
- speculative,
- &mut dup_bindings,
- binding.span,
- );
- // Okay to ignore `Err` because of `ErrorReported` (see above).
- }
-
- arg_count
+ )
}
- pub fn instantiate_lang_item_trait_ref(
+ pub(crate) fn instantiate_lang_item_trait_ref(
&self,
lang_item: hir::LangItem,
span: Span,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
) {
+ let binding_span = Some(span);
+ let constness = ty::BoundConstness::NotConst;
+ let speculative = false;
+ let trait_ref_span = span;
let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+ let trait_segment = &hir::PathSegment::invalid();
+ let infer_args = false;
- let (substs, _) = self.create_substs_for_ast_path(
+ self.instantiate_poly_trait_ref_inner(
+ hir_id,
span,
+ binding_span,
+ constness,
+ bounds,
+ speculative,
+ trait_ref_span,
trait_def_id,
- &[],
- &hir::PathSegment::invalid(),
+ trait_segment,
args,
- false,
- Some(self_ty),
+ infer_args,
+ self_ty,
);
- let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
- let tcx = self.tcx();
- let bound_vars = tcx.late_bound_vars(hir_id);
- let poly_trait_ref =
- ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
- bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst));
-
- let mut dup_bindings = FxHashMap::default();
- for binding in assoc_bindings {
- let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
- hir_id,
- poly_trait_ref,
- &binding,
- bounds,
- false,
- &mut dup_bindings,
- span,
- );
- }
}
fn ast_path_to_mono_trait_ref(
.is_some()
}
- // Returns `true` if a bounds list includes `?Sized`.
- pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+ // Sets `implicitly_sized` to true on `Bounds` if necessary
+ pub(crate) fn add_implicitly_sized<'hir>(
+ &self,
+ bounds: &mut Bounds<'hir>,
+ ast_bounds: &'hir [hir::GenericBound<'hir>],
+ self_ty_where_predicates: Option<(hir::HirId, &'hir [hir::WherePredicate<'hir>])>,
+ span: Span,
+ ) {
let tcx = self.tcx();
// Try to find an unbound in bounds.
let mut unbound = None;
- for ab in ast_bounds {
- if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
- if unbound.is_none() {
- unbound = Some(&ptr.trait_ref);
- } else {
- tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+ let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
+ for ab in ast_bounds {
+ if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
+ if unbound.is_none() {
+ unbound = Some(&ptr.trait_ref);
+ } else {
+ tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+ }
}
}
- }
-
- let kind_id = tcx.lang_items().require(LangItem::Sized);
- match unbound {
- Some(tpb) => {
- // FIXME(#8559) currently requires the unbound to be built-in.
- if let Ok(kind_id) = kind_id {
- if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
- tcx.sess.span_warn(
- span,
- "default bound relaxed for a type parameter, but \
- this does nothing because the given bound is not \
- a default; only `?Sized` is supported",
- );
- return false;
+ };
+ search_bounds(ast_bounds);
+ if let Some((self_ty, where_clause)) = self_ty_where_predicates {
+ let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id();
+ for clause in where_clause {
+ match clause {
+ hir::WherePredicate::BoundPredicate(pred) => {
+ match pred.bounded_ty.kind {
+ hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
+ Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {}
+ _ => continue,
+ },
+ _ => continue,
+ }
+ search_bounds(pred.bounds);
}
+ _ => {}
}
}
- _ if kind_id.is_ok() => {
- return false;
+ }
+
+ let sized_def_id = tcx.lang_items().require(LangItem::Sized);
+ match (&sized_def_id, unbound) {
+ (Ok(sized_def_id), Some(tpb))
+ if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
+ {
+ // There was in fact a `?Sized` bound, return without doing anything
+ return;
+ }
+ (_, Some(_)) => {
+ // There was a `?Trait` bound, but it was not `?Sized`; warn.
+ tcx.sess.span_warn(
+ span,
+ "default bound relaxed for a type parameter, but \
+ this does nothing because the given bound is not \
+ a default; only `?Sized` is supported",
+ );
+ // Otherwise, add implicitly sized if `Sized` is available.
}
+ _ => {
+ // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
+ }
+ }
+ if sized_def_id.is_err() {
// No lang item for `Sized`, so we can't add it as a bound.
- None => {}
+ return;
}
-
- true
+ bounds.implicitly_sized = Some(span);
}
/// This helper takes a *converted* parameter type (`param_ty`)
/// **A note on binders:** there is an implied binder around
/// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
/// for more details.
- #[tracing::instrument(level = "debug", skip(self, bounds))]
- fn add_bounds(
+ #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))]
+ pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
&self,
param_ty: Ty<'tcx>,
- ast_bounds: &[hir::GenericBound<'_>],
+ ast_bounds: I,
bounds: &mut Bounds<'tcx>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
) {
for ast_bound in ast_bounds {
- match *ast_bound {
- hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
- self.instantiate_poly_trait_ref(
- &b.trait_ref,
- b.span,
- ty::BoundConstness::NotConst,
+ match ast_bound {
+ hir::GenericBound::Trait(poly_trait_ref, modifier) => {
+ let constness = match modifier {
+ hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
+ hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+ hir::TraitBoundModifier::Maybe => continue,
+ };
+
+ let _ = self.instantiate_poly_trait_ref(
+ &poly_trait_ref.trait_ref,
+ poly_trait_ref.span,
+ constness,
param_ty,
bounds,
false,
);
}
- hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
- self.instantiate_poly_trait_ref(
- &b.trait_ref,
- b.span,
- ty::BoundConstness::ConstIfConst,
- param_ty,
- bounds,
- false,
+ &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
+ self.instantiate_lang_item_trait_ref(
+ lang_item, span, hir_id, args, param_ty, bounds,
);
}
- hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe)
- | hir::GenericBound::Unsized(_) => {}
- hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
- .instantiate_lang_item_trait_ref(
- lang_item, span, hir_id, args, param_ty, bounds,
- ),
- hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push((
- ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars),
- l.span,
- )),
+ hir::GenericBound::Outlives(lifetime) => {
+ let region = self.ast_region_to_region(lifetime, None);
+ bounds
+ .region_bounds
+ .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
+ }
}
}
}
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
///
/// `span` should be the declaration size of the parameter.
- pub fn compute_bounds(
+ pub(crate) fn compute_bounds(
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
- sized_by_default: SizedByDefault,
- span: Span,
) -> Bounds<'tcx> {
- self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
+ self.compute_bounds_inner(param_ty, &ast_bounds)
}
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
/// named `assoc_name` into ty::Bounds. Ignore the rest.
- pub fn compute_bounds_that_match_assoc_type(
+ pub(crate) fn compute_bounds_that_match_assoc_type(
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
- sized_by_default: SizedByDefault,
- span: Span,
assoc_name: Ident,
) -> Bounds<'tcx> {
let mut result = Vec::new();
}
}
- self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
+ self.compute_bounds_inner(param_ty, &result)
}
fn compute_bounds_inner(
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
- sized_by_default: SizedByDefault,
- span: Span,
) -> Bounds<'tcx> {
let mut bounds = Bounds::default();
- self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
-
- bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
- if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
- } else {
- None
- };
+ self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
bounds
}
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder.
let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
- self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars());
+ self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
}
}
Ok(())
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
if let (true, Ok(snippet)) = (
self.tcx()
- .sess
+ .resolutions(())
.confused_type_with_std_module
- .borrow()
.keys()
.any(|full_span| full_span.contains(span)),
self.tcx().sess.source_map().span_to_snippet(span),
variant,
fields,
base_expr.is_none(),
+ expr.span,
);
if let Some(base_expr) = base_expr {
// If check_expr_struct_fields hit an error, do not attempt to populate
variant: &'tcx ty::VariantDef,
ast_fields: &'tcx [hir::ExprField<'tcx>],
check_completeness: bool,
+ expr_span: Span,
) -> bool {
let tcx = self.tcx;
ident,
});
} else {
- self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span);
+ self.report_unknown_field(
+ adt_ty, variant, field, ast_fields, kind_name, expr_span,
+ );
}
tcx.ty_error()
field: &hir::ExprField<'_>,
skip_fields: &[hir::ExprField<'_>],
kind_name: &str,
- ty_span: Span,
+ expr_span: Span,
) {
if variant.is_recovered() {
self.set_tainted_by_errors();
),
);
err.span_label(field.ident.span, "field does not exist");
- err.span_suggestion(
- ty_span,
+ err.span_suggestion_verbose(
+ expr_span,
&format!(
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
adt = ty,
_ => {
err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
err.span_label(field.ident.span, "field does not exist");
- err.span_suggestion(
- ty_span,
+ err.span_suggestion_verbose(
+ expr_span,
&format!(
"`{adt}` is a tuple {kind_name}, use the appropriate syntax",
adt = ty,
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
-use rustc_hir::intravisit;
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
}
}
if let Some(span) =
- tcx.sess.confused_type_with_std_module.borrow().get(&span)
+ tcx.resolutions(()).confused_type_with_std_module.get(&span)
{
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
err.span_suggestion(
let projection_ty = pred.skip_binder().projection_ty;
let substs_with_infer_self = tcx.mk_substs(
- iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
+ iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
.chain(projection_ty.substs.iter().skip(1)),
);
err.note(&format!(
"the following trait bounds were not satisfied:\n{bound_list}"
));
+ self.suggest_derive(&mut err, &unsatisfied_predicates);
+
unsatisfied_bounds = true;
}
}
None
}
+ fn suggest_derive(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ unsatisfied_predicates: &Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
+ ) {
+ let derivables = [
+ sym::Eq,
+ sym::PartialEq,
+ sym::Ord,
+ sym::PartialOrd,
+ sym::Clone,
+ sym::Copy,
+ sym::Hash,
+ sym::Default,
+ sym::debug_trait,
+ ];
+ let mut derives = unsatisfied_predicates
+ .iter()
+ .filter_map(|(pred, _)| {
+ let trait_pred =
+ if let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() {
+ trait_pred
+ } else {
+ return None;
+ };
+ let trait_ref = trait_pred.trait_ref;
+ let adt_def = if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() {
+ adt_def
+ } else {
+ return None;
+ };
+ if adt_def.did.is_local() {
+ let diagnostic_items = self.tcx.diagnostic_items(trait_ref.def_id.krate);
+ return derivables.iter().find_map(|trait_derivable| {
+ let item_def_id =
+ if let Some(item_def_id) = diagnostic_items.get(trait_derivable) {
+ item_def_id
+ } else {
+ return None;
+ };
+ if item_def_id == &trait_pred.trait_ref.def_id
+ && !(adt_def.is_enum() && *trait_derivable == sym::Default)
+ {
+ return Some((
+ format!("{}", trait_ref.self_ty()),
+ self.tcx.def_span(adt_def.did),
+ format!("{}", trait_ref.print_only_trait_path()),
+ ));
+ }
+ None
+ });
+ }
+ None
+ })
+ .collect::<Vec<(String, Span, String)>>();
+ derives.sort();
+ let derives_grouped = derives.into_iter().fold(
+ Vec::<(String, Span, String)>::new(),
+ |mut acc, (self_name, self_span, trait_name)| {
+ if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
+ if acc_self_name == &self_name {
+ traits.push_str(format!(", {}", trait_name).as_str());
+ return acc;
+ }
+ }
+ acc.push((self_name, self_span, trait_name));
+ acc
+ },
+ );
+ for (self_name, self_span, traits) in &derives_grouped {
+ err.span_suggestion_verbose(
+ self_span.shrink_to_lo(),
+ &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
+ format!("#[derive({})]\n", traits),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+
/// Print out the type for use in value namespace.
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
match ty.kind() {
candidates: Vec<DefId>,
) {
let module_did = self.tcx.parent_module(self.body_id);
- let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
- let krate = self.tcx.hir().krate();
- let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
+ let (span, found_use) = find_use_placement(self.tcx, module_did);
if let Some(span) = span {
let path_strings = candidates.iter().map(|did| {
// Produce an additional newline to separate the new use statement
providers.all_traits = compute_all_traits;
}
-struct UsePlacementFinder<'tcx> {
- target_module: hir::HirId,
- span: Option<Span>,
- found_use: bool,
- tcx: TyCtxt<'tcx>,
-}
-
-impl UsePlacementFinder<'tcx> {
- fn check(
- tcx: TyCtxt<'tcx>,
- krate: &'tcx hir::Crate<'tcx>,
- target_module: hir::HirId,
- ) -> (Option<Span>, bool) {
- let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
- intravisit::walk_crate(&mut finder, krate);
- (finder.span, finder.found_use)
- }
-}
-
-impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
- fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
- if self.span.is_some() {
- return;
- }
- if hir_id != self.target_module {
- intravisit::walk_mod(self, module, hir_id);
- return;
- }
- // Find a `use` statement.
- for &item_id in module.item_ids {
- let item = self.tcx.hir().item(item_id);
- match item.kind {
- hir::ItemKind::Use(..) => {
- // Don't suggest placing a `use` before the prelude
- // import or other generated ones.
- if !item.span.from_expansion() {
- self.span = Some(item.span.shrink_to_lo());
- self.found_use = true;
- return;
- }
+fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {
+ let mut span = None;
+ let mut found_use = false;
+ let (module, _, _) = tcx.hir().get_module(target_module);
+
+ // Find a `use` statement.
+ for &item_id in module.item_ids {
+ let item = tcx.hir().item(item_id);
+ match item.kind {
+ hir::ItemKind::Use(..) => {
+ // Don't suggest placing a `use` before the prelude
+ // import or other generated ones.
+ if !item.span.from_expansion() {
+ span = Some(item.span.shrink_to_lo());
+ found_use = true;
+ break;
}
- // Don't place `use` before `extern crate`...
- hir::ItemKind::ExternCrate(_) => {}
- // ...but do place them before the first other item.
- _ => {
- if self.span.map_or(true, |span| item.span < span) {
- if !item.span.from_expansion() {
- self.span = Some(item.span.shrink_to_lo());
- // Don't insert between attributes and an item.
- let attrs = self.tcx.hir().attrs(item.hir_id());
- // Find the first attribute on the item.
- // FIXME: This is broken for active attributes.
- for attr in attrs {
- if !attr.span.is_dummy()
- && self.span.map_or(true, |span| attr.span < span)
- {
- self.span = Some(attr.span.shrink_to_lo());
- }
+ }
+ // Don't place `use` before `extern crate`...
+ hir::ItemKind::ExternCrate(_) => {}
+ // ...but do place them before the first other item.
+ _ => {
+ if span.map_or(true, |span| item.span < span) {
+ if !item.span.from_expansion() {
+ span = Some(item.span.shrink_to_lo());
+ // Don't insert between attributes and an item.
+ let attrs = tcx.hir().attrs(item.hir_id());
+ // Find the first attribute on the item.
+ // FIXME: This is broken for active attributes.
+ for attr in attrs {
+ if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) {
+ span = Some(attr.span.shrink_to_lo());
}
}
}
}
}
- type Map = intravisit::ErasedMap<'tcx>;
-
- fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
- intravisit::NestedVisitorMap::None
- }
+ (span, found_use)
}
fn print_disambiguation_help(
}
};
+ // This restriction needs to be applied after we have handled adjustments for `move`
+ // closures. We want to make sure any adjustment that might make us move the place into
+ // the closure gets handled.
+ let (place, capture_kind) =
+ restrict_precision_for_drop_types(self, place, capture_kind, usage_span);
+
capture_info.capture_kind = capture_kind;
+
let capture_info = if let Some(existing) = processed.get(&place) {
determine_capture_info(*existing, capture_info)
} else {
self.tcx.struct_span_lint_hir(
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
closure_hir_id,
- closure_head_span,
+ closure_head_span,
|lint| {
let mut diagnostics_builder = lint.build(
format!(
self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
}
}
+
+/// Rust doesn't permit moving fields out of a type that implements drop
+fn restrict_precision_for_drop_types<'a, 'tcx>(
+ fcx: &'a FnCtxt<'a, 'tcx>,
+ mut place: Place<'tcx>,
+ mut curr_mode: ty::UpvarCapture<'tcx>,
+ span: Span,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+ let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span);
+
+ if let (false, UpvarCapture::ByValue(..)) = (is_copy_type, curr_mode) {
+ for i in 0..place.projections.len() {
+ match place.ty_before_projection(i).kind() {
+ ty::Adt(def, _) if def.destructor(fcx.tcx).is_some() => {
+ truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
+ break;
+ }
+ _ => {}
+ }
+ }
+ }
+
+ (place, curr_mode)
+}
+
/// Truncate `place` so that an `unsafe` block isn't required to capture it.
/// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
/// them completely.
//! At present, however, we do run collection across all items in the
//! crate as a kind of pass. This should eventually be factored away.
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
use crate::bounds::Bounds;
use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::constrained_generic_params as cgp;
&icx,
self_param_ty,
&bounds,
- SizedByDefault::No,
- item.span,
assoc_name,
)
} else {
- <dyn AstConv<'_>>::compute_bounds(
- &icx,
- self_param_ty,
- &bounds,
- SizedByDefault::No,
- item.span,
- )
+ <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, &bounds)
};
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
index += 1;
- let sized = SizedByDefault::Yes;
- let bounds = <dyn AstConv<'_>>::compute_bounds(
+ let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, param_ty, ¶m.bounds);
+ // Params are implicitly sized unless a `?Sized` bound is found
+ <dyn AstConv<'_>>::add_implicitly_sized(
&icx,
- param_ty,
+ &mut bounds,
¶m.bounds,
- sized,
+ Some((param.hir_id, ast_generics.where_clause.predicates)),
param.span,
);
predicates.extend(bounds.predicates(tcx, param_ty));
}
}
- for bound in bound_pred.bounds.iter() {
- match bound {
- hir::GenericBound::Trait(poly_trait_ref, modifier) => {
- let constness = match modifier {
- hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
- hir::TraitBoundModifier::MaybeConst => {
- ty::BoundConstness::ConstIfConst
- }
- // We ignore `where T: ?Sized`, it is already part of
- // type parameter `T`.
- hir::TraitBoundModifier::Maybe => continue,
- };
-
- let mut bounds = Bounds::default();
- let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
- &icx,
- &poly_trait_ref.trait_ref,
- poly_trait_ref.span,
- constness,
- ty,
- &mut bounds,
- false,
- );
- predicates.extend(bounds.predicates(tcx, ty));
- }
-
- &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
- let mut bounds = Bounds::default();
- <dyn AstConv<'_>>::instantiate_lang_item_trait_ref(
- &icx,
- lang_item,
- span,
- hir_id,
- args,
- ty,
- &mut bounds,
- );
- predicates.extend(bounds.predicates(tcx, ty));
- }
-
- hir::GenericBound::Unsized(_) => {}
-
- hir::GenericBound::Outlives(lifetime) => {
- let region =
- <dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
- predicates.insert((
- ty::Binder::bind_with_vars(
- ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
- ty, region,
- )),
- bound_vars,
- )
- .to_predicate(tcx),
- lifetime.span,
- ));
- }
- }
- }
+ let mut bounds = Bounds::default();
+ <dyn AstConv<'_>>::add_bounds(
+ &icx,
+ ty,
+ bound_pred.bounds.iter(),
+ &mut bounds,
+ bound_vars,
+ );
+ predicates.extend(bounds.predicates(tcx, ty));
}
hir::WherePredicate::RegionPredicate(region_pred) => {
param_ty: Ty<'tcx>,
bound: &'tcx hir::GenericBound<'tcx>,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
- match *bound {
- hir::GenericBound::Trait(ref tr, modifier) => {
- let constness = match modifier {
- hir::TraitBoundModifier::Maybe => return vec![],
- hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
- hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
- };
-
- let mut bounds = Bounds::default();
- let _ = astconv.instantiate_poly_trait_ref(
- &tr.trait_ref,
- tr.span,
- constness,
- param_ty,
- &mut bounds,
- false,
- );
- bounds.predicates(astconv.tcx(), param_ty)
- }
- hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
- let mut bounds = Bounds::default();
- astconv.instantiate_lang_item_trait_ref(
- lang_item,
- span,
- hir_id,
- args,
- param_ty,
- &mut bounds,
- );
- bounds.predicates(astconv.tcx(), param_ty)
- }
- hir::GenericBound::Unsized(_) => vec![],
- hir::GenericBound::Outlives(ref lifetime) => {
- let region = astconv.ast_region_to_region(lifetime, None);
- let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
- .to_predicate(astconv.tcx());
- vec![(pred, lifetime.span)]
- }
- }
+ let mut bounds = Bounds::default();
+ astconv.add_bounds(
+ param_ty,
+ std::array::IntoIter::new([bound]),
+ &mut bounds,
+ ty::List::empty(),
+ );
+ bounds.predicates(astconv.tcx(), param_ty)
}
fn compute_sig_of_foreign_fn_decl<'tcx>(
use super::ItemCtxt;
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
fn associated_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_item_def_id: DefId,
- bounds: &'tcx [hir::GenericBound<'tcx>],
+ ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
let item_ty = tcx.mk_projection(
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
);
- let bounds = <dyn AstConv<'_>>::compute_bounds(
- &ItemCtxt::new(tcx, assoc_item_def_id),
- item_ty,
- &bounds,
- SizedByDefault::Yes,
- span,
- );
+ let icx = ItemCtxt::new(tcx, assoc_item_def_id);
+ let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+ // Associated types are implicitly sized unless a `?Sized` bound is found
+ <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
fn opaque_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
opaque_def_id: DefId,
- bounds: &'tcx [hir::GenericBound<'tcx>],
+ ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
ty::print::with_no_queries(|| {
let item_ty =
tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
- let bounds = <dyn AstConv<'_>>::compute_bounds(
- &ItemCtxt::new(tcx, opaque_def_id),
- item_ty,
- &bounds,
- SizedByDefault::Yes,
- span,
- )
- .predicates(tcx, item_ty);
+ let icx = ItemCtxt::new(tcx, opaque_def_id);
+ let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+ // Opaque types are implicitly sized unless a `?Sized` bound is found
+ <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
+ let bounds = bounds.predicates(tcx, item_ty);
debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
debug!("find_opaque_ty_constraints: scope={:?}", scope);
if scope == hir::CRATE_HIR_ID {
- intravisit::walk_crate(&mut locator, tcx.hir().krate());
+ tcx.hir().walk_toplevel_module(&mut locator);
} else {
debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
match tcx.hir().get(scope) {
};
}
+macro_rules! map_from_iter_rand_bench {
+ ($name: ident, $n: expr, $map: ident) => {
+ #[bench]
+ pub fn $name(b: &mut Bencher) {
+ let n: usize = $n;
+ // setup
+ let mut rng = thread_rng();
+ let mut vec = Vec::with_capacity(n);
+
+ for _ in 0..n {
+ let i = rng.gen::<usize>() % n;
+ vec.push((i, i));
+ }
+
+ // measure
+ b.iter(|| {
+ let map: $map<_, _> = vec.iter().copied().collect();
+ black_box(map);
+ });
+ }
+ };
+}
+
+macro_rules! map_from_iter_seq_bench {
+ ($name: ident, $n: expr, $map: ident) => {
+ #[bench]
+ pub fn $name(b: &mut Bencher) {
+ let n: usize = $n;
+ // setup
+ let mut vec = Vec::with_capacity(n);
+
+ for i in 0..n {
+ vec.push((i, i));
+ }
+
+ // measure
+ b.iter(|| {
+ let map: $map<_, _> = vec.iter().copied().collect();
+ black_box(map);
+ });
+ }
+ };
+}
+
macro_rules! map_find_rand_bench {
($name: ident, $n: expr, $map: ident) => {
#[bench]
map_insert_seq_bench! {insert_seq_100, 100, BTreeMap}
map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap}
+map_from_iter_rand_bench! {from_iter_rand_100, 100, BTreeMap}
+map_from_iter_rand_bench! {from_iter_rand_10_000, 10_000, BTreeMap}
+
+map_from_iter_seq_bench! {from_iter_seq_100, 100, BTreeMap}
+map_from_iter_seq_bench! {from_iter_seq_10_000, 10_000, BTreeMap}
+
map_find_rand_bench! {find_rand_100, 100, BTreeMap}
map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap}
--- /dev/null
+use core::iter::Peekable;
+
+/// A iterator for deduping the key of a sorted iterator.
+/// When encountering the duplicated key, only the last key-value pair is yielded.
+///
+/// Used by [`BTreeMap::bulk_build_from_sorted_iter`].
+pub struct DedupSortedIter<K, V, I>
+where
+ I: Iterator<Item = (K, V)>,
+{
+ iter: Peekable<I>,
+}
+
+impl<K, V, I> DedupSortedIter<K, V, I>
+where
+ I: Iterator<Item = (K, V)>,
+{
+ pub fn new(iter: I) -> Self {
+ Self { iter: iter.peekable() }
+ }
+}
+
+impl<K, V, I> Iterator for DedupSortedIter<K, V, I>
+where
+ K: Eq,
+ I: Iterator<Item = (K, V)>,
+{
+ type Item = (K, V);
+
+ fn next(&mut self) -> Option<(K, V)> {
+ loop {
+ let next = match self.iter.next() {
+ Some(next) => next,
+ None => return None,
+ };
+
+ let peeked = match self.iter.peek() {
+ Some(peeked) => peeked,
+ None => return Some(next),
+ };
+
+ if next.0 != peeked.0 {
+ return Some(next);
+ }
+ }
+ }
+}
+use crate::vec::Vec;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::ptr;
use super::borrow::DormantMutRef;
+use super::dedup_sorted_iter::DedupSortedIter;
use super::navigate::{LazyLeafRange, LeafRange};
use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root};
use super::search::SearchResult::*;
pub fn into_values(self) -> IntoValues<K, V> {
IntoValues { inner: self.into_iter() }
}
+
+ /// Makes a `BTreeMap` from a sorted iterator.
+ pub(crate) fn bulk_build_from_sorted_iter<I>(iter: I) -> Self
+ where
+ K: Ord,
+ I: Iterator<Item = (K, V)>,
+ {
+ let mut root = Root::new();
+ let mut length = 0;
+ root.bulk_push(DedupSortedIter::new(iter), &mut length);
+ BTreeMap { root: Some(root), length }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
- let mut map = BTreeMap::new();
- map.extend(iter);
- map
+ let mut inputs: Vec<_> = iter.into_iter().collect();
+
+ if inputs.is_empty() {
+ return BTreeMap::new();
+ }
+
+ // use stable sort to preserve the insertion order.
+ inputs.sort_by(|a, b| a.0.cmp(&b.0));
+ BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter())
}
}
/// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into();
/// assert_eq!(map1, map2);
/// ```
- fn from(arr: [(K, V); N]) -> Self {
- core::array::IntoIter::new(arr).collect()
+ fn from(mut arr: [(K, V); N]) -> Self {
+ if N == 0 {
+ return BTreeMap::new();
+ }
+
+ // use stable sort to preserve the insertion order.
+ arr.sort_by(|a, b| a.0.cmp(&b.0));
+ BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr))
}
}
mod append;
mod borrow;
+mod dedup_sorted_iter;
mod fix;
pub mod map;
mod mem;
const PERMITS_TRAVERSAL: bool = true;
}
impl BorrowType for Owned {
- // Traversal isn't needede, it happens using the result of `borrow_mut`.
+ // Traversal isn't needed, it happens using the result of `borrow_mut`.
// By disabling traversal, and only creating new references to roots,
// we know that every reference of the `Owned` type is to a root node.
const PERMITS_TRAVERSAL: bool = false;
// This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface
// to TreeMap
+use crate::vec::Vec;
use core::borrow::Borrow;
use core::cmp::Ordering::{Equal, Greater, Less};
use core::cmp::{max, min};
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
- let mut set = BTreeSet::new();
- set.extend(iter);
- set
+ let mut inputs: Vec<_> = iter.into_iter().collect();
+
+ if inputs.is_empty() {
+ return BTreeSet::new();
+ }
+
+ // use stable sort to preserve the insertion order.
+ inputs.sort();
+ let iter = inputs.into_iter().map(|k| (k, ()));
+ let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+ BTreeSet { map }
}
}
/// let set2: BTreeSet<_> = [1, 2, 3, 4].into();
/// assert_eq!(set1, set2);
/// ```
- fn from(arr: [T; N]) -> Self {
- core::array::IntoIter::new(arr).collect()
+ fn from(mut arr: [T; N]) -> Self {
+ if N == 0 {
+ return BTreeSet::new();
+ }
+
+ // use stable sort to preserve the insertion order.
+ arr.sort();
+ let iter = core::array::IntoIter::new(arr).map(|k| (k, ()));
+ let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+ BTreeSet { map }
}
}
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} == {Rhs}`"
)]
+#[rustc_diagnostic_item = "PartialEq"]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// by `==`.
#[doc(alias = "==")]
#[doc(alias = "!=")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Eq"]
pub trait Eq: PartialEq<Self> {
// this method is used solely by #[deriving] to assert
// that every component of a type implements #[deriving]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Ord"]
pub trait Ord: Eq + PartialOrd<Self> {
/// This method returns an [`Ordering`] between `self` and `other`.
///
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
)]
+#[rustc_diagnostic_item = "PartialOrd"]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values if one exists.
///
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`hash`]: Hash::hash
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Hash"]
pub trait Hash {
/// Feeds this value into the given [`Hasher`].
///
// existing specializations on `Copy` that already exist in the standard
// library, and there's no way to safely have this behavior right now.
#[rustc_unsafe_specialization_marker]
+#[rustc_diagnostic_item = "Copy"]
pub trait Copy: Clone {
// Empty.
}
macro_rules! impl_checked {
($T:ident) => {
- pub const fn $T(val: $T) -> Option<$T> {
- if val > 0 { Some(unchecked::$T(val) as $T) } else { None }
+ pub const fn $T(val: $T) -> Option<u32> {
+ if val > 0 { Some(unchecked::$T(val)) } else { None }
}
};
}
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log(self, base: Self) -> Self {
+ pub const fn log(self, base: Self) -> u32 {
match self.checked_log(base) {
Some(n) => n,
None => {
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log2(self) -> Self {
+ pub const fn log2(self) -> u32 {
match self.checked_log2() {
Some(n) => n,
None => {
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log10(self) -> Self {
+ pub const fn log10(self) -> u32 {
match self.checked_log10() {
Some(n) => n,
None => {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log(self, base: Self) -> Option<Self> {
+ pub const fn checked_log(self, base: Self) -> Option<u32> {
if self <= 0 || base <= 1 {
None
} else {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log2(self) -> Option<Self> {
+ pub const fn checked_log2(self) -> Option<u32> {
if self <= 0 {
None
} else {
// SAFETY: We just checked that this number is positive
- let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+ let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
Some(log)
}
}
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log10(self) -> Option<Self> {
- match int_log10::$ActualT(self as $ActualT) {
- Some(s) => Some(s as Self),
- None => None,
- }
+ pub const fn checked_log10(self) -> Option<u32> {
+ int_log10::$ActualT(self as $ActualT)
}
/// Computes the absolute value of `self`.
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log(self, base: Self) -> Self {
+ pub const fn log(self, base: Self) -> u32 {
match self.checked_log(base) {
Some(n) => n,
None => {
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log2(self) -> Self {
+ pub const fn log2(self) -> u32 {
match self.checked_log2() {
Some(n) => n,
None => {
#[track_caller]
#[rustc_inherit_overflow_checks]
#[allow(arithmetic_overflow)]
- pub const fn log10(self) -> Self {
+ pub const fn log10(self) -> u32 {
match self.checked_log10() {
Some(n) => n,
None => {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log(self, base: Self) -> Option<Self> {
+ pub const fn checked_log(self, base: Self) -> Option<u32> {
if self <= 0 || base <= 1 {
None
} else {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log2(self) -> Option<Self> {
+ pub const fn checked_log2(self) -> Option<u32> {
if self <= 0 {
None
} else {
// SAFETY: We just checked that this number is positive
- let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+ let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
Some(log)
}
}
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- pub const fn checked_log10(self) -> Option<Self> {
- match int_log10::$ActualT(self as $ActualT) {
- Some(s) => Some(s as Self),
- None => None,
- }
+ pub const fn checked_log10(self) -> Option<u32> {
+ int_log10::$ActualT(self as $ActualT)
}
/// Checked negation. Computes `-self`, returning `None` unless `self ==
assert_eq!(i.checked_log(4), None);
}
for i in 1..=i16::MAX {
- assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+ assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
}
for i in 1..=u16::MAX {
- assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+ assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
}
}
assert_eq!(0i16.checked_log2(), None);
for i in 1..=u8::MAX {
- assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
}
for i in 1..=u16::MAX {
// Guard against Android's imprecise f32::log2 implementation.
if i != 8192 && i != 32768 {
- assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
}
}
for i in i8::MIN..=0 {
assert_eq!(i.checked_log2(), None);
}
for i in 1..=i8::MAX {
- assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
}
for i in i16::MIN..=0 {
assert_eq!(i.checked_log2(), None);
for i in 1..=i16::MAX {
// Guard against Android's imprecise f32::log2 implementation.
if i != 8192 {
- assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
}
}
}
#[test]
#[cfg(not(target_os = "android"))]
fn checked_log2_not_android() {
- assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
- assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
- assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+ assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u32));
+ assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u32));
+ assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as u32));
}
#[test]
assert_eq!(i.checked_log10(), None);
}
for i in 1..=i16::MAX {
- assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+ assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
}
for i in 1..=u16::MAX {
- assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+ assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
}
}
}
}
-/// Creates a new file symbolic link on the filesystem.
+/// Creates a new symlink to a non-directory file on the filesystem.
///
/// The `link` path will be a file symbolic link pointing to the `original`
/// path.
///
+/// The `original` path should not be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
/// # Examples
///
/// ```no_run
sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
}
-/// Creates a new directory symlink on the filesystem.
+/// Creates a new symlink to a directory on the filesystem.
///
/// The `link` path will be a directory symbolic link pointing to the `original`
/// path.
///
+/// The `original` path must be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_file`] for other files.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
/// # Examples
///
/// ```no_run
import datetime
import distutils.version
import hashlib
+import json
import os
import re
import shutil
except tarfile.CompressionError:
return False
-def get(url, path, verbose=False, do_verify=True):
- suffix = '.sha256'
- sha_url = url + suffix
+def get(base, url, path, checksums, verbose=False, do_verify=True):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
temp_path = temp_file.name
- with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file:
- sha_path = sha_file.name
try:
if do_verify:
- download(sha_path, sha_url, False, verbose)
+ if url not in checksums:
+ raise RuntimeError("src/stage0.json doesn't contain a checksum for {}".format(url))
+ sha256 = checksums[url]
if os.path.exists(path):
- if verify(path, sha_path, False):
+ if verify(path, sha256, False):
if verbose:
print("using already-download file", path)
return
print("ignoring already-download file",
path, "due to failed verification")
os.unlink(path)
- download(temp_path, url, True, verbose)
- if do_verify and not verify(temp_path, sha_path, verbose):
+ download(temp_path, "{}/{}".format(base, url), True, verbose)
+ if do_verify and not verify(temp_path, sha256, verbose):
raise RuntimeError("failed verification")
if verbose:
print("moving {} to {}".format(temp_path, path))
shutil.move(temp_path, path)
finally:
- delete_if_present(sha_path, verbose)
- delete_if_present(temp_path, verbose)
-
-
-def delete_if_present(path, verbose):
- """Remove the given file if present"""
- if os.path.isfile(path):
- if verbose:
- print("removing", path)
- os.unlink(path)
+ if os.path.isfile(temp_path):
+ if verbose:
+ print("removing", temp_path)
+ os.unlink(temp_path)
def download(path, url, probably_big, verbose):
exception=exception)
-def verify(path, sha_path, verbose):
+def verify(path, expected, verbose):
"""Check if the sha256 sum of the given path is valid"""
if verbose:
print("verifying", path)
with open(path, "rb") as source:
found = hashlib.sha256(source.read()).hexdigest()
- with open(sha_path, "r") as sha256sum:
- expected = sha256sum.readline().split()[0]
verified = found == expected
if not verified:
print("invalid checksum:\n"
sys.exit(1)
-def stage0_data(rust_root):
- """Build a dictionary from stage0.txt"""
- nightlies = os.path.join(rust_root, "src/stage0.txt")
- with open(nightlies, 'r') as nightlies:
- lines = [line.rstrip() for line in nightlies
- if not line.startswith("#")]
- return dict([line.split(": ", 1) for line in lines if line])
-
-
def format_build_time(duration):
"""Return a nicer format for build time
os.rename(tmp, filepath)
+class Stage0Toolchain:
+ def __init__(self, stage0_payload):
+ self.date = stage0_payload["date"]
+ self.version = stage0_payload["version"]
+
+ def channel(self):
+ return self.version + "-" + self.date
+
+
class RustBuild(object):
"""Provide all the methods required to build Rust"""
def __init__(self):
- self.date = ''
+ self.checksums_sha256 = {}
+ self.stage0_compiler = None
+ self.stage0_rustfmt = None
self._download_url = ''
- self.rustc_channel = ''
- self.rustfmt_channel = ''
self.build = ''
self.build_dir = ''
self.clean = False
will move all the content to the right place.
"""
if rustc_channel is None:
- rustc_channel = self.rustc_channel
- rustfmt_channel = self.rustfmt_channel
+ rustc_channel = self.stage0_compiler.version
bin_root = self.bin_root(stage0)
- key = self.date
+ key = self.stage0_compiler.date
if not stage0:
key += str(self.rustc_commit)
if self.rustc(stage0).startswith(bin_root) and \
if self.rustfmt() and self.rustfmt().startswith(bin_root) and (
not os.path.exists(self.rustfmt())
- or self.program_out_of_date(self.rustfmt_stamp(), self.rustfmt_channel)
+ or self.program_out_of_date(
+ self.rustfmt_stamp(),
+ "" if self.stage0_rustfmt is None else self.stage0_rustfmt.channel()
+ )
):
- if rustfmt_channel:
+ if self.stage0_rustfmt is not None:
tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
- [channel, date] = rustfmt_channel.split('-', 1)
- filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix)
+ filename = "rustfmt-{}-{}{}".format(
+ self.stage0_rustfmt.version, self.build, tarball_suffix,
+ )
self._download_component_helper(
- filename, "rustfmt-preview", tarball_suffix, key=date
+ filename, "rustfmt-preview", tarball_suffix, key=self.stage0_rustfmt.date
)
self.fix_bin_or_dylib("{}/bin/rustfmt".format(bin_root))
self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(bin_root))
with output(self.rustfmt_stamp()) as rustfmt_stamp:
- rustfmt_stamp.write(self.rustfmt_channel)
+ rustfmt_stamp.write(self.stage0_rustfmt.channel())
# Avoid downloading LLVM twice (once for stage0 and once for the master rustc)
if self.downloading_llvm() and stage0:
):
if key is None:
if stage0:
- key = self.date
+ key = self.stage0_compiler.date
else:
key = self.rustc_commit
cache_dst = os.path.join(self.build_dir, "cache")
os.makedirs(rustc_cache)
if stage0:
- url = "{}/dist/{}".format(self._download_url, key)
+ base = self._download_url
+ url = "dist/{}".format(key)
else:
- url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit)
+ base = "https://ci-artifacts.rust-lang.org"
+ url = "rustc-builds/{}".format(self.rustc_commit)
tarball = os.path.join(rustc_cache, filename)
if not os.path.exists(tarball):
- get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=stage0)
+ get(
+ base,
+ "{}/{}".format(url, filename),
+ tarball,
+ self.checksums_sha256,
+ verbose=self.verbose,
+ do_verify=stage0,
+ )
unpack(tarball, tarball_suffix, self.bin_root(stage0), match=pattern, verbose=self.verbose)
def _download_ci_llvm(self, llvm_sha, llvm_assertions):
if not os.path.exists(rustc_cache):
os.makedirs(rustc_cache)
- url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
+ base = "https://ci-artifacts.rust-lang.org"
+ url = "rustc-builds/{}".format(llvm_sha)
if llvm_assertions:
url = url.replace('rustc-builds', 'rustc-builds-alt')
# ci-artifacts are only stored as .xz, not .gz
filename = "rust-dev-nightly-" + self.build + tarball_suffix
tarball = os.path.join(rustc_cache, filename)
if not os.path.exists(tarball):
- get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=False)
+ get(
+ base,
+ "{}/{}".format(url, filename),
+ tarball,
+ self.checksums_sha256,
+ verbose=self.verbose,
+ do_verify=False,
+ )
unpack(tarball, tarball_suffix, self.llvm_root(),
match="rust-dev",
verbose=self.verbose)
def rustfmt(self):
"""Return config path for rustfmt"""
- if not self.rustfmt_channel:
+ if self.stage0_rustfmt is None:
return None
return self.program_config('rustfmt')
self.update_submodule(module[0], module[1], recorded_submodules)
print("Submodules updated in %.2f seconds" % (time() - start_time))
- def set_normal_environment(self):
+ def set_dist_environment(self, url):
"""Set download URL for normal environment"""
if 'RUSTUP_DIST_SERVER' in os.environ:
self._download_url = os.environ['RUSTUP_DIST_SERVER']
else:
- self._download_url = 'https://static.rust-lang.org'
-
- def set_dev_environment(self):
- """Set download URL for development environment"""
- if 'RUSTUP_DEV_DIST_SERVER' in os.environ:
- self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER']
- else:
- self._download_url = 'https://dev-static.rust-lang.org'
+ self._download_url = url
def check_vendored_status(self):
"""Check that vendoring is configured properly"""
build_dir = build.get_toml('build-dir', 'build') or 'build'
build.build_dir = os.path.abspath(build_dir.replace("$ROOT", build.rust_root))
- data = stage0_data(build.rust_root)
- build.date = data['date']
- build.rustc_channel = data['rustc']
-
- if "rustfmt" in data:
- build.rustfmt_channel = data['rustfmt']
+ with open(os.path.join(build.rust_root, "src", "stage0.json")) as f:
+ data = json.load(f)
+ build.checksums_sha256 = data["checksums_sha256"]
+ build.stage0_compiler = Stage0Toolchain(data["compiler"])
+ if data.get("rustfmt") is not None:
+ build.stage0_rustfmt = Stage0Toolchain(data["rustfmt"])
- if 'dev' in data:
- build.set_dev_environment()
- else:
- build.set_normal_environment()
+ build.set_dist_environment(data["dist_server"])
build.build = args.build or build.build_triple()
build.update_submodules()
import bootstrap
-class Stage0DataTestCase(unittest.TestCase):
- """Test Case for stage0_data"""
- def setUp(self):
- self.rust_root = tempfile.mkdtemp()
- os.mkdir(os.path.join(self.rust_root, "src"))
- with open(os.path.join(self.rust_root, "src",
- "stage0.txt"), "w") as stage0:
- stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta\nrustfmt: beta")
-
- def tearDown(self):
- rmtree(self.rust_root)
-
- def test_stage0_data(self):
- """Extract data from stage0.txt"""
- expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta", "rustfmt": "beta"}
- data = bootstrap.stage0_data(self.rust_root)
- self.assertDictEqual(data, expected)
-
-
class VerifyTestCase(unittest.TestCase):
"""Test Case for verify"""
def setUp(self):
self.container = tempfile.mkdtemp()
self.src = os.path.join(self.container, "src.txt")
- self.sums = os.path.join(self.container, "sums")
self.bad_src = os.path.join(self.container, "bad.txt")
content = "Hello world"
+ self.expected = hashlib.sha256(content.encode("utf-8")).hexdigest()
+
with open(self.src, "w") as src:
src.write(content)
- with open(self.sums, "w") as sums:
- sums.write(hashlib.sha256(content.encode("utf-8")).hexdigest())
with open(self.bad_src, "w") as bad:
bad.write("Hello!")
def test_valid_file(self):
"""Check if the sha256 sum of the given file is valid"""
- self.assertTrue(bootstrap.verify(self.src, self.sums, False))
+ self.assertTrue(bootstrap.verify(self.src, self.expected, False))
def test_invalid_file(self):
"""Should verify that the file is invalid"""
- self.assertFalse(bootstrap.verify(self.bad_src, self.sums, False))
+ self.assertFalse(bootstrap.verify(self.bad_src, self.expected, False))
class ProgramOutOfDate(unittest.TestCase):
TEST_LOADER = unittest.TestLoader()
SUITE.addTest(doctest.DocTestSuite(bootstrap))
SUITE.addTests([
- TEST_LOADER.loadTestsFromTestCase(Stage0DataTestCase),
TEST_LOADER.loadTestsFromTestCase(VerifyTestCase),
TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)])
install::Src,
install::Rustc
),
- Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest),
+ Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0),
}
}
//! When you execute `x.py build`, the steps executed are:
//!
//! * First, the python script is run. This will automatically download the
-//! stage0 rustc and cargo according to `src/stage0.txt`, or use the cached
+//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached
//! versions if they're available. These are then used to compile rustbuild
//! itself (using Cargo). Finally, control is then transferred to rustbuild.
//!
builder.run(&mut cmd);
}
}
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct BumpStage0;
+
+impl Step for BumpStage0 {
+ type Output = ();
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/bump-stage0")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(BumpStage0);
+ }
+
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let mut cmd = builder.tool_cmd(Tool::BumpStage0);
+ builder.run(&mut cmd);
+ }
+}
use std::path::PathBuf;
use std::process::Command;
-use build_helper::{output, t};
+use build_helper::output;
use crate::cache::INTERNER;
use crate::config::Target;
if let Some(ref s) = build.config.ccache {
cmd_finder.must_have(s);
}
-
- if build.config.channel == "stable" {
- let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
- if stage0.contains("\ndev:") {
- panic!(
- "bootstrapping from a dev compiler in a stable release, but \
- should only be bootstrapping from a released compiler!"
- );
- }
- }
}
LintDocs, "src/tools/lint-docs", "lint-docs";
JsonDocCk, "src/tools/jsondocck", "jsondocck";
HtmlChecker, "src/tools/html-checker", "html-checker";
+ BumpStage0, "src/tools/bump-stage0", "bump-stage0";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
match *self {
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
- hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx),
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
WherePredicate::BoundPredicate {
ty: Generic(ref name), ref mut bounds, ..
} => {
- if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] =
- &bounds[..]
- {
+ if bounds.is_empty() {
for param in &mut generics.params {
match param.kind {
GenericParamDefKind::Lifetime { .. } => {}
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
if ¶m.name == name {
mem::swap(bounds, ty_bounds);
- // We now keep track of `?Sized` obligations in the HIR.
- // If we don't clear `ty_bounds` we end up with
- // `fn foo<X: ?Sized>(_: X) where X: ?Sized`.
- ty_bounds.clear();
break;
}
}
let mut global_ctxt = queries.global_ctxt()?.take();
let collector = global_ctxt.enter(|tcx| {
- let krate = tcx.hir().krate();
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let mut opts = scrape_test_config(crate_attrs);
hir_collector.visit_testable(
"".to_string(),
CRATE_HIR_ID,
- krate.module().inner,
- |this| {
- intravisit::walk_crate(this, krate);
- },
+ tcx.hir().span(CRATE_HIR_ID),
+ |this| tcx.hir().walk_toplevel_module(this),
);
collector
.join("\n");
nb_lines += doc[prev_offset..offset.start].lines().count();
+ // If there are characters between the preceding line ending and
+ // this code block, `str::lines` will return an additional line,
+ // which we subtract here.
+ if nb_lines != 0 && !&doc[prev_offset..offset.start].ends_with("\n") {
+ nb_lines -= 1;
+ }
let line = tests.get_line() + nb_lines + 1;
tests.add_test(text, block_info, line);
prev_offset = offset.start;
-use super::{plain_text_summary, short_markdown_summary};
+use super::{find_testable_code, plain_text_summary, short_markdown_summary};
use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
t("Struct<'a, T>", "<p>Struct<’a, T></p>\n");
t("Struct<br>", "<p>Struct<br></p>\n");
}
+
+#[test]
+fn test_find_testable_code_line() {
+ fn t(input: &str, expect: &[usize]) {
+ impl crate::doctest::Tester for Vec<usize> {
+ fn add_test(&mut self, _test: String, _config: LangString, line: usize) {
+ self.push(line);
+ }
+ }
+ let mut lines = Vec::<usize>::new();
+ find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
+ assert_eq!(lines, expect);
+ }
+
+ t("", &[]);
+ t("```rust\n```", &[1]);
+ t(" ```rust\n```", &[1]);
+ t("\n```rust\n```", &[2]);
+ t("\n ```rust\n```", &[2]);
+ t("```rust\n```\n```rust\n```", &[1, 3]);
+ t("```rust\n```\n ```rust\n```", &[1, 3]);
+}
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::stability;
+use rustc_middle::span_bug;
use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Adt, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants};
use super::{
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
}
fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
+ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
+ if layout.abi.is_unsized() {
+ write!(w, "(unsized)");
+ } else {
+ let bytes = layout.size.bytes() - tag_size;
+ write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
+ }
+ }
+
if !cx.shared.show_type_layout {
return;
}
<a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
chapter for details on type layout guarantees.</p></div>"
);
- if ty_layout.layout.abi.is_unsized() {
- writeln!(w, "<p><strong>Size:</strong> (unsized)</p>");
- } else {
- let bytes = ty_layout.layout.size.bytes();
- writeln!(
- w,
- "<p><strong>Size:</strong> {size} byte{pl}</p>",
- size = bytes,
- pl = if bytes == 1 { "" } else { "s" },
- );
+ w.write_str("<p><strong>Size:</strong> ");
+ write_size_of_layout(w, ty_layout.layout, 0);
+ writeln!(w, "</p>");
+ if let Variants::Multiple { variants, tag, tag_encoding, .. } =
+ &ty_layout.layout.variants
+ {
+ if !variants.is_empty() {
+ w.write_str(
+ "<p><strong>Size for each variant:</strong></p>\
+ <ul>",
+ );
+
+ let adt = if let Adt(adt, _) = ty_layout.ty.kind() {
+ adt
+ } else {
+ span_bug!(tcx.def_span(ty_def_id), "not an adt")
+ };
+
+ let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
+ 0
+ } else if let Primitive::Int(i, _) = tag.value {
+ i.size().bytes()
+ } else {
+ span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
+ };
+
+ for (index, layout) in variants.iter_enumerated() {
+ let ident = adt.variants[index].ident;
+ write!(w, "<li><code>{name}</code>: ", name = ident);
+ write_size_of_layout(w, layout, tag_size);
+ writeln!(w, "</li>");
+ }
+ w.write_str("</ul>");
+ }
}
}
// This kind of layout error can occur with valid code, e.g. if you try to
if include_sources {
if generate_link_to_definition {
- intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+ tcx.hir().walk_toplevel_module(&mut visitor);
}
let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
(krate, sources, visitor.matches)
--- /dev/null
+{
+ "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.",
+ "dist_server": "https://static.rust-lang.org",
+ "compiler": {
+ "date": "2021-08-22",
+ "version": "beta"
+ },
+ "rustfmt": {
+ "date": "2021-08-26",
+ "version": "nightly"
+ },
+ "checksums_sha256": {
+ "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.gz": "1aae6206b6ee057a53c6863d1aa9246a913bd8cc87945221ffe25a0763198ec9",
+ "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.xz": "9bb4026714d46f99077c4ec2ac1f818a059252996077569339a72704a1044cc5",
+ "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "127a066958fe2f67154ae5e5ffdf67e216cd9da5c8ca7f6f5818017ef647eb57",
+ "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f62459d78c012d129a38f9f05975f784ca59f613cb77f273ac1be992320968ca",
+ "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "eb0e5765d0d37129a1e70680cb701fc7968baf98a183a25fbe495d5e1818a67c",
+ "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "8168902da36e32c2b2946ec18d41c4877191e3b5ec95276d85a1453541be8adf",
+ "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "e8a774fd383d0a7a3a1216ebd3a005fe01560002c8a28b89ce7f9a0ac522a07f",
+ "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "da7e246ca883ace9f9006257dd52756395307613f2bc10d86bacfe9b24f861c8",
+ "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "bc20e1ffe92aeca2a01bab6b1e383dfd7cecde01780bb2369ef5e10ef6e88bc7",
+ "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5020ad70b694f18fa19be09d86983a7f396b38d71a65cf061438870d9264de45",
+ "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "53792dbfd932874bc7be8cf6683e5fa318afe9e59a3069f1c82279d9b66edcfd",
+ "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "cb393c4f0c0b6ef9c921733267192c01935fec55944c770765e3dcc37d9c20a8",
+ "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "96f017458f94370758b2cfa30f787707f548aeb9ca2dd9a52a43b27c73040b82",
+ "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "aa0b966b0ae33dc01714f16b3e511ae1f60da0a1a0e4de32e09cbe7a5e6a67b3",
+ "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "38f9b818c71bbf607cd0db8e73b539506f42c529fb8a5053860e844914e0ade3",
+ "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "ddfe1cee4f7d8a451ff5d1eb880c3e9ffa3fa1e59a8c12322e46562e379101de",
+ "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "33d5d918ae8d35ecc760bf876573a51d62c98a46eb6c60c2e3ba8acba4ce6488",
+ "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "0424f863ecf6e6d870325539637899720806a4130ffe815c724cdc34d8eb444f",
+ "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "d5e71781a82b424b28b90fe08d2ac4d86b37acd476bc36c106222128202a9476",
+ "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "65f860c74140318eb5c034a04c85e3eabfb31dfa8d70791d701f15d979d50361",
+ "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "034e491668d0f55b1fba9d606c2acb2d7d1d00db528f141207202ec6e5ca4410",
+ "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "f320d08c2116bcf1646f141426785e2b27488e48cf7e0ab97dab39efa4668efd",
+ "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "8bcb363d7dd7656bdeb5525df048dea384b34d564c98e3374c8c82f037e5074d",
+ "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "bbb924b505c82fef0d8912deb95b312d6547f96d15ff7cb06c5d77ee56c6fbbb",
+ "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "056e1662756321e884b84e662b9e465d58187f1fd9227ae4d7a9fce0110ddfb8",
+ "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c01a661eee4e2ab0c93cc6575f8ae56c16b79bd0d5479d9f918004cf8a8abc2b",
+ "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "b74739855529627407a72244de3efd706ed99c347061513a677ebc7fd3b4e7c1",
+ "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "a275d7e95312e868636aa1539de0b2f490973119ffb4863f5534eed395c4113e",
+ "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "4f6326173b50952d933b02cc477156d5aad067798b347ce502889e607e98c84c",
+ "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "86ffca7848946079b62f083a92e47440a431b5c451aca3600efc0a5f3939ba2f",
+ "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "9c9406fcb15e88f93a23d0a275e44559e33b4a2eeab4403cbb2184bdca36318e",
+ "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "99ca6df78a1dfcb0c9a919f0eec47783f95399bae39271a6367c07b8ef346a5a",
+ "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c24493b3e919ec268aa4b98da0a66332fa4e104210ed15b8f6c3b8c240ebeffe",
+ "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "7cfec0a0bae8471a32385a7c19d1ec17dba25ab1d6211cd062df73a9a1c030a2",
+ "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8a8d81661cc1789185be6d4c13ac2ee602194a5526467ab34e4f23243cb9f474",
+ "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b8ada6046b5351a627ae1fb4ee8ba059fa551f1de4444aba1d1915a27371d339",
+ "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "946d2d77ec784019f18372610ff438321e22f7e0d2e0045cc71180f3b2f6d376",
+ "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "2f3756d68b354341f98a3cfa4c89d78bf6e8c631dfb6477fceec5e6b00833d30",
+ "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.gz": "bccb3002b5cc3556555bb05208b7d64b9aee3a7dc3b482c03090ad0102c22570",
+ "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.xz": "a0f7dbfb008cb12bc7a8c9f464715e5aedfae175fdf5bb7bdf3d971072cd9b54",
+ "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "26fcc16d533e427eeded47f8c088aaa180602f68043f5dcd84755ac2166f16af",
+ "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "d5bc7bc9f2d5d2bbe7167f810b1334a86ddd694d111e145223474f8d6dee00af",
+ "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "6f3fe7f685324ff07995e5fb453462a1c4b5dac9208cd23935f6435af9146692",
+ "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "86e37578645f4436b7889c3b9c110888a2aff7af2833a7f5f38fa345a6f36e76",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "f0964def1f80732c1a67f0e4258a301ae2ee27d7ea474f70ab44816907a95ec3",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "6a4655c9b902b904b3dd2ca00dd656d0ef99c77e632f6d6ffc615486b4bfa543",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "5aeb8db8c2e5afd80378a0aa1572c57ff021fb5dccb1bd914b994f0ca8764667",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "0892a93f462e70aee33117de90caaa7b7ef363a27e573602c1d606c0309ae2d9",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "e4be5cd72bb220514c73d7da14ff2962dcd74b8602c1724d71538ab11da94132",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "0b643ba40ce6dbb270f85f45b2dd4d727051a896099493166cfad05c9be96b1f",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "998df5339f738815ab7c38b32df00eef09ff0e415a85d2ae2ab1c0836a380906",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "4ca058f973e2d439e812f839e57920dd9e73a0da9f9bf37889c06f3b1755b07e",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "6511df143067a3c3f6f741540f890f3bca46b11c01cda1c92e1708d0be30ebeb",
+ "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "4ebef9830e25fb28e12ea538e17a46cfe0748e6a14cf976048df056ae708b1ea",
+ "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "6af3a7f720d5a7100683636c387865b3d4e9b5148ca04c1238662b81c8bbde9c",
+ "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "459e63b66eb8e53e106896c3003183c5ef3803a8dd3d501d50e6d4e03343ad66",
+ "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.gz": "95c816378d57b5d7336373f7f53b603dd8a4efcf17634d4e008b6bd896947cac",
+ "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.xz": "209caeea6df90996d5239d0900767135bde716387317a10dc348b96aa818a93a",
+ "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.gz": "54ec6a313cc523fc568c4879cf36ab90bade8a1ae9c2ee89bafd57c2c9f3f754",
+ "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.xz": "82de1d66bf9cf226b80fea722d2828f368cbe75bc5d99a524193b50db6003636",
+ "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.gz": "1a08cd54ff716d6ef3e53177e31787e8aa00f948054b42f94d791d3d59aa3169",
+ "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.xz": "32c1b56cc223bab3e7f15de719488c874011dd6be622038ce5b1f7ff03b05c59",
+ "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "62a85f52db02e9afc659e84ea8bc3c8828f6a9fe4c1b58eecc3cefeb99e2d8ac",
+ "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "1e6126312252956f5ad887ca5e8271be3cf31ac8d793071f6af8c2adcdd57f00",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "5542b7e2ee1611f0410e2e962796cd7067e483b37730061a4f788f853f31c7c1",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "97f149839149fcff4004260eb119c1213f10a455b37a8256aec977bc04c9e2c0",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "48dada900d144fc9a17ff273ab44d9c4c5fb0cfbaae986d6396aaa6c9c5c22d5",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "c93b5da1e22138da0a97be32b9498a3ede270253a22a9d9275f610e349438bfb",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "904b39e24f5fe72393f943a5ecb3bfa6e07f3623a0cde911b161558660ee27d9",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "013646fe9e3f640ae820bfccce656c1bc94d0c3856613dbdea8b06574e072ad4",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.gz": "59de57b6902c755a2d92d5aa154452e84c747bc414605cebb367a4a17cf16ae7",
+ "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.xz": "9822fd8d21f863018ead909155ed7d931c5a9bb9ac6461c1f19609ad1a206a48",
+ "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.gz": "235bc683a244a69b1f36a875a418efb56af6e1f8411dbace6f9cef3ce1191f7d",
+ "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.xz": "a2d267e75d64e0bb96c9a8b78bb67db4ba46576edc51955108595c17ff285083",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "cc5d42c65ebc2733017a463c5a4903c681fd923dfa820ed6e420950f6c599ba5",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1e9b3e5c0025c15f485eee6a39dc20ea62bfa777a820bd524817eeab07878e67",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5f298d431d03d56112d2527c889d94296c03fb4187bbe26bd0e2be50bc9207ed",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "8be37b928562c4f08342b0661077dca25484d9e12e1e48b375fef02f6699fe87",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "db7d25058f4f39007495e864a20a398d307f9505721c9f5991db6d7065db50ee",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "fc858a2f2b7fe83cd148ee133b952ef8d63a6f39600fb101c7b98d37734484df",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "bc1ab01b0d7783c8cde71c1d4507fbf68330933e86d5b0280426eb9e9103ba38",
+ "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "18a1ca7fb88d56832ee5a331c3f3fa38ff2c72ecded3e093f4d6aef5e67e886d",
+ "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "3eef0c676173ae40e3b1f900627c953955fdea5b3a24401bf69e9d433c9b0996",
+ "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "58cdd696c46434bc0aea39b562aab818da1644da08bb385047b7b83cfedf9334",
+ "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "0035c38e059eac51cf8786bfde6162bb27ee8c642260af40646665902f9e4cc8",
+ "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "893d2d56614198da58327881684b1edab0a7d849eb8e3d6ba1705c192c98718e",
+ "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "489d6080bf6ab3dddfd490cc2c6cd956473389678eafe4b85b88e0ba06dfd73a",
+ "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "10ed28b9ce5b2d94492034e707a78d18540b096d1439faf5c7370d29c50ea105",
+ "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "febbed115d82f51d8c19b49f89a6fb9f1062826d6283e5877b8327b4b0572671",
+ "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0f96c9b4bc3464cef4deeec087da38fc39d2cefb1cff7b413aedb8a79f412dc8",
+ "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "8d407d9ddbe27ac708efb40d12b2292857c49f306afa018fd7df44116ccade3c",
+ "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "253b5f4613369b4431296b1151b7c4228594889ac69674a0e3ef75438120868a",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "11e715bf0082733d94a796ed4e123f7ec77aa5fe0e8d037dd513dd69bc230a2e",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "a2d8a16c08721a406f8132f5deb960b65e38d3235a76b72d5f267b2bddb9ad91",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2351b24b205851ff51e79a228416bb6ea801551050cb791464a0364a56a0133b",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "12da6b0947eebc24ae2a279bad6f1a50d26d57c956cb66840b5db6ef266975e4",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "96d333f046236bbfe809a5526e798197e8416442ddaec5e692aa642dd58f3397",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "f2d5832790120cceda3c07cb2dadb4d4e8e30228ffedbf4988a52573382689c1",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "d71cf49d01b781c55a64b174d4b91906771aeb90e885310576b5d77a068a8961",
+ "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "3e9b5c730f855b690103d44929384738748bdbc312fe5f8bdb9cb3fe1d8dc701",
+ "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.gz": "b0464837c6303c85d67ebcf45752ad9c859ea4ff013310c4ae64a2ff318db56b",
+ "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.xz": "13aec30cbdfb84483669a5d5a5d2f465f60692e997a6073d5f749c2950fe6a45",
+ "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.gz": "4c54b72683f8800f77b60889a8e91fe293a21916f756ab6fbe5f1e39884a11b2",
+ "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.xz": "5b917d543bd41f47ac8983cc5f3dfb19515b940eff644c5421f23575d8958e35",
+ "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "305fce68a56206cffb34b4735fbff367b8d1f3131a043f5cf03de1ede9402323",
+ "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "511fe782be16d7402519546af50427fc953f599773466668c0133e3d252874ce",
+ "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "31223e26db1d00219cf78e70c096aaec45a5ba2f2835dcb55edcc1e2e83e28b8",
+ "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "2453e08515943e38def4d65c8278f2d25c5b7dfa7883040346c0824abaab9cb0",
+ "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "1f22b735b50f2ccbb3ba99a27e4901b2da9d408361ad8ce2710ab61dbb6a8c46",
+ "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "e2f31b9933df67a5fdae28f26b38f907fb2607ccfc2a1f2e6b6fd9853eb6eb6a",
+ "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "a3d2d4184376f6d398a3b1bfbab881659408340287d61d7f29d70bb167824427",
+ "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "3803e83360d67e1866d2dada4f62fbf2a04ac3cbc7c347ba4ce97b2e6adf9ced",
+ "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "c2890c8ae6c3bb71811867ab953e774161415d454009d9f36a116c86994a9056",
+ "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "671191cab9795d52a7ed9762951de46a89988bb22233b6a0b09e85bdc5e5d904",
+ "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.gz": "3e83c96f73f5b526e3f20939338e0b51a94898ffcfa3c7d08ef72966e9161f71",
+ "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.xz": "8c96f60b63bdcec60ea52cbb3880f2d684b2b96a37b37946a24d893eafb4dc77",
+ "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "760e6deb8aec1185b8127bc012794463eefa87dd48a1fb69e6f79ccad45422e5",
+ "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "82809e4bf5b89cfad4d8c8770deb5c2bab4ed1f17463a09c728c25684b7d2d72",
+ "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "288086c4caf64a38b441937f9d3335b0ef419bb6a2693216b48aefe31c34f7ea",
+ "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "06bb31b48abfbfdf4c627d87717987cb0e721100f952e77435c156bd45eb02a3",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "589d7aeabc268fb06f3fd7ff37dfff434924fe87fb778ffa366a27ebf815a26c",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "b5b7bf0752034c4e79827e2155afbc7b2fd59a5220e8acf9b244023a725f9483",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "94c9450ad3915dd6367833b59e07b66083d653eaa72b3b486676c3475fcca86e",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "014e3abef9cbea6008653ba3e85c7cf074add0bbfa71afa90a9f577f014de19c",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "9897bea4ada2d49e055210699a757f59620d8092e9b40c3eba2dd9fde0205309",
+ "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "7c53fbd4643e4f9f5e441a79bdbbf8044b3d35d113ca2ce670462433c9299ce4",
+ "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "2d4af2bd5c632de7de1abf556acda7c4897f5475221a7e72d36d70236c90a332",
+ "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "f388bb0bbfa4d505101b6f087205cef9593b29d55d04dc0f08629d23df6f4dd5",
+ "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "7a35ebffe2858e68c8585c54d980edfb7fd84b3a78856110871d062f58e4c4d9",
+ "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "40ca86dbff7248854b86ae2a4c05efa5e240ae40d88a887a2681aa0c4995fad3",
+ "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "3d380de1f425c4e022037805b4687567870d84bd06375c26528e5a9529b1f0df",
+ "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "15f951100779f6535a25f91b58630951376d9191dabb3405b34a78246bd07d6b",
+ "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "d1d2f014a7d0c5b6140d282bf38d5fc4c7a93df0e484d9f893fe3ed25c5cf384",
+ "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "7f96e0ebaa820cf927962b0c0c584b4b96d3fd34e90e281162138937f145fde5",
+ "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "e6d8a5e5de7328d045ccc4c6457e82282c7b0a23bc35443f402672d94df088ef",
+ "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "d015d566ae58d854de39337ddfc31f29cdbb4e87320e20b0fbcc83912415d11f",
+ "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "cbbcf7edb5f785d89bc20c287a6dcab69eabbdfff0ed8d9283ea0766d98ccfee",
+ "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "4b988afc44729564783300cfd47b1ace974bd8eacb52cc553365fdd07b8b38e7",
+ "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "674d244f0d536ff053be6384ee9ba9b80db2cc6d9bd840434d26fabdb259d7be",
+ "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "07aa043aac39364935f6758e1d2200d6334b719e4b13ad7bcc9e693cfef90e3c",
+ "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "19aa1bc698c24eb1136de2a8ace0b872a472e9fb5b1c1fbd48d03fa8e3dab00b",
+ "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "a9db5dfaca379bcb6a2c3bb5c6d6eafe4dace2e814c7edb5fdf6a26595be2538",
+ "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ebe482fecfce4ff0ee9dd514b984b9c04565470ecd7a24d94778d51e31107915",
+ "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "b663ce48f79cf4634d35e8c35f10c2c51d775c906b9c7a46ae6e67d7070e1b21",
+ "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "aeb314e2de96b9d7623a8b58d34fb1d290039b1ad63ad91da5052bbcb8569d66",
+ "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "87731e0ea78d1478f87c50d770618b7feb6d404ae257704a1a622bbfc4a079cc",
+ "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "5eeea41e13e8941e1a7e29dc649cc34fafad8ef01fdeffb133cf0dad6cc57997",
+ "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "3435ba7a88ad51266a32fdba648f1d4a60a918ad396261a03593a409db028f1b",
+ "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d453444ef726401c683042f2d33c70fc078ef79d95d4cbd0f007d41bb8894e2b",
+ "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "ab83c5f5477bb3a800e2054d345ed48bba162c871788f7b187f875652f9e8163",
+ "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "d007269d819f76c53e211c8a2871db177c6f910de463f87ae1cc3d3e3f0d42b8",
+ "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "3bc82447155b9a453abe1788705b61ea41f017048a017d973a41a587b81b4bab",
+ "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5c6b7fb54fa4effd3140848b9f7779b4139971f0666758bff43c8bc93877d962",
+ "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "4043a4dca70b44ff5471a3457fbc85218850ab0dd52bbeef87bc629170f07bc3",
+ "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "aaa6eee8c67c6c666cca044c75e0049fc982442647528263ac87bfd17bddd0e5",
+ "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "ce8633daef8fab199318c26cac981de0a7db1e93a066c05187f4f3165826da6a",
+ "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "d5323d5b0a8a9c4f7f688449ac4b39b1b0e30ae26fbdb355ab3477c033e86f74",
+ "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e4dd4e3b3fef2434ad5b96d7c966576f9d27cca146bb1df3ec0dea92e65d1234",
+ "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "ca1e486ed9b37d64c4c1ff4ade719bd4d75ea42d862a53e7ce5106045498618e",
+ "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "b07b65d1df2b7147cfcda1aa8c43b64cb0f29290fe9518569969550fd176399e",
+ "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "3225c1a028dbff77a73c8209417261689dcffff8c9019bfb81d7c2ddf440999d",
+ "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "d219a81bc543d000200f0a11de6db87f5f0b135122150f37782d0e1132669ffc",
+ "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "92a70667972c1fa0e5963ef189a450f65861d779f2251e10884bc9dac3751e2a",
+ "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "31405140b78366c182ebcb02632983017409c3c282a2eac6716d410fc2f6d1a4",
+ "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3f6dfab8290bdd2e12f7a4a8ba0e2b58006e0a0096357077cdd1392e94a81bd7",
+ "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "327a86e0e83ccaac9ebb5458e48906a5e83ec928fc01939758a50ce46c114334",
+ "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "c798402360747dac456746c4fb68de30e702ba6a3a1cea0bd5884546d1c2f714",
+ "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "63a9ebcbb4e97cd80c0c97ba6323614cc69a4ff15904e6120aae970a803b3402",
+ "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "bf1ae6e7ceeee0b9631d638aa33b29fc064699eebf1da192aed0b7c0a98f6866",
+ "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "da183dbff702ab18cf02d34c395c6dc70344b525c0d09bc26a8670b75e6e900a",
+ "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "f6c66612b1f500218927504a23eb3df1bd8ff5a6171d576ebb681bb0f426d5c6",
+ "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "8364308682a2c6e91b2c7bfacb09dd9a7487c106ae95c489286d13e641ecaaa0",
+ "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "711e05b89ab2cf2cc17aa7beeb5bc2aafcd851606a8dd535230e64bc5d232dea",
+ "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f444669bde93eae4599db7624f830b031f4d4d116d0344829be3177558a5dfd1",
+ "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "9b4699b67763b7c2691a95c69827f6c8ce8847c64e0806b0c3f36f48848a7e4e",
+ "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "2c038bc6607b115f817859aae07c495d6d2a1bd4cfe9007f36494b9229a68d86",
+ "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "7634d01dfdb18a43bc8a230df711e8254f3bbc214b89844475bfba9eb920a5cf",
+ "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "ba0815d8b0d5600cd09148343bcbfa25004b3092bee1ed0e0673fdf8937ebf62",
+ "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "823ee6535da426700b0aed6a33201873d8b6611248506e436cdddae92a074a06",
+ "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "c4b21b5300959794c811653aa907fd259970b08c41d4ce303384b34783b142cf",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "d71ce2ec3eb040244c017dc7bb40342da106d097a579ab69312f1879d5c446c7",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "05375174c0d6f9480c5b504ee16823a28d2994bea0eee52242cef25f9d7b766d",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "9e9efb15d1718421b5537aca94dbc078d8cf4f1651b0b2e790af5fb0d8592ea4",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "d7ffe70ed73bf689c3edcccc1bfc23ba75737f2d0841d471720d23a67b2cd63e",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "704a086e751b96f1249bd295a9dc45f9aeee0d93bf96d2d6fe00ffaf33af3062",
+ "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c7ea8e97a90c4e27f910f8ef1e64885540179dc55ef09e4f5a844bb7ab3d0c9b",
+ "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "2165a0868d21ce1cf10e6360f8384866a985358475cae1bfa74d33d3516db565",
+ "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "6909a1ace7b22fa66b175cbf3de0cc54708f0aa73baa3e2168f3e758698c26c8",
+ "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "dd2eb7f4fb9285c11cdbeddaee20a75179a1588486ccbcb7b6e32971790acaf6",
+ "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "9e51dc30f624af1410a77b4f77f01868ec141d6288b09827f7e3a313b276f78a",
+ "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.gz": "b29b2748928aaf72aa30117cfd8bd9c6c13a6c7255efe1bcbd6bf535aefb1294",
+ "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.xz": "90f58b108a9538e190fd3ecec97581b95c85ed27ebcbf1f4ef85b4e3248db0f5",
+ "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "b6549bfeb4ad3de444ff7afce6baaa34ee7468d41480a86072cd3a26e1191de0",
+ "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "44d77279c9997ebc5f4952fde208de6747f6b95e1887c1ac637f3f5170cda003",
+ "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.gz": "3a69d284711c0eab25a73b6d22a3fd92e6741e22a454d0210694c73c2775e6db",
+ "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.xz": "08b97affa6264d739eb31925f3d4a2fb0feb32e6b3eff770c580782bea216ca0",
+ "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "15334ea58e51d1d5f35f15c75a0f941b3648d9bc2acbb57a6c07b788c78aa6d2",
+ "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "7aad1c1dc41f5713fb9a3414b0cd64b78f3b8cd6bd12a9fe14318cbab5c804aa",
+ "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.gz": "48e706203750b335276140b8156c5c74ed48cd36aa7a6f732f7febe3d517da76",
+ "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.xz": "d0a14f312a2f91961f955352f6e508cdf5e5ac82be10837843ec7c87ed9d3ff9",
+ "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.gz": "12a29451878739ba28838a8bf0eda9ab4826457a6ef249644bbe11e3afbde650",
+ "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.xz": "f2fe871094a8dbd11bf15d9139ca0d630b9fc2c03d1bfed295d1ee01a8484910",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "42237c674c4c5f6181da0eaeffc755a08087b87350770fca6a3d707158cd66f4",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "167aa8827682e3a6c140a7607ede1c0ca90014634940c228dc538263b6e1ea8d",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "7517896917e38d12d3265b0202ea8bd839d8cfd08b9c6b2c6033b5f70d24f049",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "902b1a27c034206fd03457a52eb495c2bed5d3f4355e4d94d1dea05746e10df1",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "3b2143072753553cc05d40e0684fdbabe6eb8c436588ce2f29ca393f3c5a8609",
+ "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "47d03efe92f8fcfbdb192565dcf4db4e4c1c301ff4bd8cb15e0ae74c5ee00122",
+ "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "7394b58442de5d444c1fdaef7d91da57f6bd64a50ccd8be518e2e620e0829036",
+ "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "4839a52f87ec51bdf0438dfaeb57f3757b481ad47a7e86db9740d3e86e2c261f",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "a44012100040021f42335ba35be08570c86d72c371783e203fd1a6144d46a6fe",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "7279b03775bd896709700727d9db6030a05a4cad3842c1b225404bd1545a0ba9",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "ee719a8fc9a6a5ba1d47fc5d95ebdc8f692b473ed22202d3315de1aebcbae374",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "a85f334cf580035472b054383365c6da4509aa85a3901e6d30649c3e6f1af4f9",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "96884f6544e2d51034cac32618e4e35ee0c84467d8a80f635d8073980fed0ce6",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "98f745588c290a0319216d067a60ba3665506111bdcc4a773b5b850f9ac8107a",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "cb3249e99fd60a57cdab4a529c14eae3d76fc85768ec9cb9186eeafc32f45214",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "614acd645f9c79eda648236e6f3c028d9bb5482297059bfc93dab9f2e90d1478",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "c7988d678d330d31c3e88df27b9c2b482854d0b7f277f8126e2996a9f4180387",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "11d16c7f5b64e3d4bcfcad489c2710ca7e3cad12c82221848c51ed839688e02b",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "45f880920e746f53810fc70526e18ef807e6d4089ef147bed8c53c536624f646",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "0910b51938eed74ad4af9e07f74ea5648a143fbd142a9cb4fe1bc7f7b7bd6159",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "c14fd257005a11026cc3ebf23fb9f2d35a6d99f9136471574d8c0d18fc66e3b7",
+ "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "9c3438ecac2dfaf827039b506c114bdc06c05a69b81761abfb63f8a227950da7",
+ "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.gz": "357bb650d7377610e61a9ff2167a7fd480ca844322849e5dcc80a91edc5fffa5",
+ "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.xz": "3f0883cd2c1d1bc31dd89a72711ba6a22a1c455f28dc2d5644e70898614a637a",
+ "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "6366923332e491d21b5f448500fd56673fd21738e6edcbdb21c11fafb00723de",
+ "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "b0e7462540e6c96b373f6aebf6ab58ca4c2cc62627c5c5ec8b135516ce9098f9",
+ "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "21bdf608d2bc3799206065225410ccbb015a379cbcf79a901e4e9420d1a4feb4",
+ "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4b1520615af8f2baad919740716c482cd5ac421bd87e44cde21788e79c996a4c",
+ "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "4aece49879bb274f0170b98941fa220d1ae4f1c4cb33c3fa7ae4146679675d1d",
+ "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "d3c565f7a2a1bcf21849122c1c6fbbf81ce1e8dbaf103e8f5c406b2f35aadde1",
+ "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "311df5769ba9a2889c1e9a97df6c1bd369224832a80789bae339121138e40513",
+ "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "e2818874f3f3d873e858e78585e60804971d57e206c023e8a1c82d03cc9ee5b3",
+ "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "9bb1e02517abfe3e626812cea2d389b26451db341bd1c56f5c06f90a71936cde",
+ "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "fe02b9b389297a781bbdac812ac3526973a221edc2cd7b2be4fcb197e817b148",
+ "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c6733d130bda448d7801caa215d3f58abd6576119eb764a55c326344fcbbdede",
+ "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "0a553a9821eb076873976bf523c8b1278de367854d6fbca0728bde97768c4ec9",
+ "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "c5a724275014bf1c244ff6ab878271747097b3f216e5753e3ca65c1714a2456a",
+ "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "0a6ff560eb1a7d02e48661939bbb940cdb5d988ccacbcbdc0f7fa24890b0d9b2",
+ "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "da487112240ab21c3b3f9d9816e7b4738022f58ba0e93c0772a8fcbb17ba0573",
+ "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "944bd6f24ff92a748c804e3deac1994fe03cda4b897be3eb12f21d069add4cdd",
+ "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "e986624d0a97155a588c9b95c7470c1b322bbae11f9582ad62d2c914642400d9",
+ "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "dbaf95a9b3f6fccab5d59533be35f59b7901b31e61488f85032bd15bfb67eb34",
+ "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "374bd970d5cba1b9af4a36250dfea2eaacafd9e6b4b0d4d9165abdd11841d4c3",
+ "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "2ddec9e30d15f2e1f05e9a59c739f1be51fc8d836acda395aacfb933826a5637",
+ "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "a21a1c099324517b6da6dfd8f2154b4d32bfe69d3a1f386e1bc5be2c3743b938",
+ "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b81fa8c2d534386ceb0bb0767c260e340cda7122e23c834afb17097976ff682d",
+ "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "2822fdb98095c292a4e0b0e6ee3be4e1cc5ffda42dae101b2c6a6c4bb7a1ec4e",
+ "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7d40bef08d3f0d097755eae0b26057f579fd40f4968dd9e5cc82c2b9b67d9c0e",
+ "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f64962ca9b60013ce98e634ebb5207dac14c7b39aca5de37db8a6b3debad7250",
+ "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "a3f8dfb574b3af0ac48011cc7ec69d9f3e89a1994a475c3c6920b0a110db141c",
+ "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6dcce24fa93e66b69495df2d8e9aee15bbba263945fa3dea5cdb1d2c499c9744",
+ "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "038d888fea4ff185329b4ac93066167ec7cfd05a3f23be0a2fae5b8eab51d0ac",
+ "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "6a83680ff659d7b9717639d56eb18c230162ee4983ce5ac4aef78b8d9d0829ef",
+ "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "43313c88c1950ec36549f023d8e7b6c6cccb9749159115dad5255451c65f98c8",
+ "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "635544e9035d213ac7e3a82d08b445b2a446119511c219c0ad870f185133f76d",
+ "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e2fca8f43e37ed2d4896df1429e9b806f02b0e8bdd0f136cf16f606eb1ac15e2",
+ "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "ae8bafeb6423cb270b3a2538db07946d35f2514d5d5116ea085a78e4b80596aa",
+ "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c8abe082666ea792414943eab46d00727acafa97760e799a4d22ec9ff27a810f",
+ "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "b680196dea6eb4bf49afa002e6115645a67c2f7ed6de8ffcc0ace6ed2c193c76",
+ "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "1d3cca881398f45c8ef9db64820cd2afb542b55517c9ea66b71955a31fb7fad1",
+ "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.gz": "493431cd41fae24883877615ca83c1a4e94cafa7e6d6f587dfcce9782c36edaa",
+ "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.xz": "08b5610cc53cfe64914866b115ca15d184df83cf0c8bb65106380bd875bf62cb",
+ "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "17c0e93976b2a83df5f6baabd67412389550f3694268e5478440c8579efbbd18",
+ "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "0e736cf5ac25a78e611ea89589a8f6f0eda9891646579fe0a0b8853ab210ee19",
+ "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "33f17eb3e95e4b00895c234f5d2d2c9ce19d1d36811bebc3f92bcfeed770a6bf",
+ "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b26e0adcfeb9b95dce5d39c7d34126a405d9705cf58a6ee560b10eeb274b6ef0",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "27d6e27acb2d060b59e35789b81779f48a520670ad1590cb46b9862a6be74a63",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "39670b9f1865ab74458dded5a9e9f181045c8eb7e7bc82ffc308fcbc5bc26267",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "d970bcce7178cc0ddb96de50450da71b236ab56861efd399da03f916ce059685",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "6d6bda8752a6b205ca8e155624f671e716e80c78256f052c22dc2e53c379b589",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "e667282411745dfa982922d139a26058097250c33e83ca955e75b65c6098f651",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "7ed509f918aed5d259479663911427564c066b41487d4550050a9c07096344d9",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "59b3aac5504deea4daf79d5ee90951c3df5247568419a3605c8895698e7a460c",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "941f93fd0a542b9aa6b35fe26a5145085cf758c10b185e9892acf52796efe944",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "755987f90f50bbcf9881f62849bfc5749e41d95e5d6b2a35c7fce4218ba3dc60",
+ "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "09cead4864a49e750d91438149b74fa4c0d4b923efda40ba638b2ca0d3ad97c6",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "17e7cb26d7c13cc14d826966a4b93e9c152b46f2d7081038e8d3385ed5d3ba43",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "85f896275ecef1d491bb8beab54ab13d612d49fb8386b6b61d9121f52fb15e44",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e948e456f51a9fb983d36d15352d8e7782051e1fb62a4adad2ae973725aa6091",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "d21b59cc2c1706e9c14bf1464b17ed5bd51e2d225e1b3ea53c13d90ae34d4a2d",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "a51b04fa8b159ac5c80ec1db0518cf589a8530820863870173347941a5d3e0e0",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "bbb801bd4ddaeb4d2494039943e8ac746fd41fb625d3c544af2a79587f9e327e",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "8d94c74ac727b381433ff010d6a5b6576d326c88418afb1ee8a67de5731c1bd9",
+ "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "da44eae518dc561f89c810d4a5f50da38b938e22542193595be615c147973ee9",
+ "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "11e8422a4b4ab386015c54cf488c40297e6b63006989c40b1e4321a325333433",
+ "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "b8e835cfd7f32a823ed00d174c4158220b8572c2d76486c60a20cbdad11bb216",
+ "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "ff7a412a7923a24cb118979cc772863e6d9844ab6bcc619d9adca6d36b89daf8",
+ "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "4fcf56bfbae46ff5cf7c28d787992d5d108231659e447cecbd25035009e0c783",
+ "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "4ae574d1aab0e0c191327fa5ad79a4e9367702ef3fd1655661a8c253bf55b7e3",
+ "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8786f646813f5ab71f5786efa6cc14e567a9dd1b2532b34d9d85ee900dafe68c",
+ "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "752fdf667b1f4713b6ad3378a15835902fd7fea200c8d37f28a444dc3616b89d",
+ "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "43e401e2112120970c4a7e3dacbc5ea631c1816f27db33a28f5b9cc49e4dd5da",
+ "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "6935d612513b61092b36bae3a2cb11c29e05cd8773c65aa61b4451dab8cb9f43",
+ "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "326177f9fda4923b010fdbefbb9703aee727b4d2871ffb1cc97321c09fc3ff51",
+ "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "875d3d7fc0e1cfda7b029656b27436f2b9d332b3f46988dba1cfbfd8d244cd7e",
+ "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "4b3e9d27d256cbbe65c0330d557dbcdd6b6144222936680705f9e74deabe80f0",
+ "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "d26a73c2ccaee81d92980a3cca0508abfce7a02f56f25f3bf9c06e6fcf3aa537",
+ "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "3f69c9a1161aeb25f03681e43d35388bf75a0e20e086d6e353911aa839fcd294",
+ "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "401fbf935e3b06e185f4426a655f2d38e058409921486758f60363f92bbc8117",
+ "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "325d89dc02f7aea4803539211c45d8044986d55f7d1331a231b5d0c0ecfe5238",
+ "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "3da7ef60aff98439a1c58d504bc62aac1d2cfa29879a28968c5a61b72e9fa33f",
+ "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "3aa2757120df94d2660b7e909e4a7d66aa73ca9f9b700231d1f21bdea2b0b5db",
+ "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "74a28139895365cdffdece9920ba6fd31a982cd5620342fbdd653084621b7726",
+ "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "7915f9e15b274e938d5e318544322d233434b6554a25ff063181e7f9cc8a8ef9",
+ "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3b56ab5ce09e8f90ee80ccfcfdbc30f52309547b5123ef474a78cbbd6ca64dad",
+ "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dcb27f9d9f425b81d7ac21025eae60b2e5bbb4cb1e2c21e6970f28e5a574cbb6",
+ "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "cb5627d2075b726c4a30b36cdf234371d02f1fe0b545fd50e02b65588b7bbe5f",
+ "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "d7d075dc678d545fedfdff220dd6b9b9c91cbf5b58fd9cb486777c596c20c20f",
+ "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "fe6af0046c2a6cc8c66d0d51590c7a725115fe785b06bed555c9c68dfaf9819f",
+ "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "559b98d646138414c3e0878bdc8245db35c17f9e804ccc0935c4f397672debcd",
+ "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "cda6141eff957bf7f7580b093d261d690fd660961722c37b19c390cb4ce85ecf",
+ "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7c4eaccfd5704b0d6e7dfeb6cd70922625df90391f1e27e48bc75f0e79b3832a",
+ "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1d16189f4fe2c5d6fb572e279eab121408c1d85d5fecb6a3f25b00ed748b8b14",
+ "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "99be46da8f40418b48261e61a645acd4755c132baf9e2f3a2ca64e853daab9ec",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "82daf2631178e46d94ce2a2718327c5e17da755397cfcddaff4b9d695aa88f3a",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6288c9cbf5e33c59597d990bf99c9536414bb73aa0bcedf1175dab4c6dd9d188",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "29e13fd9d3eb61ea609bbb55bc5f36df094623f1f1a154d9554212bf4021b8cb",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c287a80d6388527213d820c22d723fb9e17018425795f499521e7580ed9f6aed",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "2eefa9ae776a7760b3111b39e2c732d2303c4aab2e124cfbef2f7dddc32bdc30",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "a5544207cad0be04393f3a17f8f743340bf468d20a60aa44bbf3b1ea476e54d4",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "b4dfbc422e7b51db45555e6d1b775b214bf633ec6c93303fb7c52e4e25db69e4",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "158c6366adaaaf17d0d40f64a9c8887fc20f1c7600fb31b102fcc3bcbd388221",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "6fda2931d41c4c42b5f59df4a789ff3c2082ff65892e1318439aec555834a34e",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "25a2823ba3668506fe9bb85c1f51d2406b8654c4197d1dc7d88ee19f35e77756",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "2a79c57d33aca5bb6c0cc2497d6853a4df259537ba55acc66460be03c82cc9c0",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "065d95fc9b2d741ba1e8d20b90820a6ad72ce0cb802fd24842aacf01c3a7a589",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "313ea554f824d0176f44406ed70854736eefe94911182396c896ed454a07e6b8",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "23cce7c791cc4f49d5240898803b47f393b5f2f064a3273ffd290a8cf97b7591",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0416a1a4ad3b9c9e1bf7bd67e49f16e7a4011ebd784966f439ac04a87cb4042f",
+ "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "64b29ff6dabc46d124ccf08e8fe351a2d46ed527efe98de36d38c0ec59b226cc"
+ }
+}
+++ /dev/null
-# This file describes the stage0 compiler that's used to then bootstrap the Rust
-# compiler itself.
-#
-# Currently Rust always bootstraps from the previous stable release, and in our
-# train model this means that the master branch bootstraps from beta, beta
-# bootstraps from current stable, and stable bootstraps from the previous stable
-# release.
-#
-# If you're looking at this file on the master branch, you'll likely see that
-# rustc is configured to `beta`, whereas if you're looking at a source tarball
-# for a stable release you'll likely see `1.x.0` for rustc, with the previous
-# stable release's version number. `date` is the date where the release we're
-# bootstrapping off was released.
-
-date: 2021-07-29
-rustc: beta
-
-# We use a nightly rustfmt to format the source because it solves some
-# bootstrapping issues with use of new syntax in this repo. If you're looking at
-# the beta/stable branch, this key should be omitted, as we don't want to depend
-# on rustfmt from nightly there.
-rustfmt: nightly-2021-03-25
-
-# When making a stable release the process currently looks like:
-#
-# 1. Produce stable build, upload it to dev-static
-# 2. Produce a beta build from the previous stable build, upload to static
-# 3. Produce a nightly build from previous beta, upload to static
-# 4. Upload stable build to static, publish full release
-#
-# This means that there's a small window of time (a few days) where artifacts
-# are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org.
-# In order to ease this transition we have an extra key which is in the
-# configuration file below. When uncommented this will instruct the bootstrap.py
-# script to download from dev-static.rust-lang.org.
-#
-# This key is typically commented out at all times. If you're looking at a
-# stable release tarball it should *definitely* be commented out. If you're
-# looking at a beta source tarball and it's uncommented we'll shortly comment it
-# out.
-
-#dev: 1
+ bb6: {
_0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+ StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- goto -> bb23; // scope 0 at no-location
+ goto -> bb20; // scope 0 at no-location
}
- bb11: {
+ bb8: {
StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+ StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- bb12: {
+ bb9: {
StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+ StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
- falseEdge -> [real: bb2, imaginary: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+ bb11: {
_0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+ StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- goto -> bb23; // scope 0 at no-location
+ goto -> bb20; // scope 0 at no-location
}
- bb16: {
+ bb13: {
StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+ StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- bb17: {
+ bb14: {
StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
- StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+ StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
- falseEdge -> [real: bb4, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+ bb15: {
StorageDead(_7); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
StorageDead(_5); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
- StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
- goto -> bb22; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
}
bb7: {
+ StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
StorageLive(_5); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
_1 = (const 1_i32, move _8); // scope 2 at $DIR/match_false_edges.rs:16:31: 16:37
StorageDead(_8); // scope 2 at $DIR/match_false_edges.rs:16:36: 16:37
StorageDead(_5); // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
- StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
StorageDead(_6); // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
goto -> bb10; // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
}
bb8: {
- StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
+ StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
StorageDead(_6); // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
goto -> bb3; // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
}
}
bb7: {
+ StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
StorageLive(_5); // scope 0 at $DIR/match_false_edges.rs:27:14: 27:15
_1 = (const 1_i32, move _8); // scope 2 at $DIR/match_false_edges.rs:27:31: 27:37
StorageDead(_8); // scope 2 at $DIR/match_false_edges.rs:27:36: 27:37
StorageDead(_5); // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
- StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
StorageDead(_6); // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
goto -> bb10; // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
}
bb8: {
- StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
+ StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
StorageDead(_6); // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
falseEdge -> [real: bb3, imaginary: bb1]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
}
}
bb7: {
+ StorageDead(_8); // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
FakeRead(ForMatchGuard, _5); // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
FakeRead(ForGuardBinding, _7); // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
StorageLive(_6); // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
_6 = ((_2 as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
_1 = const 1_i32; // scope 2 at $DIR/match_false_edges.rs:36:32: 36:33
StorageDead(_6); // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
- StorageDead(_8); // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
goto -> bb14; // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
}
bb8: {
- StorageDead(_8); // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
+ StorageDead(_8); // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
StorageDead(_7); // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
falseEdge -> [real: bb1, imaginary: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
}
bb12: {
StorageDead(_13); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
+ StorageDead(_12); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
FakeRead(ForMatchGuard, _5); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
FakeRead(ForGuardBinding, _11); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
StorageLive(_10); // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
_10 = ((_2 as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
_1 = const 3_i32; // scope 4 at $DIR/match_false_edges.rs:38:33: 38:34
StorageDead(_10); // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
- StorageDead(_12); // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
StorageDead(_11); // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
goto -> bb14; // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
}
bb13: {
StorageDead(_13); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
- StorageDead(_12); // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
+ StorageDead(_12); // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
StorageDead(_11); // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
falseEdge -> [real: bb3, imaginary: bb3]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
}
}
bb10: {
+ StorageDead(_9); // scope 2 at $DIR/match_test.rs:13:18: 13:19
FakeRead(ForMatchGuard, _8); // scope 2 at $DIR/match_test.rs:13:18: 13:19
_3 = const 0_i32; // scope 2 at $DIR/match_test.rs:13:23: 13:24
- StorageDead(_9); // scope 2 at $DIR/match_test.rs:13:23: 13:24
goto -> bb14; // scope 2 at $DIR/match_test.rs:13:23: 13:24
}
bb11: {
- StorageDead(_9); // scope 2 at $DIR/match_test.rs:13:23: 13:24
+ StorageDead(_9); // scope 2 at $DIR/match_test.rs:13:18: 13:19
falseEdge -> [real: bb3, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:18: 13:19
}
+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
-- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
- }
-
- bb8: {
+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
-- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
- }
-
- bb8: {
}
bb5: {
+ StorageDead(_8); // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
- FakeRead(ForMatchGuard, _5); // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
- FakeRead(ForMatchGuard, _6); // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
_0 = const 0_i32; // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
- StorageDead(_8); // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
goto -> bb7; // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
}
bb6: {
- StorageDead(_8); // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
+ StorageDead(_8); // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
goto -> bb1; // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
}
--- /dev/null
+# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
+
+# This test case makes sure that native libraries are linked with --whole-archive semantics
+# when the `-bundle,+whole-archive` modifiers are applied to them.
+#
+# The test works by checking that the resulting executables produce the expected output,
+# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+# that code would never make it into the final executable and we'd thus be missing some
+# of the output.
+
+-include ../../run-make-fulldeps/tools.mk
+
+all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linked) $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
+ $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
+ $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
+ $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
+
+# Native lib linked directly into executable
+$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) directly_linked.rs -Z unstable-options -l static:+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
+ $(RUSTC) indirectly_linked.rs
+
+# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
+ $(RUSTC) indirectly_linked_via_attr.rs
+
+# Native lib linked into rlib with via commandline
+$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) rlib_with_cmdline_native_lib.rs -Z unstable-options --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into rlib via `#[link()]` attribute on extern block.
+$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+ $(RUSTC) native_lib_in_src.rs --crate-type=rlib
+
+$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
+ $(call COMPILE_OBJ_CXX,$@,$<)
--- /dev/null
+#include <cstdio>
+
+// Since this is a global variable, its constructor will be called before
+// main() is executed. But only if the object file containing it actually
+// gets linked into the executable.
+struct Foo {
+ Foo() {
+ printf("static-initializer.");
+ fflush(stdout);
+ }
+} FOO;
--- /dev/null
+use std::io::Write;
+
+fn main() {
+ print!("directly_linked.");
+ std::io::stdout().flush().unwrap();
+}
--- /dev/null
+extern crate rlib_with_cmdline_native_lib;
+
+fn main() {
+ rlib_with_cmdline_native_lib::hello();
+}
--- /dev/null
+extern crate native_lib_in_src;
+
+fn main() {
+ native_lib_in_src::hello();
+}
--- /dev/null
+#![feature(native_link_modifiers_bundle)]
+#![feature(native_link_modifiers_whole_archive)]
+#![feature(native_link_modifiers)]
+
+use std::io::Write;
+
+#[link(name = "c_static_lib_with_constructor",
+ kind = "static",
+ modifiers = "-bundle,+whole-archive")]
+extern {}
+
+pub fn hello() {
+ print!("native_lib_in_src.");
+ std::io::stdout().flush().unwrap();
+}
--- /dev/null
+use std::io::Write;
+
+pub fn hello() {
+ print!("indirectly_linked.");
+ std::io::stdout().flush().unwrap();
+}
// @!has type_layout/trait.MyTrait.html 'Size: '
pub trait MyTrait {}
+
+// @has type_layout/enum.Variants.html 'Size: '
+// @has - '2 bytes'
+// @has - '<code>A</code>: 0 bytes'
+// @has - '<code>B</code>: 1 byte'
+pub enum Variants {
+ A,
+ B(u8),
+}
+
+// @has type_layout/enum.WithNiche.html 'Size: '
+// @has - //p '4 bytes'
+// @has - '<code>None</code>: 0 bytes'
+// @has - '<code>Some</code>: 4 bytes'
+pub enum WithNiche {
+ None,
+ Some(std::num::NonZeroU32),
+}
--- /dev/null
+// edition:2021
+
+#![feature(rustc_attrs)]
+
+// Test that we can't move out of struct that impls `Drop`.
+
+
+use std::rc::Rc;
+
+// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths
+// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop.
+pub fn test1() {
+ struct Foo(Rc<i32>);
+
+ impl Drop for Foo {
+ fn drop(self: &mut Foo) {}
+ }
+
+ let f = Foo(Rc::new(1));
+ let x = #[rustc_capture_analysis] move || {
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ println!("{:?}", f.0);
+ //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture f[] -> ByValue
+ };
+
+ x();
+}
+
+// Test that we don't restrict precision when moving `Copy` types(i.e. when copying),
+// even if any of the parent paths implement `Drop`.
+fn test2() {
+ struct Character {
+ hp: u32,
+ name: String,
+ }
+
+ impl Drop for Character {
+ fn drop(&mut self) {}
+ }
+
+ let character = Character { hp: 100, name: format!("A") };
+
+ let c = #[rustc_capture_analysis] move || {
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ println!("{}", character.hp)
+ //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture character[(0, 0)] -> ByValue
+ };
+
+ c();
+
+ println!("{}", character.name);
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/issue-88476.rs:20:13
+ |
+LL | let x = #[rustc_capture_analysis] move || {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/issue-88476.rs:47:13
+ |
+LL | let c = #[rustc_capture_analysis] move || {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+ --> $DIR/issue-88476.rs:20:39
+ |
+LL | let x = #[rustc_capture_analysis] move || {
+ | _______________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Capturing f[(0, 0)] -> ImmBorrow
+ --> $DIR/issue-88476.rs:25:26
+ |
+LL | println!("{:?}", f.0);
+ | ^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/issue-88476.rs:20:39
+ |
+LL | let x = #[rustc_capture_analysis] move || {
+ | _______________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Min Capture f[] -> ByValue
+ --> $DIR/issue-88476.rs:25:26
+ |
+LL | println!("{:?}", f.0);
+ | ^^^
+
+error: First Pass analysis includes:
+ --> $DIR/issue-88476.rs:47:39
+ |
+LL | let c = #[rustc_capture_analysis] move || {
+ | _______________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Capturing character[(0, 0)] -> ImmBorrow
+ --> $DIR/issue-88476.rs:52:24
+ |
+LL | println!("{}", character.hp)
+ | ^^^^^^^^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/issue-88476.rs:47:39
+ |
+LL | let c = #[rustc_capture_analysis] move || {
+ | _______________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Min Capture character[(0, 0)] -> ByValue
+ --> $DIR/issue-88476.rs:52:24
+ |
+LL | println!("{}", character.hp)
+ | ^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// check-pass
+// edition:2021
+
+use std::rc::Rc;
+
+// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths
+// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop.
+pub fn test1() {
+ struct Foo(Rc<i32>);
+
+ impl Drop for Foo {
+ fn drop(self: &mut Foo) {}
+ }
+
+ let f = Foo(Rc::new(1));
+ let x = move || {
+ println!("{:?}", f.0);
+ };
+
+ x();
+}
+
+
+// Test that we don't restrict precision when moving `Copy` types(i.e. when copying),
+// even if any of the parent paths implement `Drop`.
+pub fn test2() {
+ struct Character {
+ hp: u32,
+ name: String,
+ }
+
+ impl Drop for Character {
+ fn drop(&mut self) {}
+ }
+
+ let character = Character { hp: 100, name: format!("A") };
+
+ let c = move || {
+ println!("{}", character.hp)
+ };
+
+ c();
+
+ println!("{}", character.name);
+}
+
+fn main() {}
| ^^^^^^ method not found in `&TheStruct`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use Lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use Lib::TheTrait;
+ |
error: aborting due to previous error
| ^^^^^^ method not found in `&TheStruct`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use coherence_inherent_cc_lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use coherence_inherent_cc_lib::TheTrait;
+ |
error: aborting due to previous error
--- /dev/null
+#![feature(generic_const_exprs, array_map)]
+#![allow(incomplete_features)]
+
+pub struct ConstCheck<const CHECK: bool>;
+
+pub trait True {}
+impl True for ConstCheck<true> {}
+
+pub trait OrdesDec {
+ type Newlen;
+ type Output;
+
+ fn pop(self) -> (Self::Newlen, Self::Output);
+}
+
+impl<T, const N: usize> OrdesDec for [T; N]
+where
+ ConstCheck<{N > 1}>: True,
+ [T; N - 1]: Sized,
+{
+ type Newlen = [T; N - 1];
+ type Output = T;
+
+ fn pop(self) -> (Self::Newlen, Self::Output) {
+ let mut iter = IntoIter::new(self);
+ //~^ ERROR: failed to resolve: use of undeclared type `IntoIter`
+ let end = iter.next_back().unwrap();
+ let new = [(); N - 1].map(move |()| iter.next().unwrap());
+ (new, end)
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared type `IntoIter`
+ --> $DIR/issue-82956.rs:25:24
+ |
+LL | let mut iter = IntoIter::new(self);
+ | ^^^^^^^^ not found in this scope
+ |
+help: consider importing one of these items
+ |
+LL | use std::array::IntoIter;
+ |
+LL | use std::collections::binary_heap::IntoIter;
+ |
+LL | use std::collections::btree_map::IntoIter;
+ |
+LL | use std::collections::btree_set::IntoIter;
+ |
+ and 8 other candidates
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
--- /dev/null
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+trait Bar<const N: usize> {}
+
+trait Foo<'a> {
+ const N: usize;
+ type Baz: Bar<{ Self::N }>;
+ //~^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
--- /dev/null
+error: unconstrained generic constant
+ --> $DIR/issue-84659.rs:8:15
+ |
+LL | type Baz: Bar<{ Self::N }>;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:`
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait X {
+ const Y: usize;
+}
+
+fn z<T>(t: T)
+where
+ T: X,
+ [(); T::Y]: ,
+{
+}
+
+fn unit_literals() {
+ z(" ");
+ //~^ ERROR: the trait bound `&str: X` is not satisfied
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `&str: X` is not satisfied
+ --> $DIR/issue-86530.rs:16:7
+ |
+LL | z(" ");
+ | ^^^ the trait `X` is not implemented for `&str`
+ |
+note: required by a bound in `z`
+ --> $DIR/issue-86530.rs:10:8
+ |
+LL | fn z<T>(t: T)
+ | - required by a bound in this
+LL | where
+LL | T: X,
+ | ^ required by this bound in `z`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+ const ASSOC_C: usize;
+ fn foo() where [(); Self::ASSOC_C]:;
+}
+
+struct Bar<const N: &'static ()>;
+impl<const N: &'static ()> Foo for Bar<N> {
+ const ASSOC_C: usize = 3;
+
+ fn foo() where [u8; Self::ASSOC_C]: {
+ let _: [u8; Self::ASSOC_C] = loop {};
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features, unused_variables)]
+
+struct F<const S: &'static str>;
+impl<const S: &'static str> X for F<{ S }> {
+ const W: usize = 3;
+
+ fn d(r: &[u8; Self::W]) -> F<{ S }> {
+ let x: [u8; Self::W] = [0; Self::W];
+ F
+ }
+}
+
+pub trait X {
+ const W: usize;
+ fn d(r: &[u8; Self::W]) -> Self;
+}
+
+fn main() {}
--- /dev/null
+trait Trait<const N: usize> {
+ const Assoc: usize;
+}
+
+impl<const N: usize> Trait<N> for () {
+ const Assoc: usize = 1;
+}
+
+
+pub const fn foo<const N: usize>() where (): Trait<N> {
+ let bar = [(); <()>::Assoc];
+ //~^ error: constant expression depends on a generic parameter
+}
+
+trait Trait2<const N: usize> {
+ const Assoc2: usize;
+}
+
+impl<const N: usize> Trait2<N> for () {
+ const Assoc2: usize = N - 1;
+}
+
+
+pub const fn foo2<const N: usize>() where (): Trait2<N> {
+ let bar2 = [(); <()>::Assoc2];
+ //~^ error: constant expression depends on a generic parameter
+}
+
+fn main() {
+ foo::<0>();
+ foo2::<0>();
+}
--- /dev/null
+error: constant expression depends on a generic parameter
+ --> $DIR/sneaky-array-repeat-expr.rs:11:20
+ |
+LL | let bar = [(); <()>::Assoc];
+ | ^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+ --> $DIR/sneaky-array-repeat-expr.rs:25:21
+ |
+LL | let bar2 = [(); <()>::Assoc2];
+ | ^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
error: aborting due to previous error
|
= note: conflicting implementation in crate `complex_impl_support`:
- impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
- where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: FnOnce<(T,)>, U: 'static, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
+ where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/complex-impl.rs:9:1
LL | trait GenericLifetimeAT<'a> {
| ^^^^^^^^^^^^^^^^^ --
-error[E0106]: missing lifetime specifier
- --> $DIR/wrong-number-of-args.rs:169:44
- |
-LL | type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
- | ^ expected named lifetime parameter
- |
-help: consider introducing a named lifetime parameter
- |
-LL | type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
- | ++++ +++
-
error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:169:26
|
LL | trait GenericLifetimeAT<'a> {
| ^^^^^^^^^^^^^^^^^
+error[E0106]: missing lifetime specifier
+ --> $DIR/wrong-number-of-args.rs:169:44
+ |
+LL | type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
+ | ++++ +++
+
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:181:26
|
LL | type C = Box<dyn GenericTypeAT<'static, A, AssocTy=()>>;
| +++
-error[E0106]: missing lifetime specifier
- --> $DIR/wrong-number-of-args.rs:201:48
- |
-LL | type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
- | ^ expected named lifetime parameter
- |
-help: consider introducing a named lifetime parameter
- |
-LL | type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
- | ++++ +++
-
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:201:26
|
LL | type A = Box<dyn GenericLifetimeTypeAT<A, AssocTy=()>>;
| ++
+error[E0106]: missing lifetime specifier
+ --> $DIR/wrong-number-of-args.rs:201:48
+ |
+LL | type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
+ | ++++ +++
+
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:207:26
|
LL | type D<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), AssocTy=()>>;
| ++++ +++
-error[E0106]: missing lifetime specifier
- --> $DIR/wrong-number-of-args.rs:221:48
- |
-LL | type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
- | ^ expected named lifetime parameter
- |
-help: consider introducing a named lifetime parameter
- |
-LL | type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
- | ++++ +++
-
error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:221:26
|
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ -
+error[E0106]: missing lifetime specifier
+ --> $DIR/wrong-number-of-args.rs:221:48
+ |
+LL | type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
+ | ++++ +++
+
error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:227:26
|
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
| ++++
-error[E0106]: missing lifetime specifiers
- --> $DIR/wrong-number-of-args.rs:279:56
- |
-LL | type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
- | ^ expected 2 lifetime parameters
- |
-help: consider introducing a named lifetime parameter
- |
-LL | type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
- | ++++ +++++++
-
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:279:26
|
LL | type A = Box<dyn GenericLifetimeLifetimeTypeAT<A, AssocTy=()>>;
| ++
+error[E0106]: missing lifetime specifiers
+ --> $DIR/wrong-number-of-args.rs:279:56
+ |
+LL | type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
+ | ^ expected 2 lifetime parameters
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
+ | ++++ +++++++
+
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:285:26
|
--- /dev/null
+// check-pass
+// edition:2018
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>;
+
+fn main() {
+ f();
+}
+
+async fn f() {
+ run("dependency").await;
+}
+
+struct InMemoryStorage;
+
+struct User<'dep> {
+ dep: &'dep str,
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+ fn execute(&self) -> BoxFuture<Result<(), String>> {
+ todo!()
+ }
+}
+
+trait Storage {
+ type Error;
+}
+
+impl Storage for InMemoryStorage {
+ type Error = String;
+}
+
+trait StorageRequestReturnType {
+ type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+ fn execute(
+ &self,
+ ) -> BoxFuture<Result<<Self as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+struct SaveUser<'a> {
+ name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+ type Output = ();
+}
+
+impl<'dep> User<'dep> {
+ async fn save<S>(self)
+ where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+ {
+ SaveUser { name: "Joe" }
+ .execute()
+ .await;
+ }
+}
+
+async fn run<S>(dep: &str)
+where
+ S: Storage,
+ for<'a> SaveUser<'a>: StorageRequest<S>,
+{
+ User { dep }.save().await;
+}
--- /dev/null
+// check-pass
+
+trait Bar {
+ type Type;
+}
+struct Foo<'a>(&'a ());
+impl<'a> Bar for Foo<'a> {
+ type Type = ();
+}
+
+fn func<'a>(_: <Foo<'a> as Bar>::Type) {}
+fn assert_is_func<A>(_: fn(A)) {}
+
+fn test()
+where
+ for<'a> <Foo<'a> as Bar>::Type: Sized,
+{
+ assert_is_func(func);
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+pub trait Indexable {
+ type Idx;
+}
+impl Indexable for u8 {
+ type Idx = u8;
+}
+impl Indexable for u16 {
+ type Idx = u16;
+}
+
+pub trait Indexer<T: Indexable>: std::ops::Index<T::Idx, Output = T> {}
+
+trait StoreIndex: Indexer<u8> + Indexer<u16> {}
+
+fn foo(st: &impl StoreIndex) -> &dyn StoreIndex {
+ st as &dyn StoreIndex
+}
+
+fn main() {}
--- /dev/null
+#![feature(unboxed_closures)]
+
+trait SomeTrait<'a> {
+ type Associated;
+}
+
+fn give_me_ice<T>() {
+ callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+ //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied
+}
+
+fn callee<T: Fn<(&'static (),)>>() {
+ println!("{}", std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>());
+}
+
+fn main() {
+ give_me_ice::<()>();
+}
--- /dev/null
+error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
+ --> $DIR/issue-85455.rs:8:5
+ |
+LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | fn give_me_ice<T: SomeTrait<'_>>() {
+ | +++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
| ^^^^^ method not found in `()`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use std::clone::Clone;`
= note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::clone::Clone;
+ |
error: aborting due to 2 previous errors
| ^ method not found in `()`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use foo::T;`
= note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use foo::T;
+ |
error: aborting due to previous error
| ^^^ method not found in `&B`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use a::A;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use a::A;
+ |
error: aborting due to previous error
| ----------- `NonCopyable` defined here
...
LL | let z = NonCopyable{ p: () };
- | ----------- ^ field does not exist
- | |
- | help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)`
+ | ^ field does not exist
+ |
+help: `NonCopyable` is a tuple struct, use the appropriate syntax
+ |
+LL | let z = NonCopyable(/* fields */);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
| -- `Enum::V1` defined here
...
LL | Enum::V1 { x }
- | -------- ^ field does not exist
- | |
- | help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
+ | ^ field does not exist
+ |
+help: `Enum::V1` is a tuple variant, use the appropriate syntax
+ |
+LL | Enum::V1(/* fields */)
+ | ~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
#![deny(unused)]
//~^ ERROR: deny(unused) incompatible with previous forbid
//~| WARNING being phased out
- //~| ERROR: deny(unused) incompatible with previous forbid
- //~| WARNING being phased out
#![warn(unused)]
#![allow(unused)]
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-error: deny(unused) incompatible with previous forbid
- --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
- |
-LL | #![forbid(unused)]
- | ------ `forbid` level set here
-LL | #![deny(unused)]
- | ^^^^^^ overruled by previous forbid
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
#![forbid(unused, non_snake_case)]
#![forbid(forbidden_lint_groups)]
-#[allow(unused_variables)] //~ ERROR incompatible with previous
+#[allow(unused_variables)]
//~^ ERROR incompatible with previous
//~| WARNING this was previously accepted by the compiler
-//~| WARNING this was previously accepted by the compiler
fn foo() {}
#[allow(unused)] //~ ERROR incompatible with previous
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
error: allow(unused) incompatible with previous forbid
- --> $DIR/outer-forbid.rs:26:9
+ --> $DIR/outer-forbid.rs:25:9
|
LL | #![forbid(unused, non_snake_case)]
| ------ `forbid` level set here
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
error[E0453]: allow(nonstandard_style) incompatible with previous forbid
- --> $DIR/outer-forbid.rs:30:9
+ --> $DIR/outer-forbid.rs:29:9
|
LL | #![forbid(unused, non_snake_case)]
| -------------- `forbid` level set here
LL | #[allow(nonstandard_style)]
| ^^^^^^^^^^^^^^^^^ overruled by previous forbid
-error: allow(unused_variables) incompatible with previous forbid
- --> $DIR/outer-forbid.rs:20:9
- |
-LL | #![forbid(unused, non_snake_case)]
- | ------ `forbid` level set here
-...
-LL | #[allow(unused_variables)]
- | ^^^^^^^^^^^^^^^^ overruled by previous forbid
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0453`.
struct S4<T>(T) where for<'a> T: ?Trait<'a>;
//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+//~| WARN default bound relaxed for a type parameter
struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
//~^ ERROR type parameter has more than one relaxed default bound
| ^
error: `?Trait` bounds are only permitted at the point where a type parameter is declared
- --> $DIR/maybe-bounds-where.rs:20:18
+ --> $DIR/maybe-bounds-where.rs:21:18
|
LL | fn f() where T: ?Sized {}
| ^
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+ --> $DIR/maybe-bounds-where.rs:12:11
+ |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+ | ^
+
error[E0203]: type parameter has more than one relaxed default bound, only one is supported
- --> $DIR/maybe-bounds-where.rs:15:11
+ --> $DIR/maybe-bounds-where.rs:16:11
|
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
| ^
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
- --> $DIR/maybe-bounds-where.rs:15:11
+ --> $DIR/maybe-bounds-where.rs:16:11
|
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
| ^
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0203`.
|
= note: the following trait bounds were not satisfied:
`Foo: Debug`
+help: consider annotating `Foo` with `#[derive(Debug)]`
+ |
+LL | #[derive(Debug)]
+ |
error: aborting due to previous error
// arms whose patterns were composed solely of constants to not have
// them linked in the cfg.
//
-// THis was broken for various reasons. In particular, that hack was
+// This was broken for various reasons. In particular, that hack was
// originally authored under the assunption that other checks
// elsewhere would ensure that the two patterns did not overlap. But
// that assumption did not hold, at least not in the long run (namely,
--- /dev/null
+// compile-flags: -Zunstable-options --crate-type rlib
+// build-fail
+// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+#![feature(native_link_modifiers)]
+#![feature(native_link_modifiers_bundle)]
+#![feature(native_link_modifiers_whole_archive)]
+
+#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
+extern "C" { }
+
+fn main() { }
--- /dev/null
+error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+error: could not find native static library `mylib`, perhaps an -L flag is missing?
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Mixing +bundle and +whole-archive is not allowed
+
+// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib
+// build-fail
+// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+fn main() { }
--- /dev/null
+error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+error: could not find native static library `mylib`, perhaps an -L flag is missing?
+
+error: aborting due to 2 previous errors
+
| - `S` defined here
...
LL | let s = S{0b1: 10, 0: 11};
- | - ^^^ field does not exist
- | |
- | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
+ | ^^^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let s = S(/* fields */);
+ | ~~~~~~~~~~~~~~~
error[E0026]: struct `S` does not have a field named `0x1`
--> $DIR/numeric-fields.rs:7:17
| ^^^^^^ method not found in `u32`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use crate::foo::foobar::Foobar;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use crate::foo::foobar::Foobar;
+ |
error[E0599]: no method named `bar` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:28:7
| the method is available for `Rc<u8>` here
|
= help: items from traits can only be used if the trait is in scope
- = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
- candidate #1: `use crate::m::TryIntoU32;`
- candidate #2: `use std::convert::TryInto;`
help: consider wrapping the receiver expression with the appropriate type
|
LL | let _: u32 = Box::new(3u8).try_into().unwrap();
|
LL | let _: u32 = Rc::new(3u8).try_into().unwrap();
| ++++++++ +
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+ |
+LL | use crate::m::TryIntoU32;
+ |
+LL | use std::convert::TryInto;
+ |
error: aborting due to previous error
--- /dev/null
+use std::time::Instant;
+
+enum Enum {
+ First
+}
+
+#[derive(Clone)]
+enum CloneEnum {
+ First
+}
+
+struct Struct {
+}
+
+#[derive(Clone)]
+struct CloneStruct {
+}
+
+struct Foo<X, Y> (X, Y);
+impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+ fn test(&self) -> (X, Y) {
+ (self.0, self.1)
+ }
+}
+
+fn test1() {
+ let x = Foo(Enum::First, CloneEnum::First);
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test2() {
+ let x = Foo(Struct{}, CloneStruct{});
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test3() {
+ let x = Foo(Vec::<Enum>::new(), Instant::now());
+ let y = x.test();
+ //~^the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn main() {}
--- /dev/null
+error[E0599]: the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:28:15
+ |
+LL | enum Enum {
+ | ---------
+ | |
+ | doesn't satisfy `Enum: Clone`
+ | doesn't satisfy `Enum: Default`
+...
+LL | enum CloneEnum {
+ | -------------- doesn't satisfy `CloneEnum: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+ | ------------------------ method `test` not found for this
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Enum, CloneEnum>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Enum: Clone`
+ `Enum: Default`
+ `CloneEnum: Default`
+help: consider annotating `Enum` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error[E0599]: the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:34:15
+ |
+LL | struct Struct {
+ | -------------
+ | |
+ | doesn't satisfy `Struct: Clone`
+ | doesn't satisfy `Struct: Default`
+...
+LL | struct CloneStruct {
+ | ------------------ doesn't satisfy `CloneStruct: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+ | ------------------------ method `test` not found for this
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Struct, CloneStruct>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Struct: Clone`
+ `Struct: Default`
+ `CloneStruct: Default`
+help: consider annotating `CloneStruct` with `#[derive(Default)]`
+ |
+LL | #[derive(Default)]
+ |
+help: consider annotating `Struct` with `#[derive(Clone, Default)]`
+ |
+LL | #[derive(Clone, Default)]
+ |
+
+error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
+ --> $DIR/derive-trait-for-method-call.rs:40:15
+ |
+LL | struct Foo<X, Y> (X, Y);
+ | ------------------------ method `test` not found for this
+...
+LL | let y = x.test();
+ | ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+ |
+ ::: $SRC_DIR/std/src/time.rs:LL:COL
+ |
+LL | pub struct Instant(time::Instant);
+ | ---------------------------------- doesn't satisfy `Instant: Default`
+ |
+ ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+ | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+ |
+ = note: the following trait bounds were not satisfied:
+ `Vec<Enum>: Clone`
+ `Instant: Default`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
--- /dev/null
+pub struct S(f32, f32);
+
+pub enum E {
+ V(f32, f32),
+}
+
+fn main() {
+ let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ //~^ ERROR struct `S` has no field named `x`
+ //~| ERROR struct `S` has no field named `y`
+ //~| ERROR struct `S` has no field named `x`
+ //~| ERROR struct `S` has no field named `y`
+ let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ //~^ ERROR variant `E::V` has no field named `x`
+ //~| ERROR variant `E::V` has no field named `y`
+ //~| ERROR variant `E::V` has no field named `x`
+ //~| ERROR variant `E::V` has no field named `y`
+}
--- /dev/null
+error[E0560]: struct `S` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:19
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:27
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:41
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+ | ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:8:49
+ |
+LL | pub struct S(f32, f32);
+ | - `S` defined here
+...
+LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `S` is a tuple struct, use the appropriate syntax
+ |
+LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+ | ~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:22
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:30
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:47
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+ --> $DIR/nested-non-tuple-tuple-struct.rs:13:55
+ |
+LL | V(f32, f32),
+ | - `E::V` defined here
+...
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+ | ^ field does not exist
+ |
+help: `E::V` is a tuple variant, use the appropriate syntax
+ |
+LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+ | ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0559, E0560.
+For more information about an error, try `rustc --explain E0559`.
--- /dev/null
+// build-fail
+#![feature(rustc_attrs)]
+
+// Ensure that non-object-safe methods in Iterator does not generate
+// vtable entries.
+
+#[rustc_dump_vtable]
+trait A: Iterator {}
+//~^ error Vtable
+
+impl<T> A for T where T: Iterator {}
+
+fn foo(_a: &mut dyn A<Item=u8>) {
+}
+
+fn main() {
+ foo(&mut vec![0, 1, 2, 3].into_iter());
+}
--- /dev/null
+error: Vtable entries for `<std::vec::IntoIter<u8> as A>`: [
+ MetadataDropInPlace,
+ MetadataSize,
+ MetadataAlign,
+ Method(<std::vec::IntoIter<u8> as Iterator>::next),
+ Method(<std::vec::IntoIter<u8> as Iterator>::size_hint),
+ Method(<std::vec::IntoIter<u8> as Iterator>::advance_by),
+ Method(<std::vec::IntoIter<u8> as Iterator>::nth),
+]
+ --> $DIR/vtable-non-object-safe.rs:8:1
+ |
+LL | trait A: Iterator {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
// build-fail
#![feature(rustc_attrs)]
+#![feature(negative_impls)]
+#![allow(where_clauses_object_safety)]
// B --> A
#[rustc_dump_vtable]
trait A {
fn foo_a1(&self) {}
- fn foo_a2(&self) where Self: Sized {}
+ fn foo_a2(&self) where Self: Send {}
}
#[rustc_dump_vtable]
trait B: A {
//~^ error Vtable
fn foo_b1(&self) {}
- fn foo_b2() where Self: Sized {}
+ fn foo_b2(&self) where Self: Send {}
}
struct S;
+impl !Send for S {}
impl A for S {}
impl B for S {}
Method(<S as B>::foo_b1),
Vacant,
]
- --> $DIR/vtable-vacant.rs:13:1
+ --> $DIR/vtable-vacant.rs:15:1
|
LL | / trait B: A {
LL | |
LL | | fn foo_b1(&self) {}
-LL | | fn foo_b2() where Self: Sized {}
+LL | | fn foo_b2(&self) where Self: Send {}
LL | | }
| |_^
| ^^^^^ method not found in `&()`
|
= help: items from traits can only be used if the trait is in scope
- = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
- `use std::ops::Deref;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use std::ops::Deref;
+ |
error: aborting due to previous error
= note: the following trait bounds were not satisfied:
`CloneNoCopy: Copy`
which is required by `U5<CloneNoCopy>: Clone`
+help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
+ |
+LL | #[derive(Copy)]
+ |
error[E0277]: the trait bound `U1: Copy` is not satisfied
--> $DIR/union-derive-clone.rs:6:10
= note: the following trait bounds were not satisfied:
`CloneNoCopy: Copy`
which is required by `U5<CloneNoCopy>: Clone`
+help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
+ |
+LL | #[derive(Copy)]
+ |
error[E0277]: the trait bound `U1: Copy` is not satisfied
--> $DIR/union-derive-clone.rs:6:10
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
+help: consider annotating `R` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
error: aborting due to previous error
--- /dev/null
+[package]
+name = "bump-stage0"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.34"
+curl = "0.4.38"
+indexmap = { version = "1.7.0", features = ["serde"] }
+serde = { version = "1.0.125", features = ["derive"] }
+serde_json = "1.0.59"
+toml = "0.5.7"
--- /dev/null
+use anyhow::Error;
+use curl::easy::Easy;
+use indexmap::IndexMap;
+use std::collections::HashMap;
+use std::convert::TryInto;
+
+const DIST_SERVER: &str = "https://static.rust-lang.org";
+const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"];
+const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"];
+
+struct Tool {
+ channel: Channel,
+ version: [u16; 3],
+ checksums: IndexMap<String, String>,
+}
+
+impl Tool {
+ fn new() -> Result<Self, Error> {
+ let channel = match std::fs::read_to_string("src/ci/channel")?.trim() {
+ "stable" => Channel::Stable,
+ "beta" => Channel::Beta,
+ "nightly" => Channel::Nightly,
+ other => anyhow::bail!("unsupported channel: {}", other),
+ };
+
+ // Split "1.42.0" into [1, 42, 0]
+ let version = std::fs::read_to_string("src/version")?
+ .trim()
+ .split('.')
+ .map(|val| val.parse())
+ .collect::<Result<Vec<_>, _>>()?
+ .try_into()
+ .map_err(|_| anyhow::anyhow!("failed to parse version"))?;
+
+ Ok(Self { channel, version, checksums: IndexMap::new() })
+ }
+
+ fn update_json(mut self) -> Result<(), Error> {
+ std::fs::write(
+ "src/stage0.json",
+ format!(
+ "{}\n",
+ serde_json::to_string_pretty(&Stage0 {
+ comment: "Generated by `./x.py run src/tools/bump-stage0`. \
+ Run that command again to update the bootstrap compiler.",
+ dist_server: DIST_SERVER.into(),
+ compiler: self.detect_compiler()?,
+ rustfmt: self.detect_rustfmt()?,
+ checksums_sha256: {
+ // Keys are sorted here instead of beforehand because values in this map
+ // are added while filling the other struct fields just above this block.
+ self.checksums.sort_keys();
+ self.checksums
+ }
+ })?
+ ),
+ )?;
+ Ok(())
+ }
+
+ // Currently Rust always bootstraps from the previous stable release, and in our train model
+ // this means that the master branch bootstraps from beta, beta bootstraps from current stable,
+ // and stable bootstraps from the previous stable release.
+ //
+ // On the master branch the compiler version is configured to `beta` whereas if you're looking
+ // at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous
+ // release's version number.
+ fn detect_compiler(&mut self) -> Result<Stage0Toolchain, Error> {
+ let channel = match self.channel {
+ Channel::Stable | Channel::Beta => {
+ // The 1.XX manifest points to the latest point release of that minor release.
+ format!("{}.{}", self.version[0], self.version[1] - 1)
+ }
+ Channel::Nightly => "beta".to_string(),
+ };
+
+ let manifest = fetch_manifest(&channel)?;
+ self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
+ Ok(Stage0Toolchain {
+ date: manifest.date,
+ version: if self.channel == Channel::Nightly {
+ "beta".to_string()
+ } else {
+ // The version field is like "1.42.0 (abcdef1234 1970-01-01)"
+ manifest.pkg["rust"]
+ .version
+ .split_once(' ')
+ .expect("invalid version field")
+ .0
+ .to_string()
+ },
+ })
+ }
+
+ /// We use a nightly rustfmt to format the source because it solves some bootstrapping issues
+ /// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided,
+ /// as we don't want to depend on rustfmt from nightly there.
+ fn detect_rustfmt(&mut self) -> Result<Option<Stage0Toolchain>, Error> {
+ if self.channel != Channel::Nightly {
+ return Ok(None);
+ }
+
+ let manifest = fetch_manifest("nightly")?;
+ self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
+ Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() }))
+ }
+
+ fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> {
+ let prefix = format!("{}/", DIST_SERVER);
+ for component in components {
+ let pkg = manifest
+ .pkg
+ .get(*component)
+ .ok_or_else(|| anyhow::anyhow!("missing component from manifest: {}", component))?;
+ for target in pkg.target.values() {
+ for pair in &[(&target.url, &target.hash), (&target.xz_url, &target.xz_hash)] {
+ if let (Some(url), Some(sha256)) = pair {
+ let url = url
+ .strip_prefix(&prefix)
+ .ok_or_else(|| {
+ anyhow::anyhow!("url doesn't start with dist server base: {}", url)
+ })?
+ .to_string();
+ self.checksums.insert(url, sha256.clone());
+ }
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+fn main() -> Result<(), Error> {
+ let tool = Tool::new()?;
+ tool.update_json()?;
+ Ok(())
+}
+
+fn fetch_manifest(channel: &str) -> Result<Manifest, Error> {
+ Ok(toml::from_slice(&http_get(&format!(
+ "{}/dist/channel-rust-{}.toml",
+ DIST_SERVER, channel
+ ))?)?)
+}
+
+fn http_get(url: &str) -> Result<Vec<u8>, Error> {
+ let mut data = Vec::new();
+ let mut handle = Easy::new();
+ handle.fail_on_error(true)?;
+ handle.url(url)?;
+ {
+ let mut transfer = handle.transfer();
+ transfer.write_function(|new_data| {
+ data.extend_from_slice(new_data);
+ Ok(new_data.len())
+ })?;
+ transfer.perform()?;
+ }
+ Ok(data)
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum Channel {
+ Stable,
+ Beta,
+ Nightly,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct Stage0 {
+ #[serde(rename = "__comment")]
+ comment: &'static str,
+ dist_server: String,
+ compiler: Stage0Toolchain,
+ rustfmt: Option<Stage0Toolchain>,
+ checksums_sha256: IndexMap<String, String>,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct Stage0Toolchain {
+ date: String,
+ version: String,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct Manifest {
+ date: String,
+ pkg: HashMap<String, ManifestPackage>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct ManifestPackage {
+ version: String,
+ target: HashMap<String, ManifestTargetPackage>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct ManifestTargetPackage {
+ available: bool,
+ url: Option<String>,
+ hash: Option<String>,
+ xz_url: Option<String>,
+ xz_hash: Option<String>,
+}
| ^
= help: ...or consider changing the match arm bodies
-error: this `match` has identical arm bodies
- --> $DIR/match_same_arms.rs:33:14
- |
-LL | 3 => 2, //~ ERROR 3rd matched arms have same body
- | ^
- |
-note: same as this
- --> $DIR/match_same_arms.rs:32:14
- |
-LL | 2 => 2, //~ ERROR 2nd matched arms have same body
- | ^
-help: consider refactoring into `2 | 3`
- --> $DIR/match_same_arms.rs:32:9
- |
-LL | 2 => 2, //~ ERROR 2nd matched arms have same body
- | ^
- = help: ...or consider changing the match arm bodies
-
error: this `match` has identical arm bodies
--> $DIR/match_same_arms.rs:50:55
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: ...or consider changing the match arm bodies
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
|
= note: `-D clippy::identity-op` implied by `-D warnings`
-error: the operation is ineffective. Consider reducing it to `1`
- --> $DIR/modulo_one.rs:13:22
- |
-LL | const ONE: u32 = 1 * 1;
- | ^^^^^
-
error: any number modulo 1 will be 0
--> $DIR/modulo_one.rs:17:5
|
LL | INT_MIN % NEG_ONE; // also caught by rustc
| ^^^^^^^^^^^^^^^^^
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
|
= note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
-error: this sequence of operators looks suspiciously like a bug
- --> $DIR/suspicious_operation_groupings.rs:14:9
- |
-LL | self.x == other.y && self.y == other.y && self.z == other.z
- | ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
-
error: this sequence of operators looks suspiciously like a bug
--> $DIR/suspicious_operation_groupings.rs:27:20
|
LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
| ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
-error: aborting due to 27 previous errors
+error: aborting due to 26 previous errors
-Subproject commit 09cadcbb62a3529801d0463d9878db3f0b5060c7
+Subproject commit 7a2f1cadcd5120c44eda3596053de767cd8173a2
-Subproject commit a82a0527057eab59c24a0452add35ccb39584e80
+Subproject commit bf88026f11f2cc7bb9fefdfe1dbcab642f110afa
-Subproject commit 996300f4a061e895a339a909fddce94f68ce7d19
+Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
suggestions: vec![],
span: span.unwrap_or_else(MultiSpan::new),
sort_span: DUMMY_SP,
+ is_lint: false,
}
}