RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
SCRIPT: python x.py dist
DIST_REQUIRE_ALL_TOOLS: 0
+ WINDOWS_SDK_20348_HACK: 1
os: windows-latest-xl
- name: dist-i686-mingw
env:
[[package]]
name = "aho-corasick"
-version = "0.7.13"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "cargo"
-version = "0.57.0"
+version = "0.58.0"
dependencies = [
"anyhow",
"atty",
"cargo_metadata 0.12.0",
"clippy_lints",
"clippy_utils",
- "compiletest_rs 0.6.0",
+ "compiletest_rs",
"derive-new",
"filetime",
"if_chain",
dependencies = [
"bytecount",
"clap",
- "itertools 0.9.0",
+ "itertools 0.10.1",
"opener",
"regex",
"shell-escape",
"cargo_metadata 0.12.0",
"clippy_utils",
"if_chain",
- "itertools 0.9.0",
+ "itertools 0.10.1",
"pulldown-cmark 0.8.0",
"quine-mc_cluskey",
"regex-syntax",
"winapi",
]
-[[package]]
-name = "compiletest_rs"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb"
-dependencies = [
- "diff",
- "filetime",
- "getopts",
- "lazy_static",
- "libc",
- "log",
- "miow",
- "regex",
- "rustfix 0.5.1",
- "serde",
- "serde_derive",
- "serde_json",
- "tempfile",
- "tester",
- "winapi",
-]
-
[[package]]
name = "compiletest_rs"
version = "0.7.0"
version = "0.1.0"
dependencies = [
"colored",
- "compiletest_rs 0.7.0",
+ "compiletest_rs",
"env_logger 0.8.1",
"getrandom 0.2.0",
"hex 0.4.2",
"rustc-std-workspace-core",
]
+[[package]]
+name = "odht"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2504d29fda40b3f2f9ef525392435ab660e407c188196cb664b116ebcca0142"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
[[package]]
name = "once_cell"
version = "1.7.2"
[[package]]
name = "regex"
-version = "1.4.6"
+version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"libc",
"measureme",
"rustc-demangle",
+ "rustc_arena",
"rustc_ast",
"rustc_attr",
"rustc_codegen_ssa",
name = "rustc_hir"
version = "0.0.0"
dependencies = [
+ "odht",
"rustc_ast",
"rustc_data_structures",
"rustc_feature",
version = "0.0.0"
dependencies = [
"libc",
+ "odht",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
[package]
name = "rustc-main"
version = "0.0.0"
-edition = '2018'
+edition = "2021"
[dependencies]
rustc_driver = { path = "../rustc_driver" }
[package]
name = "rustc_apfloat"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
bitflags = "1.2.1"
[package]
name = "rustc_arena"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
[package]
name = "rustc_ast"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
Never,
/// A tuple (`(A, B, C, D,...)`).
Tup(Vec<P<Ty>>),
- /// An anonymous struct type i.e. `struct { foo: Type }`
- AnonymousStruct(Vec<FieldDef>, bool),
- /// An anonymous union type i.e. `union { bar: Type }`
- AnonymousUnion(Vec<FieldDef>, bool),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
///
let is_first = i == 0;
if !is_first {
let mod_sep_span =
- Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
+ Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
}
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
}
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
- TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => {
- fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
- }
}
vis.visit_span(span);
visit_lazy_tts(tokens, vis);
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
- TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
- walk_list!(visitor, visit_field_def, fields)
- }
TyKind::Never | TyKind::CVarArgs => {}
}
}
[package]
name = "rustc_ast_lowering"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
}
}
StmtKind::Item(ref it) => {
- stmts.extend(self.lower_item_id(it).into_iter().enumerate().map(
+ stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
|(i, item_id)| {
let hir_id = match i {
0 => self.lower_node_id(s.id),
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
- None,
));
let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(
let mut generic_args = vec![];
for (idx, arg) in args.into_iter().enumerate() {
if legacy_args_idx.contains(&idx) {
- let parent_def_id = self.current_hir_id_owner.0;
+ let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
let if_expr = self.expr(span, if_kind, ThinVec::new());
let block = self.block_expr(self.arena.alloc(if_expr));
- hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi()))
+ let span = self.lower_span(span.with_hi(cond.span.hi()));
+ let opt_label = self.lower_label(opt_label);
+ hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
}
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
)
};
+ // #82462: to correctly diagnose borrow errors, the block that contains
+ // the iter expr needs to have a span that covers the loop body.
+ let desugared_full_span =
+ self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e.span, None);
+
let match_expr = self.arena.alloc(self.expr_match(
- desugared_span,
+ desugared_full_span,
into_iter_expr,
arena_vec![self; iter_arm],
hir::MatchSource::ForLoopDesugar,
// surrounding scope of the `match` since the `match` is not a terminating scope.
//
// Also, add the attributes to the outer returned expr node.
- self.expr_drop_temps_mut(desugared_span, match_expr, attrs.into())
+ self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
}
/// Desugar `ExprKind::Try` from: `<expr>?` into:
impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_item(&mut self, item: &'a Item) {
let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
- lctx.without_in_scope_lifetime_defs(|lctx| {
- let hir_item = lctx.lower_item(item);
- lctx.insert_item(hir_item)
- })
+ let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item));
+ hir::OwnerNode::Item(node)
});
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
- ItemKind::Mod(..) => {
- let def_id = this.lctx.lower_node_id(item.id).expect_owner();
- let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
- visit::walk_item(this, item);
- this.lctx.current_module = old_current_module;
- }
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
- AssocCtxt::Trait => {
- let hir_item = lctx.lower_trait_item(item);
- lctx.insert_trait_item(hir_item);
- }
- AssocCtxt::Impl => {
- let hir_item = lctx.lower_impl_item(item);
- lctx.insert_impl_item(hir_item);
- }
+ AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
+ AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
});
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
- self.lctx.allocate_hir_id_counter(item.id);
self.lctx.with_hir_id_owner(item.id, |lctx| {
- let hir_item = lctx.lower_foreign_item(item);
- lctx.insert_foreign_item(hir_item);
+ hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
});
visit::walk_foreign_item(self, item);
// only used when lowering a child item of a trait or impl.
fn with_parent_item_lifetime_defs<T>(
&mut self,
- parent_hir_id: hir::ItemId,
+ parent_hir_id: LocalDefId,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let old_len = self.in_scope_lifetimes.len();
- let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind {
+ let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind {
hir::ItemKind::Impl(hir::Impl { ref generics, .. })
| hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
_ => &[],
pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
hir::Mod {
inner: self.lower_span(inner),
- item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))),
+ item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
}
}
- pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
- let node_ids = match i.kind {
- ItemKind::Use(ref use_tree) => {
- let mut vec = smallvec![i.id];
- self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
- vec
- }
- ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
- smallvec![i.id]
- }
- _ => smallvec![i.id],
- };
-
+ pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
+ let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }];
+ if let ItemKind::Use(ref use_tree) = &i.kind {
+ self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
+ }
node_ids
- .into_iter()
- .map(|node_id| hir::ItemId {
- def_id: self.allocate_hir_id_counter(node_id).expect_owner(),
- })
- .collect()
}
fn lower_item_id_use_tree(
&mut self,
tree: &UseTree,
base_id: NodeId,
- vec: &mut SmallVec<[NodeId; 1]>,
+ vec: &mut SmallVec<[hir::ItemId; 1]>,
) {
match tree.kind {
UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec {
- vec.push(id);
+ vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
self.lower_item_id_use_tree(nested, id, vec);
}
}
for (_, &id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{
- vec.push(id);
+ vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
}
}
}
}
- pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
+ fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let mut ident = i.ident;
- let mut vis = self.lower_visibility(&i.vis, None);
+ let mut vis = self.lower_visibility(&i.vis);
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
- hir::Item {
+ let item = hir::Item {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
fn lower_item_kind(
}
}
- let mut resolutions = self.expect_full_res_from_use(id);
+ let mut resolutions = self.expect_full_res_from_use(id).fuse();
// We want to return *something* from this function, so hold onto the first item
// for later.
let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
// won't be dealing with macros in the rest of the compiler.
// Essentially a single `use` which imports two names is desugared into
// two imports.
- for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) {
+ for new_node_id in [id1, id2] {
+ let new_id = self.resolver.local_def_id(new_node_id);
+ let res = if let Some(res) = resolutions.next() {
+ res
+ } else {
+ // Associate an HirId to both ids even if there is no resolution.
+ self.node_id_to_hir_id.ensure_contains_elem(new_node_id, || None);
+ debug_assert!(self.node_id_to_hir_id[new_node_id].is_none());
+ self.node_id_to_hir_id[new_node_id] = Some(hir::HirId::make_owner(new_id));
+ continue;
+ };
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
let span = path.span;
self.with_hir_id_owner(new_node_id, |this| {
- let new_id = this.lower_node_id(new_node_id);
let res = this.lower_res(res);
- let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None);
+ let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
let vis = this.rebuild_vis(&vis);
if let Some(attrs) = attrs {
- this.attrs.insert(new_id, attrs);
+ this.attrs.insert(hir::HirId::make_owner(new_id), attrs);
}
- this.insert_item(hir::Item {
- def_id: new_id.expect_owner(),
+ let item = hir::Item {
+ def_id: new_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(span),
- });
+ };
+ hir::OwnerNode::Item(this.arena.alloc(item))
});
}
- let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None);
+ let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
// Add all the nested `PathListItem`s to the HIR.
for &(ref use_tree, id) in trees {
- let new_hir_id = self.lower_node_id(id);
+ let new_hir_id = self.resolver.local_def_id(id);
let mut prefix = prefix.clone();
let kind =
this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
if let Some(attrs) = attrs {
- this.attrs.insert(new_hir_id, attrs);
+ this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs);
}
- this.insert_item(hir::Item {
- def_id: new_hir_id.expect_owner(),
+ let item = hir::Item {
+ def_id: new_hir_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(use_tree.span),
- });
+ };
+ hir::OwnerNode::Item(this.arena.alloc(item))
});
}
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
let res = self.lower_res(res);
- let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None);
+ let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::ListStem)
}
}
respan(self.lower_span(vis.span), vis_kind)
}
- fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
+ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
- hir::ForeignItem {
+ let item = hir::ForeignItem {
def_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
},
- vis: self.lower_visibility(&i.vis, None),
+ vis: self.lower_visibility(&i.vis),
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
- fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
+ fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
- id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() },
+ id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
- vis: self.lower_visibility(&i.vis, Some(i.id)),
}
}
}
}
- pub(super) fn lower_field_def(
- &mut self,
- (index, f): (usize, &FieldDef),
- ) -> hir::FieldDef<'hir> {
+ fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
let t = self.lower_path_ty(
&f.ty,
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), self.lower_span(f.span)),
},
- vis: self.lower_visibility(&f.vis, None),
+ vis: self.lower_visibility(&f.vis),
ty,
}
}
- fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
+ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let trait_item_def_id = hir_id.expect_owner();
};
self.lower_attrs(hir_id, &i.attrs);
- hir::TraitItem {
+ let item = hir::TraitItem {
def_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
- let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() };
+ let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) };
let defaultness = hir::Defaultness::Default { has_value: has_default };
hir::TraitItemRef {
id,
self.expr(span, hir::ExprKind::Err, AttrVec::new())
}
- fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
+ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
let impl_item_def_id = self.resolver.local_def_id(i.id);
let (generics, kind) = match &i.kind {
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
- hir::ImplItem {
+ let item = hir::ImplItem {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
- vis: self.lower_visibility(&i.vis, None),
+ vis: self.lower_visibility(&i.vis),
defaultness,
kind,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
- fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
+ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
hir::ImplItemRef {
- id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() },
+ id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
- vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness,
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
/// lowered. This can happen during `lower_impl_item_ref()` where we need to
/// lower a `Visibility` value although we haven't lowered the owning
/// `ImplItem` in question yet.
- fn lower_visibility(
- &mut self,
- v: &Visibility,
- explicit_owner: Option<NodeId>,
- ) -> hir::Visibility<'hir> {
+ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> {
let node = match v.kind {
VisibilityKind::Public => hir::VisibilityKind::Public,
VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
VisibilityKind::Restricted { ref path, id } => {
debug!("lower_visibility: restricted path id = {:?}", id);
- let lowered_id = if let Some(owner) = explicit_owner {
- self.lower_node_id_with_owner(id, owner)
- } else {
- self.lower_node_id(id)
- };
- let res = self.expect_full_res(id);
- let res = self.lower_res(res);
+ let lowered_id = self.lower_node_id(id);
hir::VisibilityKind::Restricted {
- path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner),
+ path: self.lower_path(id, path, ParamMode::Explicit),
hir_id: lowered_id,
}
}
use rustc_ast::node_id::NodeMap;
use rustc_ast::token::{self, Token};
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit;
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust;
use rustc_data_structures::captures::Captures;
mod pat;
mod path;
-const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
-
rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
struct LoweringContext<'a, 'hir: 'a> {
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
- modules: BTreeMap<LocalDefId, hir::ModuleItems>,
-
generator_kind: Option<hir::GeneratorKind>,
attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
/// vector.
in_scope_lifetimes: Vec<ParamName>,
- current_module: LocalDefId,
-
- current_hir_id_owner: (LocalDefId, u32),
- item_local_id_counters: NodeMap<u32>,
+ current_hir_id_owner: LocalDefId,
+ item_local_id_counter: hir::ItemLocalId,
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
allow_try_trait: Option<Lrc<[Symbol]>>,
pub trait ResolverAstLowering {
fn def_key(&mut self, id: DefId) -> DefKey;
+ fn def_span(&self, id: LocalDefId) -> Span;
+
fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
true
}
+ #[inline]
+ fn def_span(&self, id: LocalDefId) -> Span {
+ self.resolver.def_span(id)
+ }
+
#[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
self.resolver.def_path_hash(def_id)
arena,
owners: IndexVec::default(),
bodies: BTreeMap::new(),
- modules: BTreeMap::new(),
attrs: BTreeMap::default(),
catch_scope: None,
loop_scope: None,
is_in_trait_impl: false,
is_in_dyn_type: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
- current_module: CRATE_DEF_ID,
- current_hir_id_owner: (CRATE_DEF_ID, 0),
- item_local_id_counters: Default::default(),
+ current_hir_id_owner: CRATE_DEF_ID,
+ item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_hir_id: IndexVec::new(),
generator_kind: None,
task_context: None,
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
- /// Full-crate AST visitor that inserts into a fresh
- /// `LoweringContext` any information that may be
- /// needed from arbitrary locations in the crate,
- /// e.g., the number of lifetime generic parameters
- /// declared for every type and trait definition.
- struct MiscCollector<'tcx, 'lowering, 'hir> {
- lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
- }
-
- impl MiscCollector<'_, '_, '_> {
- fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) {
- match tree.kind {
- UseTreeKind::Simple(_, id1, id2) => {
- for id in [id1, id2] {
- self.lctx.allocate_hir_id_counter(id);
- }
- }
- UseTreeKind::Glob => (),
- UseTreeKind::Nested(ref trees) => {
- for &(ref use_tree, id) in trees {
- self.lctx.allocate_hir_id_counter(id);
- self.allocate_use_tree_hir_id_counters(use_tree);
- }
- }
- }
- }
- }
-
- impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
- fn visit_item(&mut self, item: &'tcx Item) {
- self.lctx.allocate_hir_id_counter(item.id);
-
- if let ItemKind::Use(ref use_tree) = item.kind {
- self.allocate_use_tree_hir_id_counters(use_tree);
- }
-
- visit::walk_item(self, item);
- }
+ debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
- fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
- self.lctx.allocate_hir_id_counter(item.id);
- visit::walk_assoc_item(self, item, ctxt);
- }
-
- fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
- self.lctx.allocate_hir_id_counter(item.id);
- visit::walk_foreign_item(self, item);
- }
- }
-
- self.lower_node_id(CRATE_NODE_ID);
- debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
-
- visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
- let module = self.arena.alloc(self.lower_mod(&c.items, c.span));
- self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
- self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
- self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
+ self.with_hir_id_owner(CRATE_NODE_ID, |lctx| {
+ let module = lctx.lower_mod(&c.items, c.span);
+ lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
+ hir::OwnerNode::Crate(lctx.arena.alloc(module))
+ });
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (k, v) in self.resolver.take_trait_map().into_iter() {
}
}
- let krate = hir::Crate {
- owners: self.owners,
- bodies: self.bodies,
- modules: self.modules,
- trait_map,
- attrs: self.attrs,
- };
+ let krate =
+ hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
self.arena.alloc(krate)
}
- fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
- let id = item.item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
- self.modules.entry(self.current_module).or_default().items.insert(id);
- id
- }
-
- fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId {
- let id = item.foreign_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
- self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
- id
- }
-
- fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
- let id = item.impl_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
- self.modules.entry(self.current_module).or_default().impl_items.insert(id);
- id
- }
-
- fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId {
- let id = item.trait_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
- self.modules.entry(self.current_module).or_default().trait_items.insert(id);
- id
- }
-
- fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
- // Set up the counter if needed.
- self.item_local_id_counters.entry(owner).or_insert(0);
- // Always allocate the first `HirId` for the owner itself.
- let lowered = self.lower_node_id_with_owner(owner, owner);
- debug_assert_eq!(lowered.local_id.as_u32(), 0);
- lowered
- }
-
fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
LoweringHasher {
source_map: CachingSourceMapView::new(self.sess.source_map()),
}
}
- fn lower_node_id_generic(
+ fn with_hir_id_owner(
&mut self,
- ast_node_id: NodeId,
- alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
- ) -> hir::HirId {
- assert_ne!(ast_node_id, DUMMY_NODE_ID);
-
- let min_size = ast_node_id.as_usize() + 1;
+ owner: NodeId,
+ f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
+ ) -> LocalDefId {
+ let def_id = self.resolver.local_def_id(owner);
- if min_size > self.node_id_to_hir_id.len() {
- self.node_id_to_hir_id.resize(min_size, None);
+ // Always allocate the first `HirId` for the owner itself.
+ self.node_id_to_hir_id.ensure_contains_elem(owner, || None);
+ if let Some(_lowered) = self.node_id_to_hir_id[owner] {
+ panic!("with_hir_id_owner must not be called multiple times on owner {:?}", def_id);
}
+ self.node_id_to_hir_id[owner] = Some(hir::HirId::make_owner(def_id));
- if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
- existing_hir_id
- } else {
- // Generate a new `HirId`.
- let hir_id = alloc_hir_id(self);
- self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
+ let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
+ let current_local_counter =
+ std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
- hir_id
- }
- }
+ let item = f(self);
- fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
- let counter = self
- .item_local_id_counters
- .insert(owner, HIR_ID_COUNTER_LOCKED)
- .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
- let def_id = self.resolver.local_def_id(owner);
- let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter));
- let ret = f(self);
- let (new_def_id, new_counter) =
- std::mem::replace(&mut self.current_hir_id_owner, old_owner);
+ self.current_hir_id_owner = current_owner;
+ self.item_local_id_counter = current_local_counter;
- debug_assert!(def_id == new_def_id);
- debug_assert!(new_counter >= counter);
+ self.owners.ensure_contains_elem(def_id, || None);
+ self.owners[def_id] = Some(item);
- let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
- debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
- ret
+ def_id
}
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though.
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
- self.lower_node_id_generic(ast_node_id, |this| {
- let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner;
- let local_id = *local_id_counter;
- *local_id_counter += 1;
- hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
- })
- }
-
- fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId {
- self.lower_node_id_generic(ast_node_id, |this| {
- let local_id_counter = this
- .item_local_id_counters
- .get_mut(&owner)
- .expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`");
- let local_id = *local_id_counter;
-
- // We want to be sure not to modify the counter in the map while it
- // is also on the stack. Otherwise we'll get lost updates when writing
- // back from the stack to the map.
- debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
-
- *local_id_counter += 1;
- let owner = this.resolver.opt_local_def_id(owner).expect(
- "you forgot to call `create_def` or are lowering node-IDs \
- that do not belong to the current owner",
- );
+ assert_ne!(ast_node_id, DUMMY_NODE_ID);
- hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
- })
+ self.node_id_to_hir_id.ensure_contains_elem(ast_node_id, || None);
+ if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
+ existing_hir_id
+ } else {
+ // Generate a new `HirId`.
+ let owner = self.current_hir_id_owner;
+ let local_id = self.item_local_id_counter;
+ self.item_local_id_counter.increment_by(1);
+ let hir_id = hir::HirId { owner, local_id };
+ self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
+ hir_id
+ }
}
fn next_id(&mut self) -> hir::HirId {
fn lower_res(&mut self, res: Res<NodeId>) -> Res {
res.map_id(|id| {
- self.lower_node_id_generic(id, |_| {
+ self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| {
panic!("expected `NodeId` to be lowered already for res {:#?}", res);
})
})
}
/// Intercept all spans entering HIR.
- /// For now we are not doing anything with the intercepted spans.
+ /// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
- span
+ if self.sess.opts.debugging_opts.incremental_relative_spans {
+ span.with_parent(Some(self.current_hir_id_owner))
+ } else {
+ // Do not make spans relative when not using incremental compilation.
+ span
+ }
}
fn lower_ident(&self, ident: Ident) -> Ident {
node_id,
DefPathData::LifetimeNs(str_name),
ExpnId::root(),
- span,
+ span.with_parent(None),
);
hir::GenericParam {
// wouldn't have been added yet.
let generics = this.lower_generics_mut(
generics,
- ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0),
+ ImplTraitContext::Universal(&mut params, this.current_hir_id_owner),
);
let res = f(this, &mut params);
(params, (generics, res))
}
AssocTyConstraintKind::Bound { ref bounds } => {
let mut capturable_lifetimes;
- let mut parent_def_id = self.current_hir_id_owner.0;
+ let mut parent_def_id = self.current_hir_id_owner;
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position:
// Construct an AnonConst where the expr is the "ty"'s path.
- let parent_def_id = self.current_hir_id_owner.0;
+ let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
let kind = match t.kind {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err => hir::TyKind::Err,
- // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
- TyKind::AnonymousStruct(ref _fields, _recovered) => {
- self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit();
- hir::TyKind::Err
- }
- TyKind::AnonymousUnion(ref _fields, _recovered) => {
- self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit();
- hir::TyKind::Err
- }
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
- self.allocate_hir_id_counter(opaque_ty_node_id);
-
- let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
+ let mut collected_lifetimes = Vec::new();
+ self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
let hir_bounds = lower_bounds(lctx);
- let collected_lifetimes = lifetimes_from_impl_trait_bounds(
+ collected_lifetimes = lifetimes_from_impl_trait_bounds(
opaque_ty_node_id,
&hir_bounds,
capturable_lifetimes,
def_node_id,
DefPathData::LifetimeNs(name.ident().name),
ExpnId::root(),
- span,
+ span.with_parent(None),
);
let (name, kind) = match name {
};
trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
- lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
-
- collected_lifetimes
+ lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
let lifetimes =
opaque_ty_item: hir::OpaqueTy<'hir>,
span: Span,
opaque_ty_span: Span,
- ) {
+ ) -> hir::OwnerNode<'hir> {
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
span: self.lower_span(opaque_ty_span),
};
-
- // Insert the item into the global item list. This usually happens
- // automatically for all AST items. But this opaque type item
- // does not actually exist in the AST.
- self.insert_item(opaque_ty_item);
+ hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
if let Some((_, ibty)) = &mut in_band_ty_params {
this.lower_ty_direct(
¶m.ty,
- ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0),
+ ImplTraitContext::Universal(ibty, this.current_hir_id_owner),
)
} else {
this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed())
let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
- self.allocate_hir_id_counter(opaque_ty_node_id);
-
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
// return type). This is done by introducing lifetime parameters for:
// grow.
let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
- let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| {
+ let mut lifetime_params = Vec::new();
+ self.with_hir_id_owner(opaque_ty_node_id, |this| {
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
//
// Note: this must be done after lowering the output type,
// as the output type may introduce new in-band lifetimes.
- let lifetime_params: Vec<(Span, ParamName)> = this
+ lifetime_params = this
.in_scope_lifetimes
.iter()
.cloned()
};
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
- this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
-
- lifetime_params
+ this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
// As documented above on the variable
num_lifetimes,
parenthesized_generic_args,
itctx.reborrow(),
- None,
)
},
)),
0,
ParenthesizedGenericArgs::Err,
itctx.reborrow(),
- None,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
res: Res,
p: &Path,
param_mode: ParamMode,
- explicit_owner: Option<NodeId>,
) -> &'hir hir::Path<'hir> {
self.arena.alloc(hir::Path {
res,
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
- explicit_owner,
)
})),
span: self.lower_span(p.span),
) -> &'hir hir::Path<'hir> {
let res = self.expect_full_res(id);
let res = self.lower_res(res);
- self.lower_path_extra(res, p, param_mode, None)
+ self.lower_path_extra(res, p, param_mode)
}
crate fn lower_path_segment(
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext<'_, 'hir>,
- explicit_owner: Option<NodeId>,
) -> hir::PathSegment<'hir> {
debug!(
"path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
}
let res = self.expect_full_res(segment.id);
- let id = if let Some(owner) = explicit_owner {
- self.lower_node_id_with_owner(segment.id, owner)
- } else {
- self.lower_node_id(segment.id)
- };
+ let id = self.lower_node_id(segment.id);
debug!(
"lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
segment.ident, segment.id, id,
[package]
name = "rustc_ast_passes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
itertools = "0.9"
}
}
}
- TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields)
- });
- }
_ => visit::walk_ty(self, t),
}
}
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
if let Some(ident) = field.ident {
if ident.name == kw::Underscore {
- self.check_anonymous_field(field);
self.visit_vis(&field.vis);
self.visit_ident(ident);
self.visit_ty_common(&field.ty);
err.emit();
}
- fn check_anonymous_field(&self, field: &FieldDef) {
- let FieldDef { ty, .. } = field;
- match &ty.kind {
- TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
- // We already checked for `kw::Underscore` before calling this function,
- // so skip the check
- }
- TyKind::Path(..) => {
- // If the anonymous field contains a Path as type, we can't determine
- // if the path is a valid struct or union, so skip the check
- }
- _ => {
- let msg = "unnamed fields can only have struct or union types";
- let label = "not a struct or union";
- self.err_handler()
- .struct_span_err(field.span, msg)
- .span_label(ty.span, label)
- .emit();
- }
- }
- }
-
- fn deny_anonymous_struct(&self, ty: &Ty) {
- match &ty.kind {
- TyKind::AnonymousStruct(..) => {
- self.err_handler()
- .struct_span_err(
- ty.span,
- "anonymous structs are not allowed outside of unnamed struct or union fields",
- )
- .span_label(ty.span, "anonymous struct declared here")
- .emit();
- }
- TyKind::AnonymousUnion(..) => {
- self.err_handler()
- .struct_span_err(
- ty.span,
- "anonymous unions are not allowed outside of unnamed struct or union fields",
- )
- .span_label(ty.span, "anonymous union declared here")
- .emit();
- }
- _ => {}
- }
- }
-
- fn deny_anonymous_field(&self, field: &FieldDef) {
- if let Some(ident) = field.ident {
- if ident.name == kw::Underscore {
- self.err_handler()
- .struct_span_err(
- field.span,
- "anonymous fields are not allowed outside of structs or unions",
- )
- .span_label(ident.span, "anonymous field declared here")
- .emit()
- }
- }
- }
-
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
for Param { pat, .. } in &decl.inputs {
match pat.kind {
}
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
+ self.check_decl_num_args(fn_decl);
self.check_decl_cvaradic_pos(fn_decl);
self.check_decl_attrs(fn_decl);
self.check_decl_self_param(fn_decl, self_semantic);
}
+ /// Emits fatal error if function declaration has more than `u16::MAX` arguments
+ /// Error is fatal to prevent errors during typechecking
+ fn check_decl_num_args(&self, fn_decl: &FnDecl) {
+ let max_num_args: usize = u16::MAX.into();
+ if fn_decl.inputs.len() > max_num_args {
+ let Param { span, .. } = fn_decl.inputs[0];
+ self.err_handler().span_fatal(
+ span,
+ &format!("function can not have more than {} arguments", max_num_args),
+ );
+ }
+ }
+
fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
match &*fn_decl.inputs {
[Param { ty, span, .. }] => {
fn visit_ty(&mut self, ty: &'a Ty) {
self.visit_ty_common(ty);
- self.deny_anonymous_struct(ty);
self.walk_ty(ty)
}
}
fn visit_field_def(&mut self, s: &'a FieldDef) {
- self.deny_anonymous_field(s);
visit::walk_field_def(self, s)
}
walk_list!(self, visit_ty, ty);
}
AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
- if self.in_const_trait_impl || ctxt == AssocCtxt::Trait =>
+ if self.in_const_trait_impl
+ || ctxt == AssocCtxt::Trait
+ || matches!(sig.header.constness, Const::Yes(_)) =>
{
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
// involved, so we only emit errors where there are no other parsing errors.
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
}
- gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
// All uses of `gate_all!` below this point were added in #65742,
// and subsequently disabled (with the non-early gating readded).
}
fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
+ // checks if `#![feature]` has been used to enable any lang feature
+ // does not check the same for lib features unless there's at least one
+ // declared lang feature
use rustc_errors::Applicability;
if !sess.opts.unstable_features.is_nightly_build() {
let lang_features = &sess.features_untracked().declared_lang_features;
+ if lang_features.len() == 0 {
+ return;
+ }
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
let mut err = struct_span_err!(
sess.parse_sess.span_diagnostic,
[package]
name = "rustc_ast_pretty"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
}
self.pclose();
}
- ast::TyKind::AnonymousStruct(ref fields, ..) => {
- self.head("struct");
- self.print_record_struct_body(&fields, ty.span);
- }
- ast::TyKind::AnonymousUnion(ref fields, ..) => {
- self.head("union");
- self.print_record_struct_body(&fields, ty.span);
- }
ast::TyKind::Paren(ref typ) => {
self.popen();
self.print_type(typ);
}
}
- crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
+ crate fn print_record_struct_body(
+ &mut self,
+ fields: &Vec<ast::FieldDef>,
+ span: rustc_span::Span,
+ ) {
+ self.nbsp();
self.bopen();
self.hardbreak_if_not_bol();
}
ast::VariantData::Struct(ref fields, ..) => {
self.print_where_clause(&generics.where_clause);
- self.nbsp();
self.print_record_struct_body(fields, span);
}
}
[package]
name = "rustc_attr"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_borrowck"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
};
/// This function computes Polonius facts for the given body. It makes a copy of
-/// the body because it needs to regenerate the region identifiers.
+/// the body because it needs to regenerate the region identifiers. This function
+/// should never be invoked during a typical compilation session due to performance
+/// issues with Polonius.
///
/// Note:
/// * This function will panic if the required body was already stolen. This
/// because they are evaluated during typechecking. The panic can be avoided
/// by overriding the `mir_borrowck` query. You can find a complete example
/// that shows how to do this at `src/test/run-make/obtain-borrowck/`.
-/// * This function will also panic if computation of Polonius facts
-/// (`-Zpolonius` flag) is not enabled.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
pub fn get_body_with_borrowck_facts<'tcx>(
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
- self_arg.span,
+ // Check whether the source is accessible
+ if self
+ .infcx
+ .tcx
+ .sess
+ .source_map()
+ .span_to_snippet(self_arg.span)
+ .is_ok()
+ {
+ self_arg.span
+ } else {
+ fn_call_span
+ },
"calling this operator moves the left-hand side",
);
}
deref_target_ty
));
- err.span_note(deref_target, "deref defined here");
+ // Check first whether the source is accessible (issue #87060)
+ if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
+ err.span_note(deref_target, "deref defined here");
+ }
}
if let Some((_, mut old_err)) =
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
{
let closure_kind_ty = closure_substs.as_closure().kind_ty();
- let closure_kind = closure_kind_ty.to_opt_closure_kind();
- let capture_description = match closure_kind {
- Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
- Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
+ let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
+ Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
Some(ty::ClosureKind::FnOnce) => {
bug!("closure kind does not match first argument type")
}
None => bug!("closure kind not inferred by borrowck"),
};
+ let capture_description =
+ format!("captured variable in an `{}` closure", closure_kind);
let upvar = &self.upvars[upvar_field.unwrap().index()];
let upvar_hir_id = upvar.place.get_root_variable();
let mut diag = self.cannot_move_out_of(span, &place_description);
diag.span_label(upvar_span, "captured outer variable");
+ diag.span_label(
+ self.body.span,
+ format!("captured by this `{}` closure", closure_kind),
+ );
diag
}
ConstraintCategory::CopyBound => "copying this value ",
ConstraintCategory::OpaqueType => "opaque type ",
ConstraintCategory::ClosureUpvar(_) => "closure capture ",
+ ConstraintCategory::Usage => "this usage ",
ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => "",
debug!("do_mir_borrowck(def = {:?})", def);
- assert!(
- !return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius,
- "borrowck facts can be requested only when Polonius is enabled"
- );
-
let tcx = infcx.tcx;
let param_env = tcx.param_env(def.did);
let id = tcx.hir().local_def_id_to_hir_id(def.did);
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
+ let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius;
+
// Compute non-lexical lifetimes.
let nll::NllOutput {
regioncx,
&mdpe.move_data,
&borrow_set,
&upvars,
+ use_polonius,
);
// Dump MIR results into a file, if that is enabled. This let us
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
upvars: &[Upvar<'tcx>],
+ use_polonius: bool,
) -> NllOutput<'tcx> {
- let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
+ let mut all_facts =
+ (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
all_facts.write_to_dir(dir_path, location_table).unwrap();
}
- if infcx.tcx.sess.opts.debugging_opts.polonius {
+ if use_polonius {
let algorithm =
env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
let algorithm = Algorithm::from_str(&algorithm).unwrap();
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
/// Map universe indexes to information on why we created it.
- universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+ universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
>,
- universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+ universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
category: constraint.category,
from_closure: false,
span,
- variance_info: constraint.variance_info.clone(),
+ variance_info: constraint.variance_info,
};
}
Locations::Single(loc) => loc,
category,
from_closure: true,
span: span,
- variance_info: constraint.variance_info.clone(),
+ variance_info: constraint.variance_info,
})
.unwrap_or(BlameConstraint {
category: constraint.category,
from_closure: false,
span: body.source_info(loc).span,
- variance_info: constraint.variance_info.clone(),
+ variance_info: constraint.variance_info,
})
}
category: constraint.category,
from_closure: false,
span: constraint.locations.span(body),
- variance_info: constraint.variance_info.clone(),
+ variance_info: constraint.variance_info,
}
}
})
}
crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
- self.universe_causes[universe].clone()
+ self.universe_causes[&universe].clone()
}
}
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
/// which has no `external_name` in which case we use `'empty` as the
/// region to pass to `infer_opaque_definition_from_instantiation`.
- #[instrument(skip(self, infcx))]
+ #[instrument(level = "debug", skip(self, infcx))]
pub(crate) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
None => UniverseInfo::other(),
};
for u in old_universe..universe {
- let info_universe =
- self.borrowck_context.constraints.universe_causes.push(universe_info.clone());
- assert_eq!(u.as_u32() + 1, info_universe.as_u32());
+ self.borrowck_context
+ .constraints
+ .universe_causes
+ .insert(u + 1, universe_info.clone());
}
}
let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
- for _ in 0..canonical.max_universe.as_u32() {
+ for u in 0..canonical.max_universe.as_u32() {
let info = UniverseInfo::other();
- self.borrowck_context.constraints.universe_causes.push(info);
+ self.borrowck_context
+ .constraints
+ .universe_causes
+ .insert(ty::UniverseIndex::from_u32(u), info);
}
instantiated
// We add implied bounds from both the unnormalized and normalized ty
// See issue #87748
let constraints_implied_1 = self.add_implied_bounds(ty);
- let TypeOpOutput { output: ty, constraints: constraints1, .. } = self
+ let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx)
// }
// ```
// Both &Self::Bar and &() are WF
- let constraints_implied_2 = self.add_implied_bounds(ty);
- normalized_inputs_and_output.push(ty);
+ let constraints_implied_2 =
+ if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+ normalized_inputs_and_output.push(norm_ty);
constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
})
.collect();
b
}
};
+ // Note: if we have to introduce new placeholders during normalization above, then we won't have
+ // added those universes to the universe info, which we would want in `relate_tys`.
if let Err(terr) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
{
upvars: &[Upvar<'tcx>],
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+ let mut universe_causes = FxHashMap::default();
+ universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
- universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1),
+ universe_causes,
};
let CreateResult {
&mut constraints,
);
- for _ in ty::UniverseIndex::ROOT..infcx.universe() {
+ for u in ty::UniverseIndex::ROOT..infcx.universe() {
let info = UniverseInfo::other();
- constraints.universe_causes.push(info);
+ constraints.universe_causes.insert(u, info);
}
let mut borrowck_context = BorrowCheckContext {
crate closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
- crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+ crate universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
crate type_tests: Vec<TypeTest<'tcx>>,
}
ConstraintCategory::Return(ReturnConstraint::Normal)
}
}
+ Some(l)
+ if matches!(
+ body.local_decls[l].local_info,
+ Some(box LocalInfo::AggregateTemp)
+ ) =>
+ {
+ ConstraintCategory::Usage
+ }
Some(l) if !body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring
}
_ => ConstraintCategory::Assignment,
};
+ debug!(
+ "assignment category: {:?} {:?}",
+ category,
+ place.as_local().map(|l| &body.local_decls[l])
+ );
let place_ty = place.ty(body, tcx).ty;
let place_ty = self.normalize(place_ty, location);
&obligation,
&traits::SelectionError::Unimplemented,
false,
- false,
);
}
}
}
fn create_next_universe(&mut self) -> ty::UniverseIndex {
- let info_universe =
- self.borrowck_context.constraints.universe_causes.push(self.universe_info.clone());
let universe = self.infcx.create_next_universe();
- assert_eq!(info_universe, universe);
+ self.borrowck_context
+ .constraints
+ .universe_causes
+ .insert(universe, self.universe_info.clone());
universe
}
[package]
name = "rustc_builtin_macros"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
let mut explicit_reg = false;
let op = if !is_global_asm && p.eat_keyword(kw::In) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
+ if p.eat_keyword(kw::Underscore) {
+ let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+ return Err(err);
+ }
let expr = p.parse_expr()?;
ast::InlineAsmOperand::In { reg, expr }
} else if !is_global_asm && p.eat_keyword(sym::out) {
ast::InlineAsmOperand::Out { reg, expr, late: true }
} else if !is_global_asm && p.eat_keyword(sym::inout) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
+ if p.eat_keyword(kw::Underscore) {
+ let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+ return Err(err);
+ }
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
let out_expr =
}
} else if !is_global_asm && p.eat_keyword(sym::inlateout) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
+ if p.eat_keyword(kw::Underscore) {
+ let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+ return Err(err);
+ }
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
let out_expr =
match expr_to_spanned_string(ecx, template_expr, msg) {
Ok(template_part) => template_part,
Err(err) => {
- if let Some(mut err) = err {
+ if let Some((mut err, _)) = err {
err.emit();
}
return None;
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = cx.with_def_site_ctxt(span);
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
+ let fmt = substr.nonself_args[0].clone();
+
+ // Special fast path for unit variants. In the common case of an enum that is entirely unit
+ // variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in
+ // favor of a lookup table.
+ if let ast::VariantData::Unit(..) = vdata {
+ let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
+ let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
+ let stmts = vec![cx.stmt_expr(expr)];
+ let block = cx.block(span, stmts);
+ return cx.expr_block(block);
+ }
+
let builder = Ident::new(sym::debug_trait_builder, span);
let builder_expr = cx.expr_ident(span, builder);
- let fmt = substr.nonself_args[0].clone();
-
let mut stmts = Vec::with_capacity(fields.len() + 2);
let fn_path_finish;
match vdata {
- ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+ ast::VariantData::Unit(..) => {
+ cx.span_bug(span, "unit variants should have been handled above");
+ }
+ ast::VariantData::Tuple(..) => {
// tuple struct/"normal" variant
let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
}
Ok(fmt) => fmt,
Err(err) => {
- if let Some(mut err) = err {
+ if let Some((mut err, suggested)) = err {
let sugg_fmt = match args.len() {
0 => "{}".to_string(),
_ => format!("{}{{}}", "{} ".repeat(args.len())),
};
- err.span_suggestion(
- fmt_sp.shrink_to_lo(),
- "you might be missing a string literal to format with",
- format!("\"{}\", ", sugg_fmt),
- Applicability::MaybeIncorrect,
- );
+ if !suggested {
+ err.span_suggestion(
+ fmt_sp.shrink_to_lo(),
+ "you might be missing a string literal to format with",
+ format!("\"{}\", ", sugg_fmt),
+ Applicability::MaybeIncorrect,
+ );
+ }
err.emit();
}
return DummyResult::raw_expr(sp, true);
[package]
name = "rustc_codegen_cranelift"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
crate-type = ["dylib"]
mod returning;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
inst: Instance<'tcx>,
) -> Signature {
assert!(!inst.substs.needs_infer());
- clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]))
+ clif_sig_from_fn_abi(
+ tcx,
+ triple,
+ &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
+ )
}
/// Instance must be monomorphized
};
let extra_args = &args[fn_sig.inputs().len()..];
- let extra_args = extra_args
- .iter()
- .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))
- .collect::<Vec<_>>();
+ let extra_args = fx
+ .tcx
+ .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
let fn_abi = if let Some(instance) = instance {
- FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args)
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} else {
- FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args)
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
};
let is_cold = instance
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
substs: drop_instance.substs,
};
- let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]);
+ let fn_abi =
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
let sig = fx.bcx.import_signature(sig);
_ => {
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
- let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]);
+ let fn_abi =
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty());
let arg_value = drop_place.place_ref(
fx,
fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> {
match self.mode {
PassMode::Ignore => smallvec![],
- PassMode::Direct(attrs) => match &self.layout.abi {
+ PassMode::Direct(attrs) => match self.layout.abi {
Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
- AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())),
+ AbiParam::new(scalar_to_clif_type(tcx, scalar)),
attrs
)],
Abi::Vector { .. } => {
}
_ => unreachable!("{:?}", self.layout.abi),
},
- PassMode::Pair(attrs_a, attrs_b) => match &self.layout.abi {
+ PassMode::Pair(attrs_a, attrs_b) => match self.layout.abi {
Abi::ScalarPair(a, b) => {
- let a = scalar_to_clif_type(tcx, a.clone());
- let b = scalar_to_clif_type(tcx, b.clone());
+ let a = scalar_to_clif_type(tcx, a);
+ let b = scalar_to_clif_type(tcx, b);
smallvec![
apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a),
apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
match self.mode {
PassMode::Ignore => (None, vec![]),
- PassMode::Direct(_) => match &self.layout.abi {
+ PassMode::Direct(_) => match self.layout.abi {
Abi::Scalar(scalar) => {
- (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))])
+ (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
}
Abi::Vector { .. } => {
let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
}
_ => unreachable!("{:?}", self.layout.abi),
},
- PassMode::Pair(_, _) => match &self.layout.abi {
+ PassMode::Pair(_, _) => match self.layout.abi {
Abi::ScalarPair(a, b) => {
- let a = scalar_to_clif_type(tcx, a.clone());
- let b = scalar_to_clif_type(tcx, b.clone());
+ let a = scalar_to_clif_type(tcx, a);
+ let b = scalar_to_clif_type(tcx, b);
(None, vec![AbiParam::new(a), AbiParam::new(b)])
}
_ => unreachable!("{:?}", self.layout.abi),
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_index::vec::IndexVec;
use rustc_middle::ty::adjustment::PointerCast;
-use rustc_middle::ty::layout::FnAbiExt;
-use rustc_target::abi::call::FnAbi;
+use rustc_middle::ty::layout::FnAbiOf;
use crate::constant::ConstantCx;
use crate::prelude::*;
instance,
symbol_name,
mir,
- fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
+ fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
bcx,
block_map,
let ptr = fx.bcx.inst_results(call)[0];
lval.write_cvalue(fx, CValue::by_val(ptr, box_layout));
}
- Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
+ Rvalue::NullaryOp(null_op, ty) => {
assert!(
lval.layout()
.ty
.is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
);
- let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes();
+ let layout = fx.layout_of(fx.monomorphize(ty));
+ let val = match null_op {
+ NullOp::SizeOf => layout.size.bytes(),
+ NullOp::AlignOf => layout.align.abi.bytes(),
+ NullOp::Box => unreachable!(),
+ };
let val =
- CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
+ CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
lval.write_cvalue(fx, val);
}
Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() {
#![feature(rustc_private)]
-extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_session;
use rustc_index::vec::IndexVec;
-use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers};
+use rustc_middle::ty::layout::{
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
+};
use rustc_middle::ty::SymbolName;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Integer, Primitive};
pub(crate) instance: Instance<'tcx>,
pub(crate) symbol_name: SymbolName<'tcx>,
pub(crate) mir: &'tcx Body<'tcx>,
- pub(crate) fn_abi: Option<FnAbi<'tcx, Ty<'tcx>>>,
+ pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
pub(crate) bcx: FunctionBuilder<'clif>,
pub(crate) block_map: IndexVec<BasicBlock, Block>,
}
}
+impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
+ }
+}
+
impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.tcx
}
}
+impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+ self.0.sess.span_fatal(span, &err.to_string())
+ } else {
+ match fn_abi_request {
+ FnAbiRequest::OfFnPtr { sig, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+ sig,
+ extra_args,
+ err
+ );
+ }
+ FnAbiRequest::OfInstance { instance, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_instance({}, {:?})` failed: {}",
+ instance,
+ extra_args,
+ err
+ );
+ }
+ }
+ }
+ }
+}
+
impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.0
};
let const_val = match const_.val {
ConstKind::Value(const_val) => const_val,
- ConstKind::Unevaluated(uv)
- if fx.tcx.is_static(uv.def.did) =>
- {
+ ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
assert!(uv.substs(fx.tcx).is_empty());
assert!(uv.promoted.is_none());
}
pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
- let (element, count) = match &layout.abi {
- Abi::Vector { element, count } => (element.clone(), *count),
+ let (element, count) = match layout.abi {
+ Abi::Vector { element, count } => (element, count),
_ => unreachable!(),
};
dest.write_cvalue(fx, val);
};
- pref_align_of | min_align_of | needs_drop | type_id | type_name | variant_count, () {
+ pref_align_of | needs_drop | type_id | type_name | variant_count, () {
let const_val =
fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap();
let val = crate::constant::codegen_const_value(
write::{FuncWriter, PlainWriter},
};
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
use rustc_session::config::OutputType;
-use rustc_target::abi::call::FnAbi;
use crate::prelude::*;
vec![
format!("symbol {}", tcx.symbol_name(instance).name),
format!("instance {:?}", instance),
- format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
+ format!(
+ "abi {:?}",
+ RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())
+ ),
String::new(),
]
} else {
}
}
-fn scalar_pair_calculate_b_offset(
- tcx: TyCtxt<'_>,
- a_scalar: &Scalar,
- b_scalar: &Scalar,
-) -> Offset32 {
+fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 {
let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
Offset32::new(b_offset.bytes().try_into().unwrap())
}
match self.0 {
CValueInner::ByRef(ptr, None) => {
let clif_ty = match layout.abi {
- Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
- Abi::Vector { ref element, count } => {
- scalar_to_clif_type(fx.tcx, element.clone())
- .by(u16::try_from(count).unwrap())
- .unwrap()
- }
+ Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
+ Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
+ .by(u16::try_from(count).unwrap())
+ .unwrap(),
_ => unreachable!("{:?}", layout.ty),
};
let mut flags = MemFlags::new();
let layout = self.1;
match self.0 {
CValueInner::ByRef(ptr, None) => {
- let (a_scalar, b_scalar) = match &layout.abi {
+ let (a_scalar, b_scalar) = match layout.abi {
Abi::ScalarPair(a, b) => (a, b),
_ => unreachable!("load_scalar_pair({:?})", self),
};
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
- let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
- let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
+ let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar);
+ let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
let mut flags = MemFlags::new();
flags.set_notrap();
let val1 = ptr.load(fx, clif_ty1, flags);
to_ptr.store(fx, val, flags);
return;
}
- Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
+ Abi::ScalarPair(a_scalar, b_scalar) => {
let (value, extra) = from.load_scalar_pair(fx);
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
to_ptr.store(fx, value, flags);
[package]
name = "rustc_codegen_llvm"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc-demangle = "0.1.21"
+rustc_arena = { path = "../rustc_arena" }
rustc_attr = { path = "../rustc_attr" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_data_structures = { path = "../rustc_data_structures" }
}
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
- // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
+ if self.ret.layout.abi.is_uninhabited() {
+ llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite);
+ }
+ if !self.can_unwind {
+ llvm::Attribute::NoUnwind.apply_callsite(llvm::AttributePlace::Function, callsite);
+ }
let mut i = 0;
let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| {
}
_ => {}
}
- if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
+ if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
// If the value is a boolean, the range is 0..2 and that ultimately
// become 0..0 when the type becomes i1, which would be rejected
// by the LLVM verifier.
if let Int(..) = scalar.value {
- if !scalar.is_bool() {
- let range = scalar.valid_range_exclusive(bx);
- if range.start != range.end {
- bx.range_metadata(callsite, range);
- }
+ if !scalar.is_bool() && !scalar.is_always_valid(bx) {
+ bx.range_metadata(callsite, scalar.valid_range);
}
}
}
/// Helper function to get the LLVM type for a Scalar. Pointers are returned as
/// the equivalent integer type.
-fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: &Scalar) -> &'ll Type {
+fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type {
match scalar.value {
Primitive::Int(Integer::I8, _) => cx.type_i8(),
Primitive::Int(Integer::I16, _) => cx.type_i16(),
reg: InlineAsmRegClass,
layout: &TyAndLayout<'tcx>,
) -> &'ll Value {
- match (reg, &layout.abi) {
+ match (reg, layout.abi) {
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
if let Primitive::Int(Integer::I8, _) = s.value {
let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
Abi::Vector { element, count },
) if layout.size.bytes() == 8 => {
let elem_ty = llvm_asm_scalar_type(bx.cx, element);
- let vec_ty = bx.cx.type_vector(elem_ty, *count);
+ let vec_ty = bx.cx.type_vector(elem_ty, count);
let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
}
reg: InlineAsmRegClass,
layout: &TyAndLayout<'tcx>,
) -> &'ll Value {
- match (reg, &layout.abi) {
+ match (reg, layout.abi) {
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
if let Primitive::Int(Integer::I8, _) = s.value {
bx.extract_element(value, bx.const_i32(0))
Abi::Vector { element, count },
) if layout.size.bytes() == 8 => {
let elem_ty = llvm_asm_scalar_type(bx.cx, element);
- let vec_ty = bx.cx.type_vector(elem_ty, *count * 2);
- let indices: Vec<_> = (0..*count).map(|x| bx.const_i32(x as i32)).collect();
+ let vec_ty = bx.cx.type_vector(elem_ty, count * 2);
+ let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
}
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
reg: InlineAsmRegClass,
layout: &TyAndLayout<'tcx>,
) -> &'ll Type {
- match (reg, &layout.abi) {
+ match (reg, layout.abi) {
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
if let Primitive::Int(Integer::I8, _) = s.value {
cx.type_vector(cx.type_i8(), 8)
let mut function_features = codegen_fn_attrs
.target_features
.iter()
- .map(|f| {
+ .flat_map(|f| {
let feature = &f.as_str();
- format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+ llvm_util::to_llvm_feature(cx.tcx.sess, feature)
+ .into_iter()
+ .map(|f| format!("+{}", f))
+ .collect::<Vec<String>>()
})
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
use rustc_codegen_ssa::MemFlags;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
+};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
-use rustc_target::abi::{self, Align, Size};
+use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
use std::ffi::CStr;
use std::iter;
-use std::ops::{Deref, Range};
+use std::ops::Deref;
use std::ptr;
use tracing::debug;
}
}
+impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ self.cx.handle_fn_abi_err(err, span, fn_abi_request)
+ }
+}
+
impl Deref for Builder<'_, 'll, 'tcx> {
type Target = CodegenCx<'ll, 'tcx>;
val
}
}
- fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value {
+ fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
if scalar.is_bool() {
return self.trunc(val, self.cx().type_i1());
}
fn scalar_load_metadata<'a, 'll, 'tcx>(
bx: &mut Builder<'a, 'll, 'tcx>,
load: &'ll Value,
- scalar: &abi::Scalar,
+ scalar: abi::Scalar,
) {
match scalar.value {
abi::Int(..) => {
- let range = scalar.valid_range_exclusive(bx);
- if range.start != range.end {
- bx.range_metadata(load, range);
+ if !scalar.is_always_valid(bx) {
+ bx.range_metadata(load, scalar.valid_range);
}
}
- abi::Pointer if !scalar.valid_range.contains_zero() => {
+ abi::Pointer if !scalar.valid_range.contains(0) => {
bx.nonnull_metadata(load);
}
_ => {}
}
let llval = const_llval.unwrap_or_else(|| {
let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
- if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
+ if let abi::Abi::Scalar(scalar) = place.layout.abi {
scalar_load_metadata(self, load, scalar);
}
load
});
OperandValue::Immediate(self.to_immediate(llval, place.layout))
- } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
+ } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi {
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
let pair_ty = place.layout.llvm_type(self);
- let mut load = |i, scalar: &abi::Scalar, align| {
+ let mut load = |i, scalar: abi::Scalar, align| {
let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
let load = self.load(llty, llptr, align);
next_bx
}
- fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
+ fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) {
if self.sess().target.arch == "amdgpu" {
// amdgpu/LLVM does something weird and thinks an i64 value is
// split into a v2i32, halving the bitwidth LLVM expects,
let llty = self.cx.val_ty(load);
let v = [
self.cx.const_uint_big(llty, range.start),
- self.cx.const_uint_big(llty, range.end),
+ self.cx.const_uint_big(llty, range.end.wrapping_add(1)),
];
llvm::LLVMSetMetadata(
//! and methods are represented as just a fn ptr and not a full
//! closure.
-use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::abi::FnAbiLlvmExt;
use crate::attributes;
use crate::context::CodegenCx;
use crate::llvm;
use rustc_codegen_ssa::traits::*;
use tracing::debug;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeFoldable};
/// Codegens a reference to a fn/method item, monomorphizing and
sym
);
- let fn_abi = FnAbi::of_instance(cx, instance, &[]);
+ let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
// Create a fn pointer with the new signature.
})
}
- fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value {
+ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value {
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
match cv {
Scalar::Int(ScalarInt::ZST) => {
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
&cx.tcx,
),
- &Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
+ Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
cx.type_i8p_ext(address_space),
));
next_offset = offset + pointer_size;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_middle::mir::mono::CodegenUnit;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+ TyAndLayout,
+};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
use rustc_session::Session;
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
-use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{
+ call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
+};
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
use smallvec::SmallVec;
}
}
+impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ ty::ParamEnv::reveal_all()
+ }
+}
+
impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
type LayoutOfResult = TyAndLayout<'tcx>;
}
}
-impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- ty::ParamEnv::reveal_all()
+impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+ self.sess().span_fatal(span, &err.to_string())
+ } else {
+ match fn_abi_request {
+ FnAbiRequest::OfFnPtr { sig, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+ sig,
+ extra_args,
+ err
+ );
+ }
+ FnAbiRequest::OfInstance { instance, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_instance({}, {:?})` failed: {}",
+ instance,
+ extra_args,
+ err
+ );
+ }
+ }
+ }
}
}
use crate::llvm;
-use crate::abi::{Abi, FnAbi};
+use crate::abi::Abi;
use crate::builder::Builder;
use crate::common::CodegenCx;
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
};
use rustc_middle::ty;
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Instance;
let llfn = cx.declare_fn(
&tcx.symbol_name(instance).name,
- &FnAbi::of_fn_ptr(
- cx,
+ &cx.fn_abi_of_fn_ptr(
ty::Binder::dummy(tcx.mk_fn_sig(
iter::once(tcx.mk_unit()),
tcx.mk_unit(),
hir::Unsafety::Unsafe,
Abi::Rust,
)),
- &[],
+ ty::List::empty(),
),
);
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
-use crate::abi::FnAbi;
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DILocation, DIScope};
use rustc_middle::mir::{Body, SourceScope};
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;
ty::ParamEnv::reveal_all(),
callee,
);
- let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
+ let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
}
None => unsafe {
use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{self, DebugInfo};
-use rustc_span::symbol::{Interner, Symbol};
+use rustc_span::symbol::Symbol;
use rustc_span::FileNameDisplayPreference;
use rustc_span::{self, SourceFile, SourceFileHash, Span};
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
-#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
-pub struct UniqueTypeId(Symbol);
+mod unique_type_id {
+ use super::*;
+ use rustc_arena::DroplessArena;
+
+ #[derive(Copy, Hash, Eq, PartialEq, Clone)]
+ pub(super) struct UniqueTypeId(u32);
+
+ // The `&'static str`s in this type actually point into the arena.
+ //
+ // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
+ // found that to regress performance up to 2% in some cases. This might be
+ // revisited after further improvements to `indexmap`.
+ #[derive(Default)]
+ pub(super) struct TypeIdInterner {
+ arena: DroplessArena,
+ names: FxHashMap<&'static str, UniqueTypeId>,
+ strings: Vec<&'static str>,
+ }
+
+ impl TypeIdInterner {
+ #[inline]
+ pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId {
+ if let Some(&name) = self.names.get(string) {
+ return name;
+ }
+
+ let name = UniqueTypeId(self.strings.len() as u32);
+
+ // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
+ // UTF-8.
+ let string: &str =
+ unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
+ // It is safe to extend the arena allocation to `'static` because we only access
+ // these while the arena is still alive.
+ let string: &'static str = unsafe { &*(string as *const str) };
+ self.strings.push(string);
+ self.names.insert(string, name);
+ name
+ }
+
+ // Get the symbol as a string. `Symbol::as_str()` should be used in
+ // preference to this function.
+ pub(super) fn get(&self, symbol: UniqueTypeId) -> &str {
+ self.strings[symbol.0 as usize]
+ }
+ }
+}
+use unique_type_id::*;
/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
#[derive(Default)]
pub struct TypeMap<'ll, 'tcx> {
/// The `UniqueTypeId`s created so far.
- unique_id_interner: Interner,
+ unique_id_interner: TypeIdInterner,
/// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
/// A map from types to debuginfo metadata. This is an N:1 mapping.
/// Gets the string representation of a `UniqueTypeId`. This method will fail if
/// the ID is unknown.
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
- let UniqueTypeId(interner_key) = unique_type_id;
- self.unique_id_interner.get(interner_key)
+ self.unique_id_interner.get(unique_type_id)
}
/// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
let key = self.unique_id_interner.intern(&unique_type_id);
- self.type_to_unique_id.insert(type_, UniqueTypeId(key));
+ self.type_to_unique_id.insert(type_, key);
- UniqueTypeId(key)
+ key
}
/// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
let enum_variant_type_id =
format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
- UniqueTypeId(interner_key)
+ interner_key
}
/// Gets the unique type ID string for an enum variant part.
Variants::Multiple {
tag_encoding:
TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
- ref tag,
+ tag,
ref variants,
tag_field,
} => {
let layout = cx.layout_of(enum_type);
- if let (
- &Abi::Scalar(_),
- &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
- ) = (&layout.abi, &layout.variants)
+ if let (Abi::Scalar(_), Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. }) =
+ (layout.abi, &layout.variants)
{
return FinalMetadata(discriminant_type_metadata(tag.value));
}
if use_enum_fallback(cx) {
let discriminant_type_metadata = match layout.variants {
Variants::Single { .. } => None,
- Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. }
- | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
+ Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. }
+ | Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
Some(discriminant_type_metadata(tag.value))
}
};
// A single-variant enum has no discriminant.
Variants::Single { .. } => None,
- Variants::Multiple {
- tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
- } => {
+ Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, tag_field, .. } => {
// Find the integer type of the correct size.
let size = tag.value.size(cx);
let align = tag.value.align(cx);
}
}
- Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
+ Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, tag_field, .. } => {
let discr_type = tag.value.to_ty(cx.tcx);
let (size, align) = cx.size_and_align_of(discr_type);
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_hir as hir;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::{sym, symbol::kw, Span, Symbol};
}
sym::va_arg => {
match fn_abi.ret.layout.abi {
- abi::Abi::Scalar(ref scalar) => {
+ abi::Abi::Scalar(scalar) => {
match scalar.value {
Primitive::Int(..) => {
if self.cx().size_of(ret_ty).bytes() < 4 {
rust_fn_sig: ty::PolyFnSig<'tcx>,
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
) -> (&'ll Type, &'ll Value) {
- let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
+ let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
let llty = fn_abi.llvm_type(cx);
let llfn = cx.declare_fn(name, &fn_abi);
cx.set_frame_pointer_type(llfn);
}
if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
- let n: u64 = stripped.parse().unwrap_or_else(|_| {
- span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
- });
+ // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
+ // If there is no suffix, use the index array length.
+ let n: u64 = if stripped.is_empty() {
+ // Make sure this is actually an array, since typeck only checks the length-suffixed
+ // version of this intrinsic.
+ match args[2].layout.ty.kind() {
+ ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
+ len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| {
+ span_bug!(span, "could not evaluate shuffle index array length")
+ })
+ }
+ _ => return_error!(
+ "simd_shuffle index must be an array of `u32`, got `{}`",
+ args[2].layout.ty
+ ),
+ }
+ } else {
+ stripped.parse().unwrap_or_else(|_| {
+ span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
+ })
+ };
require_simd!(ret_ty, "return");
-
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(
out_len == n,
// Though note that Rust can also be build with an external precompiled version of LLVM
// which might lead to failures if the oldest tested / supported LLVM version
// doesn't yet support the relevant intrinsics
-pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
+pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
match (arch, s) {
- ("x86", "pclmulqdq") => "pclmul",
- ("x86", "rdrand") => "rdrnd",
- ("x86", "bmi1") => "bmi",
- ("x86", "cmpxchg16b") => "cx16",
- ("x86", "avx512vaes") => "vaes",
- ("x86", "avx512gfni") => "gfni",
- ("x86", "avx512vpclmulqdq") => "vpclmulqdq",
- ("aarch64", "fp") => "fp-armv8",
- ("aarch64", "fp16") => "fullfp16",
- ("aarch64", "fhm") => "fp16fml",
- ("aarch64", "rcpc2") => "rcpc-immo",
- ("aarch64", "dpb") => "ccpp",
- ("aarch64", "dpb2") => "ccdp",
- ("aarch64", "frintts") => "fptoint",
- ("aarch64", "fcma") => "complxnum",
- (_, s) => s,
+ ("x86", "sse4.2") => {
+ if get_version() >= (14, 0, 0) {
+ vec!["sse4.2", "crc32"]
+ } else {
+ vec!["sse4.2"]
+ }
+ }
+ ("x86", "pclmulqdq") => vec!["pclmul"],
+ ("x86", "rdrand") => vec!["rdrnd"],
+ ("x86", "bmi1") => vec!["bmi"],
+ ("x86", "cmpxchg16b") => vec!["cx16"],
+ ("x86", "avx512vaes") => vec!["vaes"],
+ ("x86", "avx512gfni") => vec!["gfni"],
+ ("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"],
+ ("aarch64", "fp") => vec!["fp-armv8"],
+ ("aarch64", "fp16") => vec!["fullfp16"],
+ ("aarch64", "fhm") => vec!["fp16fml"],
+ ("aarch64", "rcpc2") => vec!["rcpc-immo"],
+ ("aarch64", "dpb") => vec!["ccpp"],
+ ("aarch64", "dpb2") => vec!["ccdp"],
+ ("aarch64", "frintts") => vec!["fptoint"],
+ ("aarch64", "fcma") => vec!["complxnum"],
+ (_, s) => vec![s],
}
}
},
)
.filter(|feature| {
- let llvm_feature = to_llvm_feature(sess, feature);
- let cstr = CString::new(llvm_feature).unwrap();
- unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
+ for llvm_feature in to_llvm_feature(sess, feature) {
+ let cstr = CString::new(llvm_feature).unwrap();
+ if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
+ return true;
+ }
+ }
+ false
})
.map(|feature| Symbol::intern(feature))
.collect()
let mut rustc_target_features = supported_target_features(sess)
.iter()
.filter_map(|(feature, _gate)| {
- let llvm_feature = to_llvm_feature(sess, *feature);
- // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
- target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| {
- let (_f, desc) = target_features.remove(index);
- (*feature, desc)
- })
+ for llvm_feature in to_llvm_feature(sess, *feature) {
+ // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+ match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map(
+ |index| {
+ let (_f, desc) = target_features.remove(index);
+ (*feature, desc)
+ },
+ ) {
+ Some(v) => return Some(v),
+ None => {}
+ }
+ }
+ None
})
.collect::<Vec<_>>();
rustc_target_features.extend_from_slice(&[(
let filter = |s: &str| {
if s.is_empty() {
- return None;
+ return vec![];
}
let feature = if s.starts_with('+') || s.starts_with('-') {
&s[1..]
} else {
- return Some(s.to_string());
+ return vec![s.to_string()];
};
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
// are not passed down to LLVM.
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
- return None;
+ return vec![];
}
// ... otherwise though we run through `to_llvm_feature` feature when
// passing requests down to LLVM. This means that all in-language
// features also work on the command line instead of having two
// different names when the LLVM name and the Rust name differ.
- Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
+ to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect()
};
// Features implied by an implicit or explicit `--target`.
- features.extend(sess.target.features.split(',').filter_map(&filter));
+ features.extend(sess.target.features.split(',').flat_map(&filter));
// -Ctarget-features
- features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
+ features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
features
}
-use crate::abi::FnAbi;
use crate::attributes;
use crate::base;
use crate::context::CodegenCx;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
pub use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_session::config::CrateType;
use rustc_target::spec::RelocModel;
) {
assert!(!instance.substs.needs_infer());
- let fn_abi = FnAbi::of_instance(self, instance, &[]);
+ let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
let lldecl = self.declare_fn(symbol_name, &fn_abi);
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
-use crate::abi::FnAbi;
use crate::common::*;
use crate::context::TypeLowering;
use crate::type_::Type;
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
) -> &'a Type {
match layout.abi {
Abi::Scalar(_) => bug!("handled elsewhere"),
- Abi::Vector { ref element, count } => {
+ Abi::Vector { element, count } => {
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
return cx.type_vector(element, count);
}
fn scalar_llvm_type_at<'a>(
&self,
cx: &CodegenCx<'a, 'tcx>,
- scalar: &Scalar,
+ scalar: Scalar,
offset: Size,
) -> &'a Type;
fn scalar_pair_element_llvm_type<'a>(
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
- if let Abi::Scalar(ref scalar) = self.abi {
+ if let Abi::Scalar(scalar) = self.abi {
// Use a different cache for scalars because pointers to DSTs
// can be either fat or thin (data pointers of fat pointers).
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
ty::Adt(def, _) if def.is_box() => {
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
}
- ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])),
+ ty::FnPtr(sig) => {
+ cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
+ }
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
};
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
}
fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
- if let Abi::Scalar(ref scalar) = self.abi {
+ if let Abi::Scalar(scalar) = self.abi {
if scalar.is_bool() {
return cx.type_i1();
}
fn scalar_llvm_type_at<'a>(
&self,
cx: &CodegenCx<'a, 'tcx>,
- scalar: &Scalar,
+ scalar: Scalar,
offset: Size,
) -> &'a Type {
match scalar.value {
}
let (a, b) = match self.abi {
- Abi::ScalarPair(ref a, ref b) => (a, b),
+ Abi::ScalarPair(a, b) => (a, b),
_ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
};
let scalar = [a, b][index];
[package]
name = "rustc_codegen_ssa"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
cmd.arg("-o");
cmd.arg(&dwp_out_filename);
- let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+ let mut new_path = sess.get_tools_search_paths(false);
if let Some(path) = env::var_os("PATH") {
new_path.extend(env::split_paths(&path));
}
match ld_impl {
LdImpl::Lld => {
if sess.target.lld_flavor == LldFlavor::Ld64 {
- let tools_path =
- sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+ let tools_path = sess.get_tools_search_paths(false);
let ld64_exe = tools_path
.into_iter()
.map(|p| p.join("gcc-ld"))
arg
});
} else {
- let tools_path =
- sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+ let tools_path = sess.get_tools_search_paths(false);
let lld_path = tools_path
.into_iter()
.map(|p| p.join("gcc-ld"))
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{json, Encoder};
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
-use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_span::symbol::Symbol;
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
// The compiler's sysroot often has some bundled tools, so add it to the
// PATH for the child.
- let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
+ let mut new_path = sess.get_tools_search_paths(self_contained);
let mut msvc_changed_path = false;
if sess.target.is_like_msvc {
if let Some(ref tool) = msvc_tool {
// calculate the range of values for the dataful variant
let dataful_discriminant_range =
- &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
+ dataful_variant_layout.largest_niche.unwrap().scalar.valid_range;
let min = dataful_discriminant_range.start;
let min = tag.value.size(&tcx).truncate(min);
use rustc_index::vec::Idx;
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::{self, SwitchTargets};
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, HasDataLayout};
+use rustc_target::abi::{self, HasDataLayout, WrappingRange};
use rustc_target::spec::abi::Abi;
/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
&self,
fx: &mut FunctionCx<'a, 'tcx, Bx>,
bx: &mut Bx,
- fn_abi: FnAbi<'tcx, Ty<'tcx>>,
+ fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
fn_ptr: Bx::Value,
llargs: &[Bx::Value],
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
substs: drop_fn.substs,
};
- let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
+ let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
let vtable = args[1];
args = &args[..1];
(
fn_abi,
)
}
- _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])),
+ _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
};
helper.do_call(
self,
// Obtain the panic entry point.
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
+ let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call.
let def_id =
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
let instance = ty::Instance::mono(bx.tcx(), def_id);
- let fn_abi = FnAbi::of_instance(bx, instance, &[]);
+ let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call.
};
let extra_args = &args[sig.inputs().skip_binder().len()..];
- let extra_args = extra_args
- .iter()
- .map(|op_arg| {
- let op_ty = op_arg.ty(self.mir, bx.tcx());
- self.monomorphize(op_ty)
- })
- .collect::<Vec<_>>();
+ let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| {
+ let op_ty = op_arg.ty(self.mir, bx.tcx());
+ self.monomorphize(op_ty)
+ }));
let fn_abi = match instance {
- Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args),
- None => FnAbi::of_fn_ptr(&bx, sig, &extra_args),
+ Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
+ None => bx.fn_abi_of_fn_ptr(sig, extra_args),
};
if intrinsic == Some(sym::transmute) {
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
if let mir::Operand::Constant(constant) = arg {
let c = self.eval_mir_constant(constant);
- let (llval, ty) =
- self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c);
+ let (llval, ty) = self.simd_shuffle_indices(
+ &bx,
+ constant.span,
+ self.monomorphize(constant.ty()),
+ c,
+ );
return OperandRef {
val: Immediate(llval),
layout: bx.layout_of(ty),
// the load would just produce `OperandValue::Ref` instead
// of the `OperandValue::Immediate` we need for the call.
llval = bx.load(bx.backend_type(arg.layout), llval, align);
- if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+ if let abi::Abi::Scalar(scalar) = arg.layout.abi {
if scalar.is_bool() {
- bx.range_metadata(llval, 0..2);
+ bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
}
}
// We store bools as `i8` so we need to truncate to `i1`.
let src = self.codegen_operand(bx, src);
// Special-case transmutes between scalars as simple bitcasts.
- match (&src.layout.abi, &dst.layout.abi) {
+ match (src.layout.abi, dst.layout.abi) {
(abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
// HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) {
if let Some(prim) = field.val.try_to_scalar() {
let layout = bx.layout_of(field_ty);
let scalar = match layout.abi {
- Abi::Scalar(ref x) => x,
+ Abi::Scalar(x) => x,
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
};
bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir;
use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
use rustc_session::config::DebugInfo;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
+use rustc_target::abi::Abi;
use rustc_target::abi::Size;
use super::operand::{OperandRef, OperandValue};
{
let arg_index = place.local.index() - 1;
if target_is_msvc {
- // Rust compiler decomposes every &str or slice argument into two components:
- // a pointer to the memory address where the data is stored and a usize representing
- // the length of the str (or slice). These components will later be used to reconstruct
- // the original argument inside the body of the function that owns it (see the
- // definition of debug_introduce_local for more details).
- //
- // Since the original argument is declared inside a function rather than being passed
- // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
- // its data correctly. (See issue #81894 for an in-depth description of the problem).
- match *var_ty.kind() {
- ty::Ref(_, inner_type, _) => match *inner_type.kind() {
- ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
- _ => VariableKind::ArgumentVariable(arg_index + 1),
- },
- _ => VariableKind::ArgumentVariable(arg_index + 1),
+ // ScalarPair parameters are spilled to the stack so they need to
+ // be marked as a `LocalVariable` for MSVC debuggers to visualize
+ // their data correctly. (See #81894 & #88625)
+ let var_ty_layout = self.cx.layout_of(var_ty);
+ if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
+ VariableKind::LocalVariable
+ } else {
+ VariableKind::ArgumentVariable(arg_index + 1)
}
} else {
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
}
}
sym::pref_align_of
- | sym::min_align_of
| sym::needs_drop
| sym::type_id
| sym::type_name
use rustc_errors::ErrorReported;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_target::abi::call::{FnAbi, PassMode};
cx: &'a Bx::CodegenCx,
- fn_abi: FnAbi<'tcx, Ty<'tcx>>,
+ fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
/// When unwinding is initiated, we have to store this personality
/// value somewhere so that we can load it and re-use it in the
///////////////////////////////////////////////////////////////////////////
+#[instrument(level = "debug", skip(cx))]
pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
instance: Instance<'tcx>,
let mir = cx.tcx().instance_mir(instance.def);
- let fn_abi = FnAbi::of_instance(cx, instance, &[]);
+ let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
debug!("fn_abi: {:?}", fn_abi);
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
}
let cleanup_kinds = analyze::cleanup_kinds(&mir);
- // Allocate a `Block` for every basic block, except
- // the start block, if nothing loops back to it.
- let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
- let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> =
- mir.basic_blocks()
- .indices()
- .map(|bb| {
- if bb == mir::START_BLOCK && !reentrant_start_block {
- Some(start_llbb)
- } else {
- None
- }
- })
- .collect();
+ let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = mir
+ .basic_blocks()
+ .indices()
+ .map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None })
+ .collect();
let mut fx = FunctionCx {
instance,
// Apply debuginfo to the newly allocated locals.
fx.debug_introduce_locals(&mut bx);
- // Branch to the START block, if it's not the entry block.
- if reentrant_start_block {
- bx.br(fx.llbb(mir::START_BLOCK));
- }
-
// Codegen the body of each block using reverse postorder
// FIXME(eddyb) reuse RPO iterator between `analysis` and this.
for (bb, _) in traversal::reverse_postorder(&mir) {
let val = match val {
ConstValue::Scalar(x) => {
let scalar = match layout.abi {
- Abi::Scalar(ref x) => x,
+ Abi::Scalar(x) => x,
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
};
let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout));
}
ConstValue::Slice { data, start, end } => {
let a_scalar = match layout.abi {
- Abi::ScalarPair(ref a, _) => a,
+ Abi::ScalarPair(a, _) => a,
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
};
let a = Scalar::from_pointer(
llval: V,
layout: TyAndLayout<'tcx>,
) -> Self {
- let val = if let Abi::ScalarPair(ref a, ref b) = layout.abi {
+ let val = if let Abi::ScalarPair(a, b) = layout.abi {
debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout);
// Deconstruct the immediate aggregate.
let field = self.layout.field(bx.cx(), i);
let offset = self.layout.fields.offset(i);
- let mut val = match (self.val, &self.layout.abi) {
+ let mut val = match (self.val, self.layout.abi) {
// If the field is ZST, it has no data.
_ if field.is_zst() => {
return OperandRef::new_zst(bx, field);
}
// Extract a scalar component from a pair.
- (OperandValue::Pair(a_llval, b_llval), &Abi::ScalarPair(ref a, ref b)) => {
+ (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => {
if offset.bytes() == 0 {
assert_eq!(field.size, a.value.size(bx.cx()));
OperandValue::Immediate(a_llval)
}
// `#[repr(simd)]` types are also immediate.
- (OperandValue::Immediate(llval), &Abi::Vector { .. }) => {
+ (OperandValue::Immediate(llval), Abi::Vector { .. }) => {
OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
}
_ => bug!("OperandRef::extract_field({:?}): not applicable", self),
};
- match (&mut val, &field.abi) {
+ match (&mut val, field.abi) {
(OperandValue::Immediate(llval), _) => {
// Bools in union fields needs to be truncated.
*llval = bx.to_immediate(*llval, field);
}
OperandValue::Pair(a, b) => {
let (a_scalar, b_scalar) = match dest.layout.abi {
- Abi::ScalarPair(ref a, ref b) => (a, b),
+ Abi::ScalarPair(a, b) => (a, b),
_ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout),
};
let ty = bx.backend_type(dest.layout);
// Also handles the first field of Scalar, ScalarPair, and Vector layouts.
self.llval
}
- Abi::ScalarPair(ref a, ref b)
+ Abi::ScalarPair(a, b)
if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) =>
{
// Offset matches second field.
.map_or(index.as_u32() as u128, |discr| discr.val);
return bx.cx().const_uint_big(cast_to, discr_val);
}
- Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+ Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
(tag, tag_encoding, tag_field)
}
};
let llval = operand.immediate();
let mut signed = false;
- if let Abi::Scalar(ref scalar) = operand.layout.abi {
+ if let Abi::Scalar(scalar) = operand.layout.abi {
if let Int(_, s) = scalar.value {
// We use `i1` for bytes that are always `0` or `1`,
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
signed = !scalar.is_bool() && s;
- let er = scalar.valid_range_exclusive(bx.cx());
- if er.end != er.start
+ if !scalar.is_always_valid(bx.cx())
&& scalar.valid_range.end >= scalar.valid_range.start
{
// We want `table[e as usize ± k]` to not
)
}
- mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
- let ty = self.monomorphize(ty);
- assert!(bx.cx().type_is_sized(ty));
- let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes());
- let tcx = self.cx.tcx();
- (
- bx,
- OperandRef {
- val: OperandValue::Immediate(val),
- layout: self.cx.layout_of(tcx.types.usize),
- },
- )
- }
-
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
let content_ty = self.monomorphize(content_ty);
let content_layout = bx.cx().layout_of(content_ty);
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
(bx, operand)
}
+
+ mir::Rvalue::NullaryOp(null_op, ty) => {
+ let ty = self.monomorphize(ty);
+ assert!(bx.cx().type_is_sized(ty));
+ let layout = bx.cx().layout_of(ty);
+ let val = match null_op {
+ mir::NullOp::SizeOf => layout.size.bytes(),
+ mir::NullOp::AlignOf => layout.align.abi.bytes(),
+ mir::NullOp::Box => unreachable!(),
+ };
+ let val = bx.cx().const_usize(val);
+ let tcx = self.cx.tcx();
+ (
+ bx,
+ OperandRef {
+ val: OperandValue::Immediate(val),
+ layout: self.cx.layout_of(tcx.types.usize),
+ },
+ )
+ }
+
mir::Rvalue::ThreadLocalRef(def_id) => {
assert!(bx.cx().tcx().is_static(def_id));
let static_ = bx.get_static(def_id);
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
use rustc_session::{
config::{self, OutputFilenames, PrintRequest},
Session,
};
use rustc_span::symbol::Symbol;
+use rustc_target::abi::call::FnAbi;
use rustc_target::spec::Target;
pub use rustc_data_structures::sync::MetadataRef;
}
pub trait Backend<'tcx>:
- Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ Sized
+ + BackendTypes
+ + HasTyCtxt<'tcx>
+ + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
{
}
impl<'tcx, T> Backend<'tcx> for T where
- Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ Self: BackendTypes
+ + HasTyCtxt<'tcx>
+ + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
{
}
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_span::Span;
-use rustc_target::abi::{Abi, Align, Scalar, Size};
+use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
use rustc_target::spec::HasTargetSpec;
-use std::ops::Range;
-
#[derive(Copy, Clone)]
pub enum OverflowOp {
Add,
fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
- if let Abi::Scalar(ref scalar) = layout.abi {
+ if let Abi::Scalar(scalar) = layout.abi {
self.to_immediate_scalar(val, scalar)
} else {
val
}
}
- fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value;
+ fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
dest: PlaceRef<'tcx, Self::Value>,
) -> Self;
- fn range_metadata(&mut self, load: Self::Value, range: Range<u128>);
+ fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
fn nonnull_metadata(&mut self, load: Self::Value);
fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
- fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value;
+ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
fn from_const_alloc(
&self,
layout: TyAndLayout<'tcx>,
[package]
name = "rustc_const_eval"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
assert!(!layout.is_unsized());
let ret = ecx.allocate(layout, MemoryKind::Stack)?;
- let name =
- with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id())));
- let prom = cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p));
- trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
+ trace!(
+ "eval_body_using_ecx: pushing stack frame for global: {}{}",
+ with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))),
+ cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p))
+ );
ecx.push_stack_frame(
cid.instance,
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
use rustc_middle::hir::map::blocks::FnLikeNode;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
}
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
- let parent_id = tcx.hir().get_parent_did(hir_id);
- if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false }
+ let parent_id = tcx.hir().get_parent_node(hir_id);
+ matches!(
+ tcx.hir().get(parent_id),
+ hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
+ ..
+ })
+ )
}
/// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
}
}
-/// Checks whether the given item is an `impl` that has a `const` modifier.
-fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let node = tcx.hir().get(hir_id);
- matches!(
- node,
- hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
- ..
- })
- )
-}
-
fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
is_const_fn(tcx, def_id)
&& match tcx.lookup_const_stability(def_id) {
}
pub fn provide(providers: &mut Providers) {
- *providers = Providers {
- is_const_fn_raw,
- is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
- is_promotable_const_fn,
- ..*providers
- };
+ *providers = Providers { is_const_fn_raw, is_promotable_const_fn, ..*providers };
}
let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn()
|| Some(def_id) == self.tcx.lang_items().panic_str()
+ || Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
- // &str
+ // &str or &&str
assert!(args.len() == 1);
- let msg_place = self.deref_operand(&args[0])?;
+ let mut msg_place = self.deref_operand(&args[0])?;
+ while msg_place.layout.ty.is_ref() {
+ msg_place = self.deref_operand(&msg_place.into())?;
+ }
+
let msg = Symbol::intern(self.read_str(&msg_place)?);
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);
ensure_monomorphic_enough(tcx, tp_ty)?;
ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
}
- sym::min_align_of | sym::pref_align_of => {
+ sym::pref_align_of => {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
- let n = match name {
- sym::pref_align_of => layout.align.pref.bytes(),
- sym::min_align_of => layout.align.abi.bytes(),
- _ => bug!(),
- };
- ConstValue::from_machine_usize(n, &tcx)
+ ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx)
}
sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?;
self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
}
- sym::min_align_of
- | sym::pref_align_of
+ sym::pref_align_of
| sym::needs_drop
| sym::type_id
| sym::type_name
| sym::variant_count => {
let gid = GlobalId { instance, promoted: None };
let ty = match intrinsic_name {
- sym::min_align_of | sym::pref_align_of | sym::variant_count => {
- self.tcx.types.usize
- }
+ sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
sym::needs_drop => self.tcx.types.bool,
sym::type_id => self.tcx.types.u64,
sym::type_name => self.tcx.mk_static_str(),
let val = self.read_scalar(&args[0])?.check_init()?;
let bits = val.to_bits(layout_of.size)?;
let kind = match layout_of.abi {
- Abi::Scalar(ref scalar) => scalar.value,
+ Abi::Scalar(scalar) => scalar.value,
_ => span_bug!(
self.cur_span(),
"{} called on invalid type {:?}",
&r,
)?;
let val = if overflowed {
- let num_bits = l.layout.size.bits();
+ let size = l.layout.size;
+ let num_bits = size.bits();
if l.layout.abi.is_signed() {
// For signed ints the saturated value depends on the sign of the first
// term since the sign of the second term can be inferred from this and
// unsigned
if is_add {
// max unsigned
- Scalar::from_uint(
- u128::MAX >> (128 - num_bits),
- Size::from_bits(num_bits),
- )
+ Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
} else {
// underflow to 0
Scalar::from_uint(0u128, Size::from_bits(num_bits))
let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?;
Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout }))
}
- Abi::ScalarPair(ref a, ref b) => {
+ Abi::ScalarPair(a, b) => {
// We checked `ptr_align` above, so all fields will have the alignment they need.
// We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
- let (a, b) = (&a.value, &b.value);
+ let (a, b) = (a.value, b.value);
let (a_size, b_size) = (a.size(self), b.size(self));
let b_offset = a_size.align_to(b.align(self).abi);
assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
};
return Ok((discr, index));
}
- Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+ Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
(tag, tag_encoding, tag_field)
}
};
// We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
let (a, b) = match dest.layout.abi {
- Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
+ Abi::ScalarPair(a, b) => (a.value, b.value),
_ => span_bug!(
self.cur_span(),
"write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
}
Variants::Multiple {
tag_encoding: TagEncoding::Direct,
- tag: ref tag_layout,
+ tag: tag_layout,
tag_field,
..
} => {
Variants::Multiple {
tag_encoding:
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
- tag: ref tag_layout,
+ tag: tag_layout,
tag_field,
..
} => {
M::box_alloc(self, &dest)?;
}
- NullaryOp(mir::NullOp::SizeOf, ty) => {
+ NullaryOp(null_op, ty) => {
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
let layout = self.layout_of(ty)?;
if layout.is_unsized() {
// FIXME: This should be a span_bug (#80742)
self.tcx.sess.delay_span_bug(
self.frame().current_span(),
- &format!("SizeOf nullary MIR operator called for unsized type {}", ty),
+ &format!("Nullary MIR operator called for unsized type {}", ty),
);
throw_inval!(SizeOfUnsizedType(ty));
}
- self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?;
+ let val = match null_op {
+ mir::NullOp::SizeOf => layout.size.bytes(),
+ mir::NullOp::AlignOf => layout.align.abi.bytes(),
+ mir::NullOp::Box => unreachable!(),
+ };
+ self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
}
Cast(cast_kind, ref operand, cast_ty) => {
return false;
}
// Compare layout
- match (&caller.abi, &callee.abi) {
+ match (caller.abi, callee.abi) {
// Different valid ranges are okay (once we enforce validity,
// that will take care to make it UB to leave the range, just
// like for transmute).
- (abi::Abi::Scalar(ref caller), abi::Abi::Scalar(ref callee)) => {
- caller.value == callee.value
+ (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value,
+ (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => {
+ caller1.value == callee1.value && caller2.value == callee2.value
}
- (
- abi::Abi::ScalarPair(ref caller1, ref caller2),
- abi::Abi::ScalarPair(ref callee1, ref callee2),
- ) => caller1.value == callee1.value && caller2.value == callee2.value,
// Be conservative
_ => false,
}
///
macro_rules! try_validation {
($e:expr, $where:expr,
- $( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
+ $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
) => {{
match $e {
Ok(x) => x,
fn visit_scalar(
&mut self,
op: &OpTy<'tcx, M::PointerTag>,
- scalar_layout: &ScalarAbi,
+ scalar_layout: ScalarAbi,
) -> InterpResult<'tcx> {
- let value = self.read_scalar(op)?;
- let valid_range = scalar_layout.valid_range.clone();
- let WrappingRange { start: lo, end: hi } = valid_range;
- // Determine the allowed range
- // `max_hi` is as big as the size fits
- let max_hi = u128::MAX >> (128 - op.layout.size.bits());
- assert!(hi <= max_hi);
- // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128`
- if (lo == 0 && hi == max_hi) || (hi + 1 == lo) {
+ if scalar_layout.valid_range.is_full_for(op.layout.size) {
// Nothing to check
return Ok(());
}
- // At least one value is excluded. Get the bits.
+ // At least one value is excluded.
+ let valid_range = scalar_layout.valid_range;
+ let WrappingRange { start, end } = valid_range;
+ let max_value = op.layout.size.unsigned_int_max();
+ assert!(end <= max_value);
+ // Determine the allowed range
+ let value = self.read_scalar(op)?;
let value = try_validation!(
value.check_init(),
self.path,
err_ub!(InvalidUninitBytes(None)) => { "{}", value }
- expected { "something {}", wrapping_range_format(valid_range, max_hi) },
+ expected { "something {}", wrapping_range_format(valid_range, max_value) },
);
let bits = match value.try_to_int() {
Err(_) => {
// So this is a pointer then, and casting to an int failed.
// Can only happen during CTFE.
let ptr = self.ecx.scalar_to_ptr(value);
- if lo == 1 && hi == max_hi {
+ if start == 1 && end == max_value {
// Only null is the niche. So make sure the ptr is NOT null.
if self.ecx.memory.ptr_may_be_null(ptr) {
throw_validation_failure!(self.path,
{ "a potentially null pointer" }
expected {
"something that cannot possibly fail to be {}",
- wrapping_range_format(valid_range, max_hi)
+ wrapping_range_format(valid_range, max_value)
}
)
}
{ "a pointer" }
expected {
"something that cannot possibly fail to be {}",
- wrapping_range_format(valid_range, max_hi)
+ wrapping_range_format(valid_range, max_value)
}
)
}
} else {
throw_validation_failure!(self.path,
{ "{}", bits }
- expected { "something {}", wrapping_range_format(valid_range, max_hi) }
+ expected { "something {}", wrapping_range_format(valid_range, max_value) }
)
}
}
{ "a value of uninhabited type {:?}", op.layout.ty }
);
}
- Abi::Scalar(ref scalar_layout) => {
+ Abi::Scalar(scalar_layout) => {
self.visit_scalar(op, scalar_layout)?;
}
Abi::ScalarPair { .. } | Abi::Vector { .. } => {
use std::ops::Deref;
use super::ops::{self, NonConstOp, Status};
-use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
+use super::qualifs::{self, CustomEq, HasMutInterior, NeedsNonConstDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{is_lang_panic_fn, ConstCx, Qualif};
use crate::const_eval::is_unstable_const_fn;
#[derive(Default)]
pub struct Qualifs<'mir, 'tcx> {
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
- needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
+ needs_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
}
location: Location,
) -> bool {
let ty = ccx.body.local_decls[local].ty;
- if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
+ if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) {
return false;
}
let needs_drop = self.needs_drop.get_or_insert_with(|| {
let ConstCx { tcx, body, .. } = *ccx;
- FlowSensitiveAnalysis::new(NeedsDrop, ccx)
+ FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
.into_engine(tcx, &body)
.iterate_to_fixpoint()
.into_results_cursor(&body)
match pred.skip_binder() {
ty::ExistentialPredicate::AutoTrait(_)
| ty::ExistentialPredicate::Projection(_) => {
- self.check_op(ops::ty::TraitBound(kind))
+ self.check_op(ops::ty::DynTrait(kind))
}
ty::ExistentialPredicate::Trait(trait_ref) => {
if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
- self.check_op(ops::ty::TraitBound(kind))
+ self.check_op(ops::ty::DynTrait(kind))
}
}
}
}
}
- Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
Rvalue::UnaryOp(_, ref operand) => {
if is_lang_panic_fn(tcx, callee) {
self.check_op(ops::Panic);
+ // `begin_panic` and `panic_display` are generic functions that accept
+ // types other than str. Check to enforce that only str can be used in
+ // const-eval.
+
// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
}
}
+ // const-eval of the `panic_display` fn assumes the argument is `&&str`
+ if Some(callee) == tcx.lang_items().panic_display() {
+ match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+ ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
+ {}
+ _ => self.check_op(ops::PanicNonStr),
+ }
+ }
+
return;
}
let mut err_span = self.span;
- // Check to see if the type of this place can ever have a drop impl. If not, this
- // `Drop` terminator is frivolous.
- let ty_needs_drop =
- dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env);
+ let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
+ self.ccx,
+ dropped_place.ty(self.body, self.tcx).ty,
+ );
- if !ty_needs_drop {
+ if !ty_needs_non_const_drop {
return;
}
// Keep in sync with what that function handles!
Some(def_id) == tcx.lang_items().panic_fn()
|| Some(def_id) == tcx.lang_items().panic_str()
+ || Some(def_id) == tcx.lang_items().panic_display()
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
|| Some(def_id) == tcx.lang_items().panic_fmt()
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
- feature_err(
+ let mut err = feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound,
span,
"trait bounds other than `Sized` on const fn parameters are unstable",
- )
+ );
+
+ match ccx.fn_sig() {
+ Some(fn_sig) if !fn_sig.span.contains(span) => {
+ err.span_label(fn_sig.span, "function declared as const here");
+ }
+ _ => {}
+ }
+
+ err
+ }
+ }
+
+ #[derive(Debug)]
+ pub struct DynTrait(pub mir::LocalKind);
+ impl NonConstOp for DynTrait {
+ fn importance(&self) -> DiagnosticImportance {
+ match self.0 {
+ mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
+ mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
+ DiagnosticImportance::Primary
+ }
+ }
+ }
+
+ fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
+ if ccx.const_kind() != hir::ConstContext::ConstFn {
+ Status::Allowed
+ } else {
+ Status::Unstable(sym::const_fn_trait_bound)
+ }
+ }
+
+ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+ let mut err = feature_err(
+ &ccx.tcx.sess.parse_sess,
+ sym::const_fn_trait_bound,
+ span,
+ "trait objects in const fn are unstable",
+ );
+
+ match ccx.fn_sig() {
+ Some(fn_sig) if !fn_sig.span.contains(span) => {
+ err.span_label(fn_sig.span, "function declared as const here");
+ }
+ _ => {}
+ }
+
+ err
}
}
use super::check::Qualifs;
use super::ops::{self, NonConstOp};
-use super::qualifs::{NeedsDrop, Qualif};
+use super::qualifs::{NeedsNonConstDrop, Qualif};
use super::ConstCx;
/// Returns `true` if we should use the more precise live drop checker that runs after drop
match &terminator.kind {
mir::TerminatorKind::Drop { place: dropped_place, .. } => {
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
- if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
- bug!(
- "Drop elaboration left behind a Drop for a type that does not need dropping"
- );
+ if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
+ // Instead of throwing a bug, we just return here. This is because we have to
+ // run custom `const Drop` impls.
+ return;
}
if dropped_place.is_indirect() {
//! See the `Qualif` trait for more info.
use rustc_errors::ErrorReported;
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{
+ self, ImplSource, Obligation, ObligationCause, SelectionContext,
+};
use super::ConstCx;
) -> ConstQualifs {
ConstQualifs {
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
- needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
+ needs_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
error_occured,
}
/// This must be ruled out (a) because we cannot run `Drop` during compile-time
/// as that might not be a `const fn`, and (b) because implicit promotion would
/// remove side-effects that occur as part of dropping that value.
-pub struct NeedsDrop;
+pub struct NeedsNonConstDrop;
-impl Qualif for NeedsDrop {
- const ANALYSIS_NAME: &'static str = "flow_needs_drop";
+impl Qualif for NeedsNonConstDrop {
+ const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop";
const IS_CLEARED_ON_MOVE: bool = true;
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
qualifs.needs_drop
}
- fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
- ty.needs_drop(cx.tcx, cx.param_env)
+ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool {
+ // Avoid selecting for simple cases.
+ match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() {
+ Ok([]) => return false,
+ Err(ty::util::AlwaysRequiresDrop) => return true,
+ // If we've got a single component, select with that
+ // to increase the chance that we hit the selection cache.
+ Ok([t]) => ty = t,
+ Ok([..]) => {}
+ }
+
+ let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() {
+ did
+ } else {
+ // there is no way to define a type that needs non-const drop
+ // without having the lang item present.
+ return false;
+ };
+ let trait_ref =
+ ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) };
+ let obligation = Obligation::new(
+ ObligationCause::dummy(),
+ cx.param_env,
+ ty::Binder::dummy(ty::TraitPredicate {
+ trait_ref,
+ constness: ty::BoundConstness::ConstIfConst,
+ }),
+ );
+
+ let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
+ let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
+ selcx.select(&obligation)
+ });
+ match implsrc {
+ Ok(Some(ImplSource::ConstDrop(_)))
+ | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
+ _ => true,
+ }
}
fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
- adt.has_dtor(cx.tcx)
+ adt.has_non_const_dtor(cx.tcx)
}
}
// We cannot promote things that need dropping, since the promoted value
// would not get dropped.
- if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
+ if self.qualif_local::<qualifs::NeedsNonConstDrop>(place.local) {
return Err(Unpromotable);
}
Rvalue::NullaryOp(op, _) => match op {
NullOp::Box => return Err(Unpromotable),
NullOp::SizeOf => {}
+ NullOp::AlignOf => {}
},
Rvalue::UnaryOp(op, operand) => {
use rustc_middle::mir::{
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
- TerminatorKind,
+ TerminatorKind, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
}
fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
+ if bb == START_BLOCK {
+ self.fail(location, "start block must not have predecessors")
+ }
if let Some(bb) = self.body.basic_blocks().get(bb) {
let src = self.body.basic_blocks().get(location.block).unwrap();
match (src.is_cleanup, bb.is_cleanup, edge_kind) {
[package]
name = "rustc_data_structures"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
where
G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
{
- pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
- Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
+ pub fn new(graph: &'graph G) -> Self {
+ Self { graph, stack: vec![], visited: BitSet::new_empty(graph.num_nodes()) }
+ }
+
+ /// Version of `push_start_node` that is convenient for chained
+ /// use.
+ pub fn with_start_node(mut self, start_node: G::Node) -> Self {
+ self.push_start_node(start_node);
+ self
+ }
+
+ /// Pushes another start node onto the stack. If the node
+ /// has not already been visited, then you will be able to
+ /// walk its successors (and so forth) after the current
+ /// contents of the stack are drained. If multiple start nodes
+ /// are added into the walk, then their mutual successors
+ /// will all be walked. You can use this method once the
+ /// iterator has been completely drained to add additional
+ /// start nodes.
+ pub fn push_start_node(&mut self, start_node: G::Node) {
+ if self.visited.insert(start_node) {
+ self.stack.push(start_node);
+ }
+ }
+
+ /// Searches all nodes reachable from the current start nodes.
+ /// This is equivalent to just invoke `next` repeatedly until
+ /// you get a `None` result.
+ pub fn complete_search(&mut self) {
+ while let Some(_) = self.next() {}
+ }
+
+ /// Returns true if node has been visited thus far.
+ /// A node is considered "visited" once it is pushed
+ /// onto the internal stack; it may not yet have been yielded
+ /// from the iterator. This method is best used after
+ /// the iterator is completely drained.
+ pub fn visited(&self, node: G::Node) -> bool {
+ self.visited.contains(node)
+ }
+}
+
+impl<G> std::fmt::Debug for DepthFirstSearch<'_, G>
+where
+ G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut f = fmt.debug_set();
+ for n in self.visited.iter() {
+ f.entry(&n);
+ }
+ f.finish()
}
}
assert!(!is_cyclic(&diamond_acyclic));
assert!(is_cyclic(&diamond_cyclic));
}
+
+#[test]
+fn dfs() {
+ let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+
+ let result: Vec<usize> = DepthFirstSearch::new(&graph).with_start_node(0).collect();
+ assert_eq!(result, vec![0, 2, 3, 1]);
+}
+
+#[test]
+fn dfs_debug() {
+ let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+ let mut dfs = DepthFirstSearch::new(&graph).with_start_node(0);
+ dfs.complete_search();
+ assert_eq!(format!("{{0, 1, 2, 3}}"), format!("{:?}", dfs));
+}
where
Self: WithNumNodes,
{
- iterate::DepthFirstSearch::new(self, from)
+ iterate::DepthFirstSearch::new(self).with_start_node(from)
}
}
#![feature(extend_one)]
#![feature(hash_raw_entry)]
#![feature(in_band_lifetimes)]
-#![feature(iter_map_while)]
#![feature(maybe_uninit_uninit_array)]
#![feature(min_specialization)]
+#![feature(never_type)]
#![feature(type_alias_impl_trait)]
#![feature(new_uninit)]
#![feature(nll)]
use crate::fx::{FxHashMap, FxHasher};
use crate::sync::{Lock, LockGuard};
-use smallvec::SmallVec;
use std::borrow::Borrow;
use std::collections::hash_map::RawEntryMut;
use std::hash::{Hash, Hasher};
impl<T> Sharded<T> {
#[inline]
pub fn new(mut value: impl FnMut() -> T) -> Self {
- // Create a vector of the values we want
- let mut values: SmallVec<[_; SHARDS]> =
- (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect();
-
- // Create an uninitialized array
- let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> =
- mem::MaybeUninit::uninit();
-
- unsafe {
- // Copy the values into our array
- let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>;
- values.as_ptr().copy_to_nonoverlapping(first, SHARDS);
-
- // Ignore the content of the vector
- values.set_len(0);
-
- Sharded { shards: shards.assume_init() }
- }
+ Sharded { shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))) }
}
/// The shard is selected by hashing `val` with `FxHasher`.
impl_stable_hash_via_hash!(char);
impl_stable_hash_via_hash!(());
+impl<CTX> HashStable<CTX> for ! {
+ fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
+ unreachable!()
+ }
+}
+
impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.get().hash_stable(ctx, hasher)
[package]
name = "rustc_driver"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
crate-type = ["dylib"]
println!("{}", targets.join("\n"));
}
Sysroot => println!("{}", sess.sysroot.display()),
- TargetLibdir => println!(
- "{}",
- sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display()
- ),
+ TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
TargetSpec => println!("{}", sess.target.to_json().pretty()),
FileNames | CrateName => {
let input = input.unwrap_or_else(|| {
[package]
name = "rustc_error_codes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
For example, the code above can be fixed to:
```
-enum Foo {
- FirstValue(i32)
-}
+type U32 = u32;
+let t: U32 = 4;
+```
-fn main() {
- let u = Foo::FirstValue(0i32);
+or:
- let t = 4;
-}
+```
+struct U32 { value: u32 }
+let t = U32 { value: 4 };
```
+#### Note: this error code is no longer emitted by the compiler.
+
The length of the platform-intrinsic function `simd_shuffle` wasn't specified.
Erroneous code example:
-```compile_fail,E0439
+```ignore (no longer emitted)
#![feature(platform_intrinsics)]
extern "platform-intrinsic" {
[package]
name = "rustc_errors"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
}
+
+ pub fn content(&self) -> String {
+ self.0.iter().map(|x| x.content()).collect::<String>()
+ }
}
#[derive(Debug, PartialEq, Eq)]
Highlighted(String),
}
+impl StringPart {
+ pub fn content(&self) -> &str {
+ match self {
+ &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
+ }
+ }
+}
+
impl Diagnostic {
pub fn new(level: Level, message: &str) -> Self {
Diagnostic::new_with_code(level, None, message)
)
}
+ /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic.
+ /// In other words, multiple changes need to be applied as part of this suggestion.
+ pub fn multipart_suggestion_verbose(
+ &mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ self.multipart_suggestion_with_style(
+ msg,
+ suggestion,
+ applicability,
+ SuggestionStyle::ShowAlways,
+ )
+ }
/// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
pub fn multipart_suggestion_with_style(
&mut self,
self
}
+ /// See [`Diagnostic::multipart_suggestion()`].
+ pub fn multipart_suggestion_verbose(
+ &mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ if !self.0.allow_suggestions {
+ return self;
+ }
+ self.0.diagnostic.multipart_suggestion_verbose(msg, suggestion, applicability);
+ self
+ }
+
/// See [`Diagnostic::tool_only_multipart_suggestion()`].
pub fn tool_only_multipart_suggestion(
&mut self,
let mut error_codes = self
.emitted_diagnostic_codes
.iter()
- .filter_map(|x| {
- match &x {
+ .filter_map(|x| match &x {
DiagnosticId::Error(s)
- if let Ok(Some(_explanation)) = registry.try_find_description(s) =>
+ if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
{
Some(s.clone())
}
_ => None,
- }
})
.collect::<Vec<_>>();
if !error_codes.is_empty() {
[package]
name = "rustc_expand"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
build = false
[lib]
use rustc_attr::{self as attr, Deprecation, Stability};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
-use rustc_errors::{DiagnosticBuilder, ErrorReported};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported};
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::BuiltinLintDiagnostics;
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
use rustc_session::{parse::ParseSess, Limit, Session};
-use rustc_span::def_id::{CrateNum, DefId};
+use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
pub trait ResolverExpand {
fn next_node_id(&mut self) -> NodeId;
+ fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
fn resolve_dollar_crates(&mut self);
fn visit_ast_fragment_with_placeholders(
}
/// Extracts a string literal from the macro expanded version of `expr`,
-/// emitting `err_msg` if `expr` is not a string literal. This does not stop
-/// compilation on error, merely emits a non-fatal error and returns `None`.
+/// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
+/// The returned bool indicates whether an applicable suggestion has already been
+/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
+/// indicates that an ast error was encountered.
pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt<'_>,
expr: P<ast::Expr>,
err_msg: &str,
-) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> {
+) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> {
// Perform eager expansion on the expression.
// We want to be able to handle e.g., `concat!("foo", "bar")`.
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
Err(match expr.kind {
ast::ExprKind::Lit(ref l) => match l.kind {
ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
+ ast::LitKind::ByteStr(_) => {
+ let mut err = cx.struct_span_err(l.span, err_msg);
+ err.span_suggestion(
+ expr.span.shrink_to_lo(),
+ "consider removing the leading `b`",
+ String::new(),
+ Applicability::MaybeIncorrect,
+ );
+ Some((err, true))
+ }
ast::LitKind::Err(_) => None,
- _ => Some(cx.struct_span_err(l.span, err_msg)),
+ _ => Some((cx.struct_span_err(l.span, err_msg), false)),
},
ast::ExprKind::Err => None,
- _ => Some(cx.struct_span_err(expr.span, err_msg)),
+ _ => Some((cx.struct_span_err(expr.span, err_msg), false)),
})
}
+/// Extracts a string literal from the macro expanded version of `expr`,
+/// emitting `err_msg` if `expr` is not a string literal. This does not stop
+/// compilation on error, merely emits a non-fatal error and returns `None`.
pub fn expr_to_string(
cx: &mut ExtCtxt<'_>,
expr: P<ast::Expr>,
) -> Option<(Symbol, ast::StrStyle)> {
expr_to_spanned_string(cx, expr, err_msg)
.map_err(|err| {
- err.map(|mut err| {
+ err.map(|(mut err, _)| {
err.emit();
})
})
// Resolve `$crate`s in the fragment for pretty-printing.
self.cx.resolver.resolve_dollar_crates();
- let invocations = {
+ let mut invocations = {
let mut collector = InvocationCollector {
// Non-derive macro invocations cannot see the results of cfg expansion - they
// will either be removed along with the item, or invoked before the cfg/cfg_attr
self.cx
.resolver
.visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
+
+ if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
+ for (invoc, _) in invocations.iter_mut() {
+ let expn_id = invoc.expansion_data.id;
+ let parent_def = self.cx.resolver.invocation_parent(expn_id);
+ let span = match &mut invoc.kind {
+ InvocationKind::Bang { ref mut span, .. } => span,
+ InvocationKind::Attr { attr, .. } => &mut attr.span,
+ InvocationKind::Derive { path, .. } => &mut path.span,
+ };
+ *span = span.with_parent(Some(parent_def));
+ }
+ }
}
(fragment, invocations)
// `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
// See #78991 for an investigation of treating macros in this position
// as statements, rather than expressions, during parsing.
- if let StmtKind::Expr(expr) = &stmt.kind {
- if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) {
+ let res = match &stmt.kind {
+ StmtKind::Expr(expr)
+ if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) =>
+ {
self.cx.current_expansion.is_trailing_mac = true;
+ // Don't use `assign_id` for this statement - it may get removed
+ // entirely due to a `#[cfg]` on the contained expression
+ noop_flat_map_stmt(stmt, self)
}
- }
-
- let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self));
-
+ _ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)),
+ };
self.cx.current_expansion.is_trailing_mac = false;
res
}
// this with just `span.edition()`. A
// `SyntaxContext::root()` from the current crate will
// have the edition of the current crate, and a
- // `SyntaxxContext::root()` from a foreign crate will
+ // `SyntaxContext::root()` from a foreign crate will
// have the edition of that crate (which we manually
// retrieve via the `edition` parameter).
if span.ctxt() == SyntaxContext::root() {
self.sess.source_map().lookup_char_pos(span.lo()).file
}
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
- span.parent()
+ span.parent_callsite()
}
fn source(&mut self, span: Self::Span) -> Self::Span {
span.source_callsite()
let loc = self.sess.source_map().lookup_char_pos(span.hi());
LineColumn { line: loc.line, column: loc.col.to_usize() }
}
+ fn before(&mut self, span: Self::Span) -> Self::Span {
+ span.shrink_to_lo()
+ }
+ fn after(&mut self, span: Self::Span) -> Self::Span {
+ span.shrink_to_hi()
+ }
fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
[package]
name = "rustc_feature"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
since: $ver,
issue: to_nonzero($issue),
edition: None,
- description: concat!($($doc,)*),
}
),+
];
since: $ver,
issue: to_nonzero($issue),
edition: $edition,
- description: concat!($($doc,)*),
}
),+];
/// Allows specifying the as-needed link modifier
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
- /// Allows unnamed fields of struct and union type
- (incomplete, unnamed_fields, "1.53.0", Some(49804), None),
-
/// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
(active, more_qualified_paths, "1.54.0", Some(86935), None),
),
// Enumerates "identity-like" conversion methods to suggest on type mismatch.
rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE),
+ // Prevents field reads in the marked trait or method to be considered
+ // during dead code analysis.
+ rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE),
// ==========================================================================
// Internal attributes, Const related:
pub since: &'static str,
issue: Option<NonZeroU32>,
pub edition: Option<Edition>,
- description: &'static str,
}
#[derive(Copy, Clone, Debug)]
since: $ver,
issue: to_nonzero($issue),
edition: None,
- description: concat!($($doc,)*),
}
),+
];
since: $ver,
issue: to_nonzero($issue),
edition: None,
- description: concat!($($doc,)*),
}
),+
];
[package]
name = "rustc_fs_util"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[package]
name = "rustc_graphviz"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[package]
name = "rustc_hir"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
rustc_ast = { path = "../rustc_ast" }
tracing = "0.1"
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+odht = { version = "0.3.0", features = ["nightly"] }
[] pat_field: rustc_hir::PatField<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
- [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
+ [few] foreign_item_ref: rustc_hir::ForeignItemRef,
[] impl_item: rustc_hir::ImplItem<$tcx>,
- [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+ [] impl_item_ref: rustc_hir::ImplItemRef,
[] item: rustc_hir::Item<$tcx>,
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
}
}
+ #[track_caller]
+ pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {
+ self.map_id(|_| panic!("unexpected `Res::Local`"))
+ }
+
pub fn macro_kind(self) -> Option<MacroKind> {
match self {
Res::Def(DefKind::Macro(kind), _) => Some(kind),
--- /dev/null
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_span::def_id::{DefIndex, DefPathHash};
+
+#[derive(Clone, Default)]
+pub struct Config;
+
+impl odht::Config for Config {
+ type Key = DefPathHash;
+ type Value = DefIndex;
+
+ type EncodedKey = [u8; 16];
+ type EncodedValue = [u8; 4];
+
+ type H = odht::UnHashFn;
+
+ #[inline]
+ fn encode_key(k: &DefPathHash) -> [u8; 16] {
+ k.0.to_le_bytes()
+ }
+
+ #[inline]
+ fn encode_value(v: &DefIndex) -> [u8; 4] {
+ v.as_u32().to_le_bytes()
+ }
+
+ #[inline]
+ fn decode_key(k: &[u8; 16]) -> DefPathHash {
+ DefPathHash(Fingerprint::from_le_bytes(*k))
+ }
+
+ #[inline]
+ fn decode_value(v: &[u8; 4]) -> DefIndex {
+ DefIndex::from_u32(u32::from_le_bytes(*v))
+ }
+}
+
+pub type DefPathHashMap = odht::HashTableOwned<Config>;
pub use crate::def_id::DefPathHash;
use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_path_hash_map::DefPathHashMap;
use crate::hir;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::unhash::UnhashMap;
use rustc_index::vec::IndexVec;
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
use std::fmt::{self, Write};
use std::hash::Hash;
pub struct DefPathTable {
index_to_key: IndexVec<DefIndex, DefKey>,
def_path_hashes: IndexVec<DefIndex, DefPathHash>,
- def_path_hash_to_index: UnhashMap<DefPathHash, DefIndex>,
+ def_path_hash_to_index: DefPathHashMap,
}
impl DefPathTable {
// Check for hash collisions of DefPathHashes. These should be
// exceedingly rare.
- if let Some(existing) = self.def_path_hash_to_index.insert(def_path_hash, index) {
+ if let Some(existing) = self.def_path_hash_to_index.insert(&def_path_hash, &index) {
let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
pub fn enumerated_keys_and_path_hashes(
&self,
- ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ {
+ ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + ExactSizeIterator + '_ {
self.index_to_key
.iter_enumerated()
.map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+
+ def_id_to_span: IndexVec<LocalDefId, Span>,
+
+ /// The [StableCrateId] of the local crate.
+ stable_crate_id: StableCrateId,
}
/// A unique identifier that we can use to lookup a definition
}
/// Adds a root definition (no parent) and a few other reserved definitions.
- pub fn new(stable_crate_id: StableCrateId) -> Definitions {
+ pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions {
let key = DefKey {
parent: None,
disambiguated_data: DisambiguatedDefPathData {
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
+ let mut def_id_to_span = IndexVec::new();
+ // A relative span's parent must be an absolute span.
+ debug_assert_eq!(crate_span.data_untracked().parent, None);
+ let _root = def_id_to_span.push(crate_span);
+ debug_assert_eq!(_root, root);
+
Definitions {
table,
def_id_to_hir_id: Default::default(),
hir_id_to_def_id: Default::default(),
expansions_that_defined: Default::default(),
+ def_id_to_span,
+ stable_crate_id,
}
}
data: DefPathData,
expn_id: ExpnId,
mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32,
+ span: Span,
) -> LocalDefId {
debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id);
self.expansions_that_defined.insert(def_id, expn_id);
}
+ // A relative span's parent must be an absolute span.
+ debug_assert_eq!(span.data_untracked().parent, None);
+ let _id = self.def_id_to_span.push(span);
+ debug_assert_eq!(_id, def_id);
+
def_id
}
self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
}
+ /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
+ #[inline]
+ pub fn def_span(&self, def_id: LocalDefId) -> Span {
+ self.def_id_to_span[def_id]
+ }
+
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
}
#[inline(always)]
- pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
+ pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> LocalDefId {
+ debug_assert!(hash.stable_crate_id() == self.stable_crate_id);
self.table
.def_path_hash_to_index
.get(&hash)
- .map(|&local_def_index| LocalDefId { local_def_index })
+ .map(|local_def_index| LocalDefId { local_def_index })
+ .unwrap()
+ }
+
+ pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
+ &self.table.def_path_hash_to_index
}
}
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::BTreeMap;
use std::fmt;
#[derive(Copy, Clone, Encodable, HashStable_Generic)]
pub rhs_ty: &'hir Ty<'hir>,
}
-#[derive(Default, Encodable, Debug, HashStable_Generic)]
-pub struct ModuleItems {
- // Use BTreeSets here so items are in the same order as in the
- // list of all items in Crate
- pub items: BTreeSet<ItemId>,
- pub trait_items: BTreeSet<TraitItemId>,
- pub impl_items: BTreeSet<ImplItemId>,
- pub foreign_items: BTreeSet<ForeignItemId>,
-}
-
/// The top-level data structure that stores the entire contents of
/// the crate currently being compiled.
///
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
- /// A list of modules written out in the order in which they
- /// appear in the crate. This includes the main crate module.
- pub modules: BTreeMap<LocalDefId, ModuleItems>,
-
/// Map indicating what traits are in scope for places where this
/// is relevant; generated by resolve.
pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
/// A module.
Mod(Mod<'hir>),
/// An external module, e.g. `extern { .. }`.
- ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
+ ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] },
/// Module-level inline assembly (from `global_asm!`).
GlobalAsm(&'hir InlineAsm<'hir>),
/// A type alias, e.g., `type Foo = Bar<u8>`.
pub of_trait: Option<TraitRef<'hir>>,
pub self_ty: &'hir Ty<'hir>,
- pub items: &'hir [ImplItemRef<'hir>],
+ pub items: &'hir [ImplItemRef],
}
impl ItemKind<'_> {
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Debug, HashStable_Generic)]
-pub struct ImplItemRef<'hir> {
+pub struct ImplItemRef {
pub id: ImplItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub kind: AssocItemKind,
pub span: Span,
- pub vis: Visibility<'hir>,
pub defaultness: Defaultness,
}
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Debug, HashStable_Generic)]
-pub struct ForeignItemRef<'hir> {
+pub struct ForeignItemRef {
pub id: ForeignItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub span: Span,
- pub vis: Visibility<'hir>,
}
#[derive(Debug)]
}
}
- /// Returns `Constness::Const` when this node is a const fn/impl/item,
- ///
- /// HACK(fee1-dead): or an associated type in a trait. This works because
- /// only typeck cares about const trait predicates, so although the predicates
- /// query would return const predicates when it does not need to be const,
- /// it wouldn't have any effect.
+ /// Returns `Constness::Const` when this node is a const fn/impl/item.
pub fn constness_for_typeck(&self) -> Constness {
match self {
Node::Item(Item {
Node::Item(Item { kind: ItemKind::Const(..), .. })
| Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
- | Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
_ => Constness::NotConst,
fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
walk_impl_item(self, ii)
}
- fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
+ fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) {
walk_foreign_item_ref(self, ii)
}
- fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
+ fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) {
walk_impl_item_ref(self, ii)
}
fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) {
pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
- foreign_item_ref: &'v ForeignItemRef<'v>,
+ foreign_item_ref: &'v ForeignItemRef,
) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
+ let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
visitor.visit_nested_foreign_item(id);
visitor.visit_ident(ident);
- visitor.visit_vis(vis);
}
-pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
+pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
+ let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref;
visitor.visit_nested_impl_item(id);
visitor.visit_ident(ident);
visitor.visit_associated_item_kind(kind);
- visitor.visit_vis(vis);
visitor.visit_defaultness(defaultness);
}
// a weak lang item, but do not have it defined.
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
+ PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
mod arena;
pub mod def;
+pub mod def_path_hash_map;
pub mod definitions;
pub use rustc_span::def_id;
mod hir;
[package]
name = "rustc_hir_pretty"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
self.maybe_print_comment(st.span.lo());
match st.kind {
hir::StmtKind::Local(ref loc) => {
- self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc));
+ self.print_local(loc.init, |this| this.print_local_decl(&loc));
}
hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
hir::StmtKind::Expr(ref expr) => {
[package]
name = "rustc_incremental"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_index"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_infer"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>,
) -> DiagnosticBuilder<'tcx> {
+ use crate::traits::ObligationCauseCode::MatchExpressionArm;
+
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
let span = trace.cause.span(self.tcx);
_ => {}
}
}
+ if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
+ trace.cause.code
+ {
+ if let hir::MatchSource::TryDesugar = source {
+ if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
+ err.note(&format!(
+ "`?` operator cannot convert from `{}` to `{}`",
+ found_ty.content(),
+ expected_ty.content(),
+ ));
+ }
+ }
+ }
err
}
FailureCode::Error0644(failure_str) => {
);
err.span_suggestion(
generics.where_clause.tail_span_for_suggestion(),
- "consider adding a where clause".into(),
+ "consider adding a where clause",
suggestion,
Applicability::MaybeIncorrect,
);
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
Error0308(match source {
- hir::MatchSource::TryDesugar => {
- "try expression alternatives have incompatible types"
- }
+ hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
_ => "`match` arms have incompatible types",
})
}
SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause,
_ => return None,
};
- let (parent, impl_def_id) = match &cause.code {
+ // If we added a "points at argument expression" obligation, we remove it here, we care
+ // about the original obligation only.
+ let code = match &cause.code {
+ ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
+ _ => &cause.code,
+ };
+ let (parent, impl_def_id) = match code {
ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
_ => return None,
};
- let binding_span = match **parent {
+ let binding_span = match parent.code {
ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span,
_ => return None,
};
}
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
let code = match &cause.code {
- ObligationCauseCode::MatchImpl(parent, ..) => &**parent,
+ ObligationCauseCode::MatchImpl(parent, ..) => &parent.code,
_ => &cause.code,
};
if let ObligationCauseCode::ItemObligation(item_def_id) = *code {
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
+use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::{MultiSpan, Span};
+use rustc_span::{MultiSpan, Span, Symbol};
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
- if let Some(ref error) = self.error {
- debug!("try_report_impl_not_conforming_to_trait {:?}", error);
- if let RegionResolutionError::SubSupConflict(
- _,
- var_origin,
- sub_origin,
- _sub,
- sup_origin,
- _sup,
- ) = error.clone()
- {
- if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
- (&sup_origin, &sub_origin)
+ let error = self.error.as_ref()?;
+ debug!("try_report_impl_not_conforming_to_trait {:?}", error);
+ if let RegionResolutionError::SubSupConflict(
+ _,
+ var_origin,
+ sub_origin,
+ _sub,
+ sup_origin,
+ _sup,
+ ) = error.clone()
+ {
+ if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
+ if let (
+ ValuePairs::Types(sub_expected_found),
+ ValuePairs::Types(sup_expected_found),
+ CompareImplMethodObligation { trait_item_def_id, .. },
+ ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
{
- if let (
- ValuePairs::Types(sub_expected_found),
- ValuePairs::Types(sup_expected_found),
- CompareImplMethodObligation { trait_item_def_id, .. },
- ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
- {
- if sup_expected_found == sub_expected_found {
- self.emit_err(
- var_origin.span(),
- sub_expected_found.expected,
- sub_expected_found.found,
- *trait_item_def_id,
- );
- return Some(ErrorReported);
- }
+ if sup_expected_found == sub_expected_found {
+ self.emit_err(
+ var_origin.span(),
+ sub_expected_found.expected,
+ sub_expected_found.found,
+ *trait_item_def_id,
+ );
+ return Some(ErrorReported);
}
}
}
}
+ if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
+ if let SubregionOrigin::CompareImplTypeObligation {
+ span,
+ item_name,
+ impl_item_def_id,
+ trait_item_def_id,
+ } = origin
+ {
+ self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
+ return Some(ErrorReported);
+ }
+ }
None
}
}
err.emit();
}
+
+ fn emit_associated_type_err(
+ &self,
+ span: Span,
+ item_name: Symbol,
+ impl_item_def_id: DefId,
+ trait_item_def_id: DefId,
+ ) {
+ let impl_sp = self.tcx().def_span(impl_item_def_id);
+ let trait_sp = self.tcx().def_span(trait_item_def_id);
+ let mut err = self
+ .tcx()
+ .sess
+ .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
+ err.span_label(impl_sp, &format!("found"));
+ err.span_label(trait_sp, &format!("expected"));
+
+ err.emit();
+ }
}
struct TypeParamSpanVisitor<'tcx> {
"...so that the definition in impl matches the definition from the trait",
);
}
+ infer::CompareImplTypeObligation { span, .. } => {
+ label_or_note(
+ span,
+ "...so that the definition in impl matches the definition from the trait",
+ );
+ }
}
}
trait_item_def_id,
&format!("`{}: {}`", sup, sub),
),
+ infer::CompareImplTypeObligation {
+ span,
+ item_name,
+ impl_item_def_id,
+ trait_item_def_id,
+ } => self.report_extra_impl_obligation(
+ span,
+ item_name,
+ impl_item_def_id,
+ trait_item_def_id,
+ &format!("`{}: {}`", sup, sub),
+ ),
}
}
pub mod nll_relate;
pub mod opaque_types;
pub mod outlives;
+mod projection;
pub mod region_constraints;
pub mod resolve;
mod sub;
impl_item_def_id: DefId,
trait_item_def_id: DefId,
},
+
+ /// Comparing the signature and requirements of an impl associated type
+ /// against the containing trait
+ CompareImplTypeObligation {
+ span: Span,
+ item_name: Symbol,
+ impl_item_def_id: DefId,
+ trait_item_def_id: DefId,
+ },
}
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
ReferenceOutlivesReferent(_, a) => a,
CallReturn(a) => a,
CompareImplMethodObligation { span, .. } => span,
+ CompareImplTypeObligation { span, .. } => span,
}
}
trait_item_def_id,
},
+ traits::ObligationCauseCode::CompareImplTypeObligation {
+ item_name,
+ impl_item_def_id,
+ trait_item_def_id,
+ } => SubregionOrigin::CompareImplTypeObligation {
+ span: cause.span,
+ item_name,
+ impl_item_def_id,
+ trait_item_def_id,
+ },
+
_ => default(),
}
}
let old_ambient_variance = self.ambient_variance;
self.ambient_variance = self.ambient_variance.xform(variance);
- self.ambient_variance_info = self.ambient_variance_info.clone().xform(info);
+ self.ambient_variance_info = self.ambient_variance_info.xform(info);
debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
if self.ambient_covariance() {
// Covariance: a <= b. Hence, `b: a`.
- self.push_outlives(v_b, v_a, self.ambient_variance_info.clone());
+ self.push_outlives(v_b, v_a, self.ambient_variance_info);
}
if self.ambient_contravariance() {
// Contravariant: b <= a. Hence, `a: b`.
- self.push_outlives(v_a, v_b, self.ambient_variance_info.clone());
+ self.push_outlives(v_a, v_b, self.ambient_variance_info);
}
Ok(a)
--- /dev/null
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::{self, ToPredicate, Ty};
+
+use crate::traits::{Obligation, PredicateObligation};
+
+use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use super::InferCtxt;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+ /// Instead of normalizing an associated type projection,
+ /// this function generates an inference variable and registers
+ /// an obligation that this inference variable must be the result
+ /// of the given projection. This allows us to proceed with projections
+ /// while they cannot be resolved yet due to missing information or
+ /// simply due to the lack of access to the trait resolution machinery.
+ pub fn infer_projection(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ projection_ty: ty::ProjectionTy<'tcx>,
+ cause: ObligationCause<'tcx>,
+ recursion_depth: usize,
+ obligations: &mut Vec<PredicateObligation<'tcx>>,
+ ) -> Ty<'tcx> {
+ let def_id = projection_ty.item_def_id;
+ let ty_var = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::NormalizeProjectionType,
+ span: self.tcx.def_span(def_id),
+ });
+ let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
+ let obligation = Obligation::with_depth(
+ cause,
+ recursion_depth,
+ param_env,
+ projection.to_predicate(self.tcx),
+ );
+ obligations.push(obligation);
+ ty_var
+ }
+}
messages.push(msg.clone());
}
}
- if trait_span.is_some() {
- // Only provide the help if its a local trait, otherwise it's not actionable.
- violation.solution(&mut err);
- }
}
}
let has_multi_span = !multi_span.is_empty();
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
+ if trait_span.is_some() {
+ let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
+ reported_violations.sort();
+ for violation in reported_violations {
+ // Only provide the help if its a local trait, otherwise it's not actionable.
+ violation.solution(&mut err);
+ }
+ }
err
}
pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx>,
- /// Diagnostics only: we opportunistically change the `code.span` when we encounter an
- /// obligation error caused by a call argument. When this is the case, we also signal that in
- /// this field to ensure accuracy of suggestions.
- pub points_at_arg_span: bool,
/// Diagnostics only: the 'root' obligation which resulted in
/// the failure to process `obligation`. This is the obligation
/// that was initially passed to `register_predicate_obligation`
code: FulfillmentErrorCode<'tcx>,
root_obligation: PredicateObligation<'tcx>,
) -> FulfillmentError<'tcx> {
- FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation }
+ FulfillmentError { obligation, code, root_obligation }
}
}
assert!(!fresh_key, "never started projecting `{:?}`", key);
}
- /// Mark the relevant projection cache key as having its derived obligations
- /// complete, so they won't have to be re-computed (this is OK to do in a
- /// snapshot - if the snapshot is rolled back, the obligations will be
- /// marked as incomplete again).
- pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) {
- let mut map = self.map();
- let ty = match map.get(&key) {
- Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => {
- debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
- ty.value
- }
- ref value => {
- // Type inference could "strand behind" old cache entries. Leave
- // them alone for now.
- debug!("ProjectionCacheEntry::complete({:?}) - ignoring {:?}", key, value);
- return;
- }
- };
-
- map.insert(
- key,
- ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }),
- );
- }
-
- /// A specialized version of `complete` for when the key's value is known
- /// to be a NormalizedTy.
- pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) {
- // We want to insert `ty` with no obligations. If the existing value
- // already has no obligations (as is common) we don't insert anything.
- if !ty.obligations.is_empty() {
- self.map().insert(
- key,
- ProjectionCacheEntry::NormalizedTy(Normalized {
- value: ty.value,
- obligations: vec![],
- }),
- );
- }
- }
-
/// Indicates that trying to normalize `key` resulted in
/// ambiguity. No point in trying it again then until we gain more
/// type information (in which case, the "fully resolved" key will
[package]
name = "rustc_interface"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
})
}
+fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
+ tls::with_opt(|tcx| {
+ if let Some(tcx) = tcx {
+ let _span = tcx.source_span(def_id);
+ // Sanity check: relative span's parent must be an absolute span.
+ debug_assert_eq!(_span.data_untracked().parent, None);
+ }
+ })
+}
+
/// This is a callback from `rustc_ast` as it cannot access the implicit state
/// in `rustc_middle` otherwise. It is used to when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
/// TyCtxt in.
pub fn setup_callbacks() {
rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+ rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
}
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
-use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
CStore::from_tcx(tcx).report_unused_deps(tcx);
},
{
- par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+ tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_loops(module);
tcx.ensure().check_mod_attrs(module);
tcx.ensure().check_mod_naked_functions(module);
},
{
sess.time("liveness_and_intrinsic_checking", || {
- par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+ tcx.hir().par_for_each_module(|module| {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
},
{
sess.time("privacy_checking_modules", || {
- par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+ tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_privacy(module);
});
});
tracked!(no_profiler_runtime, true);
tracked!(osx_rpath_install_name, true);
tracked!(panic_abort_tests, true);
+ tracked!(panic_in_drop, PanicStrategy::Abort);
tracked!(partially_uninit_const_threshold, Some(123));
tracked!(plt, Some(true));
tracked!(polonius, true);
tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
+ tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
tracked!(report_delayed_bugs, true);
tracked!(sanitizer, SanitizerSet::ADDRESS);
let result_ptr = Ptr(&mut result as *mut _ as *mut ());
let thread = cfg.spawn(move || {
+ let _ = (&run, &result_ptr);
let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() };
let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) };
*result = Some(run());
name = "rustc_lexer"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
repository = "https://github.com/rust-lang/rust/"
description = """
[package]
name = "rustc_lint"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
if_chain = "1.0"
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// # #![allow(unused)]
/// [1, 2, 3].into_iter().for_each(|n| { *n; });
/// ```
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// let x = 123;
/// match x {
/// 0...100 => {}
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
use rustc_ast as ast;
-use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
+use rustc_data_structures::sync::join;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit as hir_visit;
|| {
tcx.sess.time("module_lints", || {
// Run per-module lints
- par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
- tcx.ensure().lint_mod(module);
- });
+ tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
});
},
);
///
/// ### Example
///
- /// ```rust,no_run
+ /// ```rust,no_run,edition2018
/// panic!("{}");
/// panic!(123);
/// ```
impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+ use rustc_middle::ty;
use rustc_middle::ty::PredicateKind::*;
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
Trait(trait_predicate) => trait_predicate,
_ => continue,
};
+ if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
+ // `~const Drop` definitely have meanings so avoid linting here.
+ continue;
+ }
let def_id = trait_predicate.trait_ref.def_id;
if cx.tcx.lang_items().drop_trait() == Some(def_id) {
// Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern.
use FfiResult::*;
if def.repr.transparent() {
- // Can assume that only one field is not a ZST, so only check
+ // Can assume that at most one field is not a ZST, so only check
// that field's type for FFI-safety.
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
self.check_field_type_for_ffi(cache, field, substs)
} else {
- bug!("malformed transparent type");
+ // All fields are ZSTs; this means that the type should behave
+ // like (), which is FFI-unsafe
+ FfiUnsafe {
+ ty,
+ reason: "this struct contains only zero-sized fields".into(),
+ help: None,
+ }
}
} else {
// We can't completely trust repr(C) markings; make sure the fields are
};
let (variants, tag) = match layout.variants {
Variants::Multiple {
- tag_encoding: TagEncoding::Direct,
- ref tag,
- ref variants,
- ..
+ tag_encoding: TagEncoding::Direct, tag, ref variants, ..
} => (variants, tag),
_ => return,
};
use rustc_ast as ast;
use rustc_ast::util::{classify, parser};
use rustc_ast::{ExprKind, StmtKind};
-use rustc_ast_pretty::pprust;
use rustc_errors::{pluralize, Applicability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{kw, sym};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
declare_lint! {
/// The `unused_must_use` lint detects unused result of a type flagged as
left_pos: Option<BytePos>,
right_pos: Option<BytePos>,
) {
- let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
- snippet
- } else {
- pprust::expr_to_string(value)
+ let spans = match value.kind {
+ ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
+ let start = block.stmts[0].span;
+ let end = block.stmts[block.stmts.len() - 1].span;
+ if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
+ (
+ value.span.with_hi(value.span.lo() + BytePos(1)),
+ value.span.with_lo(value.span.hi() - BytePos(1)),
+ )
+ } else {
+ (value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
+ }
+ }
+ ast::ExprKind::Paren(ref expr) => {
+ if value.span.from_expansion() || expr.span.from_expansion() {
+ (
+ value.span.with_hi(value.span.lo() + BytePos(1)),
+ value.span.with_lo(value.span.hi() - BytePos(1)),
+ )
+ } else {
+ (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
+ }
+ }
+ _ => return,
};
let keep_space = (
left_pos.map_or(false, |s| s >= value.span.lo()),
right_pos.map_or(false, |s| s <= value.span.hi()),
);
- self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
+ self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
}
fn emit_unused_delims(
&self,
cx: &EarlyContext<'_>,
- span: Span,
- pattern: &str,
+ spans: (Span, Span),
msg: &str,
keep_space: (bool, bool),
) {
// FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
// properly.
- if span == DUMMY_SP {
+ if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
return;
}
- cx.struct_span_lint(self.lint(), span, |lint| {
+ cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
let mut err = lint.build(&span_msg);
- let mut ate_left_paren = false;
- let mut ate_right_paren = false;
- let parens_removed = pattern
- .trim_matches(|c| match c {
- '(' | '{' => {
- if ate_left_paren {
- false
- } else {
- ate_left_paren = true;
- true
- }
- }
- ')' | '}' => {
- if ate_right_paren {
- false
- } else {
- ate_right_paren = true;
- true
- }
- }
- _ => false,
- })
- .trim();
-
- let replace = {
- let mut replace = if keep_space.0 {
- let mut s = String::from(" ");
- s.push_str(parens_removed);
- s
- } else {
- String::from(parens_removed)
- };
-
- if keep_space.1 {
- replace.push(' ');
- }
- replace
- };
-
+ let replacement = vec![
+ (spans.0, if keep_space.0 { " ".into() } else { "".into() }),
+ (spans.1, if keep_space.1 { " ".into() } else { "".into() }),
+ ];
let suggestion = format!("remove these {}", Self::DELIM_STR);
-
- err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable);
+ err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable);
err.emit();
});
}
// Otherwise proceed with linting.
_ => {}
}
-
- let pattern_text =
- if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
- snippet
- } else {
- pprust::pat_to_string(value)
- };
- self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false));
+ let spans = if value.span.from_expansion() || inner.span.from_expansion() {
+ (
+ value.span.with_hi(value.span.lo() + BytePos(1)),
+ value.span.with_lo(value.span.hi() - BytePos(1)),
+ )
+ } else {
+ (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
+ };
+ self.emit_unused_delims(cx, spans, "pattern", (false, false));
}
}
}
);
}
_ => {
- let pattern_text =
- if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) {
- snippet
- } else {
- pprust::ty_to_string(ty)
- };
-
- self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false));
+ let spans = if ty.span.from_expansion() || r.span.from_expansion() {
+ (
+ ty.span.with_hi(ty.span.lo() + BytePos(1)),
+ ty.span.with_lo(ty.span.hi() - BytePos(1)),
+ )
+ } else {
+ (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
+ };
+ self.emit_unused_delims(cx, spans, "type", (false, false));
}
}
}
[package]
name = "rustc_lint_defs"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_ast = { path = "../rustc_ast" }
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// trait Trait { }
///
/// fn takes_trait_object(_: Box<Trait>) {
UNSUPPORTED_CALLING_CONVENTIONS,
BREAK_WITH_LABEL_AND_LOOP,
UNUSED_ATTRIBUTES,
+ NON_EXHAUSTIVE_OMITTED_PATTERNS,
]
}
///
/// ### Example
///
- /// ```rust,compile_fail
+ /// ```rust,edition2018,compile_fail
/// #![deny(rust_2021_prefixes_incompatible_syntax)]
///
/// macro_rules! m {
///
/// This lint suggests to add whitespace between the `z` and `"hey"` tokens
/// to keep them separated in Rust 2021.
+ // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser.
+ #[allow(rustdoc::invalid_rust_codeblocks)]
pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
Allow,
"identifiers that will be parsed as a prefix in Rust 2021",
Warn,
"`break` expression with label and unlabeled loop as value expression"
}
+
+declare_lint! {
+ /// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a
+ /// pattern for a `#[non_exhaustive]` struct or enum is reachable.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,ignore (needs separate crate)
+ /// // crate A
+ /// #[non_exhaustive]
+ /// pub enum Bar {
+ /// A,
+ /// B, // added variant in non breaking change
+ /// }
+ ///
+ /// // in crate B
+ /// match Bar::A {
+ /// Bar::A => {},
+ /// #[warn(non_exhaustive_omitted_patterns)]
+ /// _ => {},
+ /// }
+ /// ```
+ ///
+ /// This will produce:
+ ///
+ /// ```text
+ /// warning: reachable patterns not covered of non exhaustive enum
+ /// --> $DIR/reachable-patterns.rs:70:9
+ /// |
+ /// LL | _ => {}
+ /// | ^ pattern `B` not covered
+ /// |
+ /// note: the lint level is defined here
+ /// --> $DIR/reachable-patterns.rs:69:16
+ /// |
+ /// LL | #[warn(non_exhaustive_omitted_patterns)]
+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// = help: ensure that all possible cases are being handled by adding the suggested match arms
+ /// = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found
+ /// ```
+ ///
+ /// ### Explanation
+ ///
+ /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a
+ /// (potentially redundant) wildcard when pattern-matching, to allow for future
+ /// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint
+ /// detects when such a wildcard happens to actually catch some fields/variants.
+ /// In other words, when the match without the wildcard would not be exhaustive.
+ /// This lets the user be informed if new fields/variants were added.
+ pub NON_EXHAUSTIVE_OMITTED_PATTERNS,
+ Allow,
+ "detect when patterns of types marked `non_exhaustive` are missed",
+}
[package]
name = "rustc_llvm"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[features]
static-libstdcpp = []
"aarch64",
"amdgpu",
"avr",
+ "m68k",
"mips",
"powerpc",
"systemz",
#define SUBTARGET_AVR
#endif
+#ifdef LLVM_COMPONENT_M68k
+#define SUBTARGET_M68K SUBTARGET(M68k)
+#else
+#define SUBTARGET_M68K
+#endif
+
#ifdef LLVM_COMPONENT_MIPS
#define SUBTARGET_MIPS SUBTARGET(Mips)
#else
SUBTARGET_ARM \
SUBTARGET_AARCH64 \
SUBTARGET_AVR \
+ SUBTARGET_M68K \
SUBTARGET_MIPS \
SUBTARGET_PPC \
SUBTARGET_SYSTEMZ \
#if LLVM_VERSION_GE(11, 0)
OptimizerLastEPCallbacks.push_back(
[Options](ModulePassManager &MPM, OptimizationLevel Level) {
+#if LLVM_VERSION_GE(14, 0)
+ MPM.addPass(ModuleMemorySanitizerPass(Options));
+#else
MPM.addPass(MemorySanitizerPass(Options));
+#endif
MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
}
);
#if LLVM_VERSION_GE(11, 0)
OptimizerLastEPCallbacks.push_back(
[](ModulePassManager &MPM, OptimizationLevel Level) {
+#if LLVM_VERSION_GE(14, 0)
+ MPM.addPass(ModuleThreadSanitizerPass());
+#else
MPM.addPass(ThreadSanitizerPass());
+#endif
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
}
);
report_fatal_error("bad AttributeKind");
}
+template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
+#if LLVM_VERSION_LT(14, 0)
+ t->addAttribute(Index, Attr);
+#else
+ t->addAttributeAtIndex(Index, Attr);
+#endif
+}
+
extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
LLVMRustAttribute RustAttr) {
CallBase *Call = unwrap<CallBase>(Instr);
Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
- Call->addAttribute(Index, Attr);
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
const char *Name) {
CallBase *Call = unwrap<CallBase>(Instr);
Attribute Attr = Attribute::get(Call->getContext(), Name);
- Call->addAttribute(Index, Attr);
+ AddAttribute(Call, Index, Attr);
}
-
extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
unsigned Index,
uint32_t Bytes) {
CallBase *Call = unwrap<CallBase>(Instr);
- AttrBuilder B;
- B.addAlignmentAttr(Bytes);
- Call->setAttributes(Call->getAttributes().addAttributes(
- Call->getContext(), Index, B));
+ Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
unsigned Index,
uint64_t Bytes) {
CallBase *Call = unwrap<CallBase>(Instr);
- AttrBuilder B;
- B.addDereferenceableAttr(Bytes);
- Call->setAttributes(Call->getAttributes().addAttributes(
- Call->getContext(), Index, B));
+ Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
unsigned Index,
uint64_t Bytes) {
CallBase *Call = unwrap<CallBase>(Instr);
- AttrBuilder B;
- B.addDereferenceableOrNullAttr(Bytes);
- Call->setAttributes(Call->getAttributes().addAttributes(
- Call->getContext(), Index, B));
+ Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
LLVMTypeRef Ty) {
CallBase *Call = unwrap<CallBase>(Instr);
Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
- Call->addAttribute(Index, Attr);
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
#else
Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
#endif
- Call->addAttribute(Index, Attr);
+ AddAttribute(Call, Index, Attr);
}
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
LLVMRustAttribute RustAttr) {
Function *A = unwrap<Function>(Fn);
Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
- A->addAttribute(Index, Attr);
+ AddAttribute(A, Index, Attr);
}
extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
unsigned Index,
uint32_t Bytes) {
Function *A = unwrap<Function>(Fn);
- A->addAttribute(Index, Attribute::getWithAlignment(
+ AddAttribute(A, Index, Attribute::getWithAlignment(
A->getContext(), llvm::Align(Bytes)));
}
extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
uint64_t Bytes) {
Function *A = unwrap<Function>(Fn);
- A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(),
+ AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
Bytes));
}
unsigned Index,
uint64_t Bytes) {
Function *A = unwrap<Function>(Fn);
- A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes(
+ AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
A->getContext(), Bytes));
}
LLVMTypeRef Ty) {
Function *F = unwrap<Function>(Fn);
Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
- F->addAttribute(Index, Attr);
+ AddAttribute(F, Index, Attr);
}
extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
#else
Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet);
#endif
- F->addAttribute(Index, Attr);
+ AddAttribute(F, Index, Attr);
}
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
const char *Name,
const char *Value) {
Function *F = unwrap<Function>(Fn);
- F->addAttribute(Index, Attribute::get(
+ AddAttribute(F, Index, Attribute::get(
F->getContext(), StringRef(Name), StringRef(Value)));
}
Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
AttrBuilder B(Attr);
auto PAL = F->getAttributes();
- auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+ AttributeList PALNew;
+#if LLVM_VERSION_LT(14, 0)
+ PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+#else
+ PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B);
+#endif
F->setAttributes(PALNew);
}
LLVMInitializeAVRAsmPrinter,
LLVMInitializeAVRAsmParser
);
+ init_target!(
+ llvm_component = "m68k",
+ LLVMInitializeM68kTargetInfo,
+ LLVMInitializeM68kTarget,
+ LLVMInitializeM68kTargetMC,
+ LLVMInitializeM68kAsmPrinter,
+ LLVMInitializeM68kAsmParser
+ );
init_target!(
llvm_component = "mips",
LLVMInitializeMipsTargetInfo,
[package]
name = "rustc_macros"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
span_idx = Some(syn::Index::from(idx));
} else {
throw_span_err!(
- info.span.clone().unwrap(),
+ info.span.unwrap(),
"type of field annotated with `#[suggestion(...)]` contains more than one Span"
);
}
applicability_idx = Some(syn::Index::from(idx));
} else {
throw_span_err!(
- info.span.clone().unwrap(),
+ info.span.unwrap(),
"type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
);
}
return Ok((span, applicability));
}
throw_span_err!(
- info.span.clone().unwrap(),
+ info.span.unwrap(),
"wrong types for suggestion",
|diag| {
diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)")
);
}
_ => throw_span_err!(
- info.span.clone().unwrap(),
+ info.span.unwrap(),
"wrong field type for suggestion",
|diag| {
diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)")
}
impl Interner {
- pub fn fresh() -> Self {
+ pub(crate) fn fresh() -> Self {
Interner::prefill(&[
#prefill_stream
])
[package]
name = "rustc_metadata"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[dependencies]
libc = "0.2"
+odht = { version = "0.3.0", features = ["nightly"] }
snap = "1"
tracing = "0.1"
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
/// This map is used to verify we get no hash conflicts between
/// `StableCrateId` values.
- stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
+ pub(crate) stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
/// Unused externs of the crate
unused_externs: Vec<Symbol>,
//! should be used when linking each output type requested in this session. This
//! generally follows this set of rules:
//!
-//! 1. Each library must appear exactly once in the output.
-//! 2. Each rlib contains only one library (it's just an object file)
-//! 3. Each dylib can contain more than one library (due to static linking),
-//! and can also bring in many dynamic dependencies.
+//! 1. Each library must appear exactly once in the output.
+//! 2. Each rlib contains only one library (it's just an object file)
+//! 3. Each dylib can contain more than one library (due to static linking),
+//! and can also bring in many dynamic dependencies.
//!
//! With these constraints in mind, it's generally a very difficult problem to
//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
//!
//! The current selection algorithm below looks mostly similar to:
//!
-//! 1. If static linking is required, then require all upstream dependencies
-//! to be available as rlibs. If not, generate an error.
-//! 2. If static linking is requested (generating an executable), then
-//! attempt to use all upstream dependencies as rlibs. If any are not
-//! found, bail out and continue to step 3.
-//! 3. Static linking has failed, at least one library must be dynamically
-//! linked. Apply a heuristic by greedily maximizing the number of
-//! dynamically linked libraries.
-//! 4. Each upstream dependency available as a dynamic library is
-//! registered. The dependencies all propagate, adding to a map. It is
-//! possible for a dylib to add a static library as a dependency, but it
-//! is illegal for two dylibs to add the same static library as a
-//! dependency. The same dylib can be added twice. Additionally, it is
-//! illegal to add a static dependency when it was previously found as a
-//! dylib (and vice versa)
-//! 5. After all dynamic dependencies have been traversed, re-traverse the
-//! remaining dependencies and add them statically (if they haven't been
-//! added already).
+//! 1. If static linking is required, then require all upstream dependencies
+//! to be available as rlibs. If not, generate an error.
+//! 2. If static linking is requested (generating an executable), then
+//! attempt to use all upstream dependencies as rlibs. If any are not
+//! found, bail out and continue to step 3.
+//! 3. Static linking has failed, at least one library must be dynamically
+//! linked. Apply a heuristic by greedily maximizing the number of
+//! dynamically linked libraries.
+//! 4. Each upstream dependency available as a dynamic library is
+//! registered. The dependencies all propagate, adding to a map. It is
+//! possible for a dylib to add a static library as a dependency, but it
+//! is illegal for two dylibs to add the same static library as a
+//! dependency. The same dylib can be added twice. Additionally, it is
+//! illegal to add a static dependency when it was previously found as a
+//! dylib (and vice versa)
+//! 5. After all dynamic dependencies have been traversed, re-traverse the
+//! remaining dependencies and add them statically (if they haven't been
+//! added already).
//!
//! While not perfect, this algorithm should help support use-cases such as leaf
//! dependencies being static while the larger tree of inner dependencies are
continue;
}
let cnum = CrateNum::new(i + 1);
- let found_strategy = tcx.panic_strategy(cnum);
- let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
- if is_compiler_builtins || desired_strategy == found_strategy {
+ if tcx.is_compiler_builtins(cnum) {
continue;
}
- sess.err(&format!(
- "the crate `{}` is compiled with the \
+ let found_strategy = tcx.panic_strategy(cnum);
+ if desired_strategy != found_strategy {
+ sess.err(&format!(
+ "the crate `{}` is compiled with the \
panic strategy `{}` which is \
incompatible with this crate's \
strategy of `{}`",
- tcx.crate_name(cnum),
- found_strategy.desc(),
- desired_strategy.desc()
- ));
+ tcx.crate_name(cnum),
+ found_strategy.desc(),
+ desired_strategy.desc()
+ ));
+ }
+
+ let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
+ if tcx.sess.opts.debugging_opts.panic_in_drop != found_drop_strategy {
+ sess.err(&format!(
+ "the crate `{}` is compiled with the \
+ panic-in-drop strategy `{}` which is \
+ incompatible with this crate's \
+ strategy of `{}`",
+ tcx.crate_name(cnum),
+ found_drop_strategy.desc(),
+ tcx.sess.opts.debugging_opts.panic_in_drop.desc()
+ ));
+ }
}
}
}
== Symbol::intern(&sess.opts.debugging_opts.profiler_runtime)
{
err.note(&"the compiler may have been built without the profiler runtime");
+ } else if crate_name.as_str().starts_with("rustc_") {
+ err.help(
+ "maybe you need to install the missing components with: \
+ `rustup component add rust-src rustc-dev llvm-tools-preview`",
+ );
}
err.span_label(span, "can't find crate");
err
}
}
- fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
self.tcx
.type_of(item.id.def_id)
.sum()
}
- fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+ fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
let calling_convention = if self.tcx.sess.target.arch == "x86" {
match abi {
Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, Body, Promoted};
+use rustc_middle::thir;
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
use rustc_serialize::{opaque, Decodable, Decoder};
mod cstore_impl;
-crate struct MetadataBlob(MetadataRef);
+/// A reference to the raw binary version of crate metadata.
+/// A `MetadataBlob` internally is just a reference counted pointer to
+/// the actual data, so cloning it is cheap.
+#[derive(Clone)]
+crate struct MetadataBlob(Lrc<MetadataRef>);
+
+// This is needed so we can create an OwningRef into the blob.
+// The data behind a `MetadataBlob` has a stable address because it is
+// contained within an Rc/Arc.
+unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {}
+
+// This is needed so we can create an OwningRef into the blob.
+impl std::ops::Deref for MetadataBlob {
+ type Target = [u8];
+
+ #[inline]
+ fn deref(&self) -> &[u8] {
+ &self.0[..]
+ }
+}
// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate.
source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
- /// For every definition in this crate, maps its `DefPathHash` to its
- /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
- /// this is used.
- def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
+ /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
+ def_path_hash_map: DefPathHashMapRef<'static>,
/// Likewise for ExpnHash.
expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
pub(super) struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>,
cdata: Option<CrateMetadataRef<'a>>,
+ blob: &'a MetadataBlob,
sess: Option<&'tcx Session>,
tcx: Option<TyCtxt<'tcx>>,
/// Abstract over the various ways one can create metadata decoders.
pub(super) trait Metadata<'a, 'tcx>: Copy {
- fn raw_bytes(self) -> &'a [u8];
+ fn blob(self) -> &'a MetadataBlob;
+
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
None
}
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
let tcx = self.tcx();
DecodeContext {
- opaque: opaque::Decoder::new(self.raw_bytes(), pos),
+ opaque: opaque::Decoder::new(self.blob(), pos),
cdata: self.cdata(),
+ blob: self.blob(),
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
tcx,
last_source_file_index: 0,
}
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
- fn raw_bytes(self) -> &'a [u8] {
- &self.0
+ #[inline]
+ fn blob(self) -> &'a MetadataBlob {
+ self
}
}
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
- fn raw_bytes(self) -> &'a [u8] {
- let (blob, _) = self;
- &blob.0
+ #[inline]
+ fn blob(self) -> &'a MetadataBlob {
+ self.0
}
+ #[inline]
fn sess(self) -> Option<&'tcx Session> {
let (_, sess) = self;
Some(sess)
}
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
- fn raw_bytes(self) -> &'a [u8] {
- self.blob.raw_bytes()
+ #[inline]
+ fn blob(self) -> &'a MetadataBlob {
+ &self.blob
}
+ #[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self)
}
}
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
- fn raw_bytes(self) -> &'a [u8] {
- self.0.raw_bytes()
+ #[inline]
+ fn blob(self) -> &'a MetadataBlob {
+ &self.0.blob
}
+ #[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0)
}
+ #[inline]
fn sess(self) -> Option<&'tcx Session> {
Some(&self.1)
}
}
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
- fn raw_bytes(self) -> &'a [u8] {
- self.0.raw_bytes()
+ #[inline]
+ fn blob(self) -> &'a MetadataBlob {
+ &self.0.blob
}
+ #[inline]
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
Some(*self.0)
}
+ #[inline]
fn tcx(self) -> Option<TyCtxt<'tcx>> {
Some(self.1)
}
}
impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
+ #[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
- self.tcx.expect("missing TyCtxt in DecodeContext")
+ debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext");
+ self.tcx.unwrap()
+ }
+
+ #[inline]
+ pub fn blob(&self) -> &'a MetadataBlob {
+ self.blob
}
- fn cdata(&self) -> CrateMetadataRef<'a> {
- self.cdata.expect("missing CrateMetadata in DecodeContext")
+ #[inline]
+ pub fn cdata(&self) -> CrateMetadataRef<'a> {
+ debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
+ self.cdata.unwrap()
}
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap());
Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta))
}
+
+ #[inline]
+ pub fn read_raw_bytes(&mut self, len: usize) -> &'a [u8] {
+ self.opaque.read_raw_bytes(len)
+ }
}
impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
let hi =
(hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
- Ok(Span::new(lo, hi, ctxt))
+ // Do not try to decode parent for foreign spans.
+ Ok(Span::new(lo, hi, ctxt, None))
}
}
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
ty::codec::RefDecodable::decode(d)
}
impl MetadataBlob {
crate fn new(metadata_ref: MetadataRef) -> MetadataBlob {
- MetadataBlob(metadata_ref)
+ MetadataBlob(Lrc::new(metadata_ref))
}
crate fn is_compatible(&self) -> bool {
- self.raw_bytes().starts_with(METADATA_HEADER)
+ self.blob().starts_with(METADATA_HEADER)
}
crate fn get_rustc_version(&self) -> String {
}
crate fn get_root(&self) -> CrateRoot<'tcx> {
- let slice = self.raw_bytes();
+ let slice = &self.blob()[..];
let offset = METADATA_HEADER.len();
let pos = (((slice[offset + 0] as u32) << 24)
| ((slice[offset + 1] as u32) << 16)
}
/// Iterates over each child of the given item.
- fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
- where
- F: FnMut(Export<hir::HirId>),
- {
+ fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) {
if let Some(data) = &self.root.proc_macro_data {
/* If we are loading as a proc macro, we want to return the view of this crate
* as a proc macro crate.
.decode((self, tcx))
}
- fn get_mir_abstract_const(
+ fn get_thir_abstract_const(
&self,
tcx: TyCtxt<'tcx>,
id: DefIndex,
- ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+ ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
self.root
.tables
- .mir_abstract_consts
+ .thir_abstract_consts
.get(self, id)
.map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
}
.or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
}
- /// Finds the corresponding `DefId` for the provided `DefPathHash`, if it exists.
- /// This is used by incremental compilation to map a serialized `DefPathHash` to
- /// its `DefId` in the current session.
- /// Normally, only one 'main' crate will change between incremental compilation sessions:
- /// all dependencies will be completely unchanged. In this case, we can avoid
- /// decoding every `DefPathHash` in the crate, since the `DefIndex` from the previous
- /// session will still be valid. If our 'guess' is wrong (the `DefIndex` no longer exists,
- /// or has a different `DefPathHash`, then we need to decode all `DefPathHashes` to determine
- /// the correct mapping).
- fn def_path_hash_to_def_id(
- &self,
- krate: CrateNum,
- index_guess: u32,
- hash: DefPathHash,
- ) -> Option<DefId> {
- let def_index_guess = DefIndex::from_u32(index_guess);
- let old_hash = self
- .root
- .tables
- .def_path_hashes
- .get(self, def_index_guess)
- .map(|lazy| lazy.decode(self));
-
- // Fast path: the definition and its index is unchanged from the
- // previous compilation session. There is no need to decode anything
- // else
- if old_hash == Some(hash) {
- return Some(DefId { krate, index: def_index_guess });
- }
-
- let is_proc_macro = self.is_proc_macro_crate();
-
- // Slow path: We need to find out the new `DefIndex` of the provided
- // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
- // stored in this crate.
- let map = self.cdata.def_path_hash_map.get_or_init(|| {
- let end_id = self.root.tables.def_path_hashes.size() as u32;
- let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
- for i in 0..end_id {
- let def_index = DefIndex::from_u32(i);
- // There may be gaps in the encoded table if we're decoding a proc-macro crate
- if let Some(hash) = self.root.tables.def_path_hashes.get(self, def_index) {
- map.insert(hash.decode(self), def_index);
- } else if !is_proc_macro {
- panic!("Missing def_path_hashes entry for {:?}", def_index);
- }
- }
- map
- });
- map.get(&hash).map(|index| DefId { krate, index: *index })
- }
-
// Returns the path leading to the thing with this `id`.
fn def_path(&self, id: DefIndex) -> DefPath {
debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
self.def_path_hash_unlocked(index, &mut def_path_hashes)
}
+ #[inline]
+ fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex {
+ self.def_path_hash_map.def_path_hash_to_def_index(&hash)
+ }
+
fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
debug_assert_eq!(ExpnId::from_hash(hash), None);
let index_guess = ExpnIndex::from_u32(index_guess);
let alloc_decoding_state =
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
+
+ // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation
+ // that does not copy any data. It just does some data verification.
+ let def_path_hash_map = root.def_path_hash_map.decode(&blob);
+
CrateMetadata {
blob,
root,
trait_impls,
raw_proc_macros,
source_map_import_info: OnceCell::new(),
- def_path_hash_map: Default::default(),
+ def_path_hash_map,
expn_hash_map: Default::default(),
alloc_decoding_state,
cnum,
use rustc_ast as ast;
use rustc_data_structures::stable_map::FxHashMap;
-use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) }
promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
- mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
+ thir_abstract_const => { cdata.get_thir_abstract_const(tcx, def_id.index) }
unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) }
mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
has_panic_handler => { cdata.root.has_panic_handler }
is_profiler_runtime => { cdata.root.profiler_runtime }
panic_strategy => { cdata.root.panic_strategy }
+ panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy }
extern_crate => {
let r = *cdata.extern_crate.lock();
r.map(|c| &*tcx.arena.alloc(c))
// (restrict scope of mutable-borrow of `visible_parent_map`)
{
let visible_parent_map = &mut visible_parent_map;
- let mut add_child =
- |bfs_queue: &mut VecDeque<_>, child: &Export<hir::HirId>, parent: DefId| {
- if child.vis != ty::Visibility::Public {
- return;
- }
+ let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
+ if child.vis != ty::Visibility::Public {
+ return;
+ }
- if let Some(child) = child.res.opt_def_id() {
- match visible_parent_map.entry(child) {
- Entry::Occupied(mut entry) => {
- // If `child` is defined in crate `cnum`, ensure
- // that it is mapped to a parent in `cnum`.
- if child.is_local() && entry.get().is_local() {
- entry.insert(parent);
- }
- }
- Entry::Vacant(entry) => {
+ if let Some(child) = child.res.opt_def_id() {
+ match visible_parent_map.entry(child) {
+ Entry::Occupied(mut entry) => {
+ // If `child` is defined in crate `cnum`, ensure
+ // that it is mapped to a parent in `cnum`.
+ if child.is_local() && entry.get().is_local() {
entry.insert(parent);
- bfs_queue.push_back(child);
}
}
+ Entry::Vacant(entry) => {
+ entry.insert(parent);
+ bfs_queue.push_back(child);
+ }
}
- };
+ }
+ };
while let Some(def) = bfs_queue.pop_front() {
for child in tcx.item_children(def).iter() {
self.get_crate_data(def.krate).get_visibility(def.index)
}
- pub fn item_children_untracked(
- &self,
- def_id: DefId,
- sess: &Session,
- ) -> Vec<Export<hir::HirId>> {
+ pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<Export> {
let mut result = vec![];
self.get_crate_data(def_id.krate).each_child_of_item(
def_id.index,
self.get_crate_data(cnum).root.stable_crate_id
}
+ fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum {
+ self.stable_crate_ids[&stable_crate_id]
+ }
+
/// Returns the `DefKey` for a given `DefId`. This indicates the
/// parent `DefId` as well as some idea of what kind of data the
/// `DefId` refers to.
self.get_crate_data(def.krate).def_path_hash(def.index)
}
- // See `CrateMetadataRef::def_path_hash_to_def_id` for more details
- fn def_path_hash_to_def_id(
- &self,
- cnum: CrateNum,
- index_guess: u32,
- hash: DefPathHash,
- ) -> Option<DefId> {
- self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
+ fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId {
+ let def_index = self.get_crate_data(cnum).def_path_hash_to_def_index(hash);
+ DefId { krate: cnum, index: def_index }
}
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
--- /dev/null
+use crate::rmeta::DecodeContext;
+use crate::rmeta::EncodeContext;
+use crate::rmeta::MetadataBlob;
+use rustc_data_structures::owning_ref::OwningRef;
+use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
+use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_span::def_id::{DefIndex, DefPathHash};
+
+crate enum DefPathHashMapRef<'tcx> {
+ OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>),
+ BorrowedFromTcx(&'tcx DefPathHashMap),
+}
+
+impl DefPathHashMapRef<'tcx> {
+ #[inline]
+ pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex {
+ match *self {
+ DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(def_path_hash).unwrap(),
+ DefPathHashMapRef::BorrowedFromTcx(_) => {
+ panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization")
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> {
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ match *self {
+ DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => {
+ let bytes = def_path_hash_map.raw_bytes();
+ e.emit_usize(bytes.len())?;
+ e.emit_raw_bytes(bytes)
+ }
+ DefPathHashMapRef::OwnedFromMetadata(_) => {
+ panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization")
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> {
+ fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefPathHashMapRef<'static>, String> {
+ // Import TyDecoder so we can access the DecodeContext::position() method
+ use crate::rustc_middle::ty::codec::TyDecoder;
+
+ let len = d.read_usize()?;
+ let pos = d.position();
+ let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]);
+
+ // Although we already have the data we need via the OwningRef, we still need
+ // to advance the DecodeContext's position so it's in a valid state after
+ // the method. We use read_raw_bytes() for that.
+ let _ = d.read_raw_bytes(len);
+
+ let inner = odht::HashTable::from_raw_bytes(o).map_err(|e| format!("{}", e))?;
+ Ok(DefPathHashMapRef::OwnedFromMetadata(inner))
+ }
+}
+use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
use crate::rmeta::*;
metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
};
use rustc_middle::mir::interpret;
+use rustc_middle::thir;
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
}
}
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
(**self).encode(s)
}
}
}
+ fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> {
+ self.lazy(DefPathHashMapRef::BorrowedFromTcx(
+ self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(),
+ ))
+ }
+
fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
let source_map = self.tcx.sess.source_map();
let all_source_files = source_map.files();
let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
let hygiene_bytes = self.position() - i;
+ i = self.position();
+ let def_path_hash_map = self.encode_def_path_hash_map();
+ let def_path_hash_map_bytes = self.position() - i;
+
// Encode source_map. This needs to be done last,
// since encoding `Span`s tells us which `SourceFiles` we actually
// need to encode.
hash: tcx.crate_hash(LOCAL_CRATE),
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
panic_strategy: tcx.sess.panic_strategy(),
+ panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop,
edition: tcx.sess.edition(),
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
syntax_contexts,
expn_data,
expn_hashes,
+ def_path_hash_map,
});
let total_bytes = self.position();
eprintln!(" impl bytes: {}", impl_bytes);
eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
eprintln!(" def-path table bytes: {}", def_path_table_bytes);
+ eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes);
eprintln!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
eprintln!(" mir bytes: {}", mir_bytes);
eprintln!(" item bytes: {}", item_bytes);
// items - we encode information about proc-macros later on.
let reexports = if !self.is_proc_macro {
match tcx.module_exports(local_def_id) {
- Some(exports) => {
- let hir = self.tcx.hir();
- self.lazy(
- exports
- .iter()
- .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))),
- )
- }
+ Some(exports) => self.lazy(exports),
_ => Lazy::empty(),
}
} else {
if encode_const {
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
- let abstract_const = self.tcx.mir_abstract_const(def_id);
+ // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
+ let abstract_const = self.tcx.thir_abstract_const(def_id);
if let Ok(Some(abstract_const)) = abstract_const {
- record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
+ record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const);
}
}
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
use decoder::Metadata;
+use def_path_hash_map::DefPathHashMapRef;
use table::{Table, TableBuilder};
use rustc_ast::{self as ast, MacroDef};
use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir;
+use rustc_middle::thir;
use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion;
use rustc_span::hygiene::SyntaxContextData;
mod decoder;
+mod def_path_hash_map;
mod encoder;
mod table;
hash: Svh,
stable_crate_id: StableCrateId,
panic_strategy: PanicStrategy,
+ panic_in_drop_strategy: PanicStrategy,
edition: Edition,
has_global_allocator: bool,
has_panic_handler: bool,
expn_data: ExpnDataTable,
expn_hashes: ExpnHashTable,
+ def_path_hash_map: Lazy<DefPathHashMapRef<'tcx>>,
+
source_map: Lazy<[rustc_span::SourceFile]>,
compiler_builtins: bool,
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
- mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
+ thir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>,
const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
// `def_keys` and `def_path_hashes` represent a lazy version of a
#[derive(MetadataEncodable, MetadataDecodable)]
struct ModData {
- reexports: Lazy<[Export<hir::HirId>]>,
+ reexports: Lazy<[Export]>,
expansion: ExpnId,
}
debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
let start = self.position.get();
- let bytes = &metadata.raw_bytes()[start..start + self.meta];
+ let bytes = &metadata.blob()[start..start + self.meta];
<Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
}
[package]
name = "rustc_middle"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
macro_rules! arena_types {
($macro:path, $tcx:lifetime) => (
$macro!([
- [] layouts: rustc_target::abi::Layout,
+ [] layout: rustc_target::abi::Layout,
+ [] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>,
// AdtDef are interned and compared by address
[] adt_def: rustc_middle::ty::AdtDef,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>,
/// has been removed.
fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
if self.kind.can_reconstruct_query_key() {
- tcx.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
+ Some(
+ tcx.on_disk_cache
+ .as_ref()?
+ .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())),
+ )
} else {
None
}
}
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
- let hash = tcx.def_path_hash(*self);
- // If this is a foreign `DefId`, store its current value
- // in the incremental cache. When we decode the cache,
- // we will use the old DefIndex as an initial guess for
- // a lookup into the crate metadata.
- if !self.is_local() {
- if let Some(cache) = &tcx.on_disk_cache {
- cache.store_foreign_def_id_hash(*self, hash);
- }
- }
- hash.0
+ tcx.def_path_hash(*self).0
}
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
type DepKind = DepKind;
type StableHashingContext = StableHashingContext<'tcx>;
- fn register_reused_dep_node(&self, dep_node: &DepNode) {
- if let Some(cache) = self.on_disk_cache.as_ref() {
- cache.register_reused_dep_node(*self, dep_node)
- }
- }
-
+ #[inline]
fn create_stable_hashing_context(&self) -> Self::StableHashingContext {
TyCtxt::create_stable_hashing_context(*self)
}
/// This is the replacement export map. It maps a module to all of the exports
/// within.
-pub type ExportMap<Id> = FxHashMap<LocalDefId, Vec<Export<Id>>>;
+pub type ExportMap = FxHashMap<LocalDefId, Vec<Export>>;
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct Export<Id> {
+pub struct Export {
/// The name of the target.
pub ident: Ident,
/// The resolution of the target.
- pub res: Res<Id>,
+ /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter.
+ pub res: Res<!>,
/// The span of the target.
pub span: Span,
/// The visibility of the export.
/// We include non-`pub` exports for hygienic macros that get used from extern crates.
pub vis: ty::Visibility,
}
-
-impl<Id> Export<Id> {
- pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
- Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis }
- }
-}
stable_hasher.finish()
}
-/// Represents an entry and its parent `HirId`.
-#[derive(Copy, Clone, Debug)]
-pub struct Entry<'hir> {
- parent: HirId,
- node: Node<'hir>,
-}
-
impl<'a, 'hir> NodeCollector<'a, 'hir> {
pub(super) fn root(
sess: &'a Session,
self.visit_nested_trait_item(id);
}
- fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) {
+ fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
// Do not visit the duplicate information in ImplItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
- let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii;
+ let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
self.visit_nested_impl_item(id);
}
- fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef<'hir>) {
+ fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
// Do not visit the duplicate information in ForeignItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
- let ForeignItemRef { id, ident: _, span: _, vis: _ } = *fi;
+ let ForeignItemRef { id, ident: _, span: _ } = *fi;
self.visit_nested_foreign_item(id);
}
use self::collector::NodeCollector;
-use crate::hir::{AttributeMap, IndexedHir, Owner};
+use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
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_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
+use std::collections::VecDeque;
pub mod blocks;
mod collector;
/// An iterator that walks up the ancestor tree of a given `HirId`.
/// Constructed using `tcx.hir().parent_iter(hir_id)`.
-pub struct ParentHirIterator<'map, 'hir> {
+pub struct ParentHirIterator<'hir> {
current_id: HirId,
- map: &'map Map<'hir>,
+ map: Map<'hir>,
}
-impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentHirIterator<'hir> {
type Item = (HirId, Node<'hir>);
fn next(&mut self) -> Option<Self::Item> {
/// An iterator that walks up the ancestor tree of a given `HirId`.
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
-pub struct ParentOwnerIterator<'map, 'hir> {
+pub struct ParentOwnerIterator<'hir> {
current_id: HirId,
- map: &'map Map<'hir>,
+ map: Map<'hir>,
}
-impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentOwnerIterator<'hir> {
type Item = (HirId, OwnerNode<'hir>);
fn next(&mut self) -> Option<Self::Item> {
}
pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
- // FIXME(eddyb) support `find` on the crate root.
- if local_def_id.to_def_id().index == CRATE_DEF_INDEX {
- return Some(DefKind::Mod);
- }
-
let hir_id = self.local_def_id_to_hir_id(local_def_id);
let def_kind = match self.find(hir_id)? {
Node::Item(item) => match item.kind {
{
let module = self.tcx.hir_module_items(module);
- for id in &module.items {
+ for id in module.items.iter() {
visitor.visit_item(self.item(*id));
}
- for id in &module.trait_items {
+ for id in module.trait_items.iter() {
visitor.visit_trait_item(self.trait_item(*id));
}
- for id in &module.impl_items {
+ for id in module.impl_items.iter() {
visitor.visit_impl_item(self.impl_item(*id));
}
- for id in &module.foreign_items {
+ for id in module.foreign_items.iter() {
visitor.visit_foreign_item(self.foreign_item(*id));
}
}
+ pub fn for_each_module(&self, f: impl Fn(LocalDefId)) {
+ let mut queue = VecDeque::new();
+ queue.push_back(CRATE_DEF_ID);
+
+ while let Some(id) = queue.pop_front() {
+ f(id);
+ let items = self.tcx.hir_module_items(id);
+ queue.extend(items.submodules.iter().copied())
+ }
+ }
+
+ #[cfg(not(parallel_compiler))]
+ #[inline]
+ pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
+ self.for_each_module(f)
+ }
+
+ #[cfg(parallel_compiler)]
+ pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
+ use rustc_data_structures::sync::{par_iter, ParallelIterator};
+ par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
+
+ fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
+ where
+ F: Fn(LocalDefId) + Sync,
+ {
+ (*f)(module);
+ let items = tcx.hir_module_items(module);
+ par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
+ }
+ }
+
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
- pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
+ pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
ParentHirIterator { current_id, map: self }
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
- pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> {
+ pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
ParentOwnerIterator { current_id, map: self }
}
.iter_enumerated()
.filter_map(|(def_id, hod)| {
let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
- let mut hasher = StableHasher::new();
- hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
- AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
- .hash_stable(&mut hcx, &mut hasher);
- Some((def_path_hash, hasher.finish()))
+ let hash = hod.as_ref()?.hash;
+ Some((def_path_hash, hash, def_id))
})
.collect();
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
- let node_hashes = hir_body_nodes.iter().fold(
- Fingerprint::ZERO,
- |combined_fingerprint, &(def_path_hash, fingerprint)| {
- combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
- },
- );
-
let upstream_crates = upstream_crates(tcx);
// We hash the final, remapped names of all local source files so we
source_file_names.sort_unstable();
let mut stable_hasher = StableHasher::new();
- node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
+ for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
+ def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
+ fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
+ AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
+ .hash_stable(&mut hcx, &mut stable_hasher);
+ if tcx.sess.opts.debugging_opts.incremental_relative_spans {
+ let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
+ debug_assert_eq!(span.parent(), None);
+ span.hash_stable(&mut hcx, &mut stable_hasher);
+ }
+ }
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
None => format!("unknown node{}", id_str),
}
}
+
+pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
+ let mut collector = ModuleCollector {
+ tcx,
+ submodules: Vec::default(),
+ items: Vec::default(),
+ trait_items: Vec::default(),
+ impl_items: Vec::default(),
+ foreign_items: Vec::default(),
+ };
+
+ let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
+ collector.visit_mod(hir_mod, span, hir_id);
+
+ let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
+ collector;
+ return ModuleItems {
+ submodules: submodules.into_boxed_slice(),
+ items: items.into_boxed_slice(),
+ trait_items: trait_items.into_boxed_slice(),
+ impl_items: impl_items.into_boxed_slice(),
+ foreign_items: foreign_items.into_boxed_slice(),
+ };
+
+ struct ModuleCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ submodules: Vec<LocalDefId>,
+ items: Vec<ItemId>,
+ trait_items: Vec<TraitItemId>,
+ impl_items: Vec<ImplItemId>,
+ foreign_items: Vec<ForeignItemId>,
+ }
+
+ impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
+ type Map = Map<'hir>;
+
+ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+ intravisit::NestedVisitorMap::All(self.tcx.hir())
+ }
+
+ fn visit_item(&mut self, item: &'hir Item<'hir>) {
+ self.items.push(item.item_id());
+ if let ItemKind::Mod(..) = item.kind {
+ // If this declares another module, do not recurse inside it.
+ self.submodules.push(item.def_id);
+ } else {
+ intravisit::walk_item(self, item)
+ }
+ }
+
+ fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
+ self.trait_items.push(item.trait_item_id());
+ intravisit::walk_trait_item(self, item)
+ }
+
+ fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
+ self.impl_items.push(item.impl_item_id());
+ intravisit::walk_impl_item(self, item)
+ }
+
+ fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
+ self.foreign_items.push(item.foreign_item_id());
+ intravisit::walk_foreign_item(self, item)
+ }
+ }
+}
}
}
+/// Gather the LocalDefId for each item-like within a module, including items contained within
+/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
+#[derive(Debug, HashStable)]
+pub struct ModuleItems {
+ submodules: Box<[LocalDefId]>,
+ items: Box<[ItemId]>,
+ trait_items: Box<[TraitItemId]>,
+ impl_items: Box<[ImplItemId]>,
+ foreign_items: Box<[ForeignItemId]>,
+}
+
impl<'tcx> TyCtxt<'tcx> {
#[inline(always)]
pub fn hir(self) -> map::Map<'tcx> {
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
providers.index_hir = map::index_hir;
providers.crate_hash = map::crate_hash;
- providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
+ providers.hir_module_items = map::hir_module_items;
providers.hir_owner = |tcx, id| {
let owner = tcx.index_hir(()).map[id].as_ref()?;
let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
};
providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
+ providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
providers.fn_arg_names = |tcx, id| {
let hir = tcx.hir();
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
use smallvec::SmallVec;
use std::cmp::Ord;
/// things (e.g., each `DefId`/`DefPath` is only hashed once).
#[derive(Clone)]
pub struct StableHashingContext<'a> {
- sess: &'a Session,
definitions: &'a Definitions,
cstore: &'a dyn CrateStore,
pub(super) body_resolver: BodyResolver<'a>,
!always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
StableHashingContext {
- sess,
body_resolver: BodyResolver(krate),
definitions,
cstore,
self.def_path_hash(def_id)
}
+ #[inline]
+ fn def_span(&self, def_id: LocalDefId) -> Span {
+ self.definitions.def_span(def_id)
+ }
+
fn span_data_to_lines_and_cols(
&mut self,
span: &SpanData,
ty::ReFree(ref free_region) => {
free_region.hash_stable(hcx, hasher);
}
- ty::ReVar(..) | ty::RePlaceholder(..) => {
+ ty::RePlaceholder(p) => {
+ p.hash_stable(hcx, hasher);
+ }
+ ty::ReVar(..) => {
bug!("StableHasher: unexpected region {:?}", *self)
}
}
#![feature(discriminant_kind)]
#![feature(exhaustive_patterns)]
#![feature(if_let_guard)]
+#![feature(map_first_last)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
// incr. comp. uses to identify a CrateNum.
fn crate_name(&self, cnum: CrateNum) -> Symbol;
fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId;
+ fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum;
/// Fetch a DefId from a DefPathHash for a foreign crate.
- fn def_path_hash_to_def_id(
- &self,
- cnum: CrateNum,
- index_guess: u32,
- hash: DefPathHash,
- ) -> Option<DefId>;
+ fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId;
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;
// utility functions
/// ```
///
/// With the HIR tree (calls numbered for expository purposes)
- /// ```
+ ///
+ /// ```text
/// Call#0(foo, [Call#1(f), Yield(y), Call#2(bar, Call#3(g))])
/// ```
///
+++ /dev/null
-//! A subset of a mir body used for const evaluatability checking.
-use crate::mir::{self, CastKind};
-use crate::ty::{self, Ty};
-
-rustc_index::newtype_index! {
- /// An index into an `AbstractConst`.
- pub struct NodeId {
- derive [HashStable]
- DEBUG_FORMAT = "n{}",
- }
-}
-
-/// A node of an `AbstractConst`.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum Node<'tcx> {
- Leaf(&'tcx ty::Const<'tcx>),
- Binop(mir::BinOp, NodeId, NodeId),
- UnaryOp(mir::UnOp, NodeId),
- FunctionCall(NodeId, &'tcx [NodeId]),
- Cast(CastKind, NodeId, Ty<'tcx>),
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum NotConstEvaluatable {
- Error(rustc_errors::ErrorReported),
- MentionsInfer,
- MentionsParam,
-}
-
-impl From<rustc_errors::ErrorReported> for NotConstEvaluatable {
- fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable {
- NotConstEvaluatable::Error(e)
- }
-}
-
-TrivialTypeFoldableAndLiftImpls! {
- NotConstEvaluatable,
-}
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
use std::fmt;
////////////////////////////////////////////////////////////////////////////////
#[inline]
fn machine_usize_max(&self) -> u64 {
- let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
- u64::try_from(max_usize_plus_1 - 1).unwrap()
+ self.pointer_size().unsigned_int_max().try_into().unwrap()
}
#[inline]
fn machine_isize_min(&self) -> i64 {
- let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
- i64::try_from(-max_isize_plus_1).unwrap()
+ self.pointer_size().signed_int_min().try_into().unwrap()
}
#[inline]
fn machine_isize_max(&self) -> i64 {
- let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
- i64::try_from(max_isize_plus_1 - 1).unwrap()
+ self.pointer_size().signed_int_max().try_into().unwrap()
}
#[inline]
fn machine_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64;
- // Now clamp into the machine_isize range.
+ // Now wrap-around into the machine_isize range.
if val > self.machine_isize_max() {
// This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64.
+ debug_assert!(self.pointer_size().bits() < 64);
let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
val - i64::try_from(max_usize_plus_1).unwrap()
} else {
use self::predecessors::{PredecessorCache, Predecessors};
pub use self::query::*;
-pub mod abstract_const;
pub mod coverage;
mod generic_graph;
pub mod generic_graphviz;
StaticRef { def_id: DefId, is_thread_local: bool },
/// A temporary created that references the const with the given `DefId`
ConstRef { def_id: DefId },
+ /// A temporary created during the creation of an aggregate
+ /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
+ AggregateTemp,
}
impl<'tcx> LocalDecl<'tcx> {
pub projection: &'tcx List<PlaceElem<'tcx>>,
}
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(Place<'_>, 16);
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
Constant(Box<Constant<'tcx>>),
}
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(Operand<'_>, 24);
impl<'tcx> Debug for Operand<'tcx> {
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
}
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(Rvalue<'_>, 40);
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(AggregateKind<'_>, 48);
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum NullOp {
/// Returns the size of a value of that type
SizeOf,
+ /// Returns the minimum alignment of a type
+ AlignOf,
/// Creates a new uninitialized box for a value of that type
Box,
}
//! Values computed by queries that use MIR.
-use crate::mir::{abstract_const, Body, Promoted};
+use crate::mir::{Body, Promoted};
use crate::ty::{self, Ty, TyCtxt};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
CopyBound,
SizedBound,
Assignment,
+ /// A constraint that came from a usage of a variable (e.g. in an ADT expression
+ /// like `Foo { field: my_val }`)
+ Usage,
OpaqueType,
ClosureUpvar(hir::HirId),
/// A "boring" constraint (caused by the given location) is one that
/// the user probably doesn't want to see described in diagnostics,
/// because it is kind of an artifact of the type system setup.
- /// Example: `x = Foo { field: y }` technically creates
- /// intermediate regions representing the "type of `Foo { field: y
- /// }`", and data flows from `y` into those variables, but they
- /// are not very interesting. The assignment into `x` on the other
- /// hand might be.
Boring,
// Boring and applicable everywhere.
BoringNoLocation,
self.mir_for_ctfe(def.did)
}
}
-
- #[inline]
- pub fn mir_abstract_const_opt_const_arg(
- self,
- def: ty::WithOptConstParam<DefId>,
- ) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> {
- if let Some((did, param_did)) = def.as_const_arg() {
- self.mir_abstract_const_of_const_arg((did, param_did))
- } else {
- self.mir_abstract_const(def.did)
- }
- }
}
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
- Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
desc { "get the resolver outputs" }
}
+ /// Return the span for a definition.
+ /// Contrary to `def_span` below, this query returns the full absolute span of the definition.
+ /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
+ /// of rustc_middle::hir::source_map.
+ query source_span(key: LocalDefId) -> Span {
+ desc { "get the source span" }
+ }
+
/// Represents crate as a whole (as distinct from the top-level crate module).
/// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
/// we will have to assume that any change means that you need to be recompiled.
///
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
/// Avoid calling this query directly.
- query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
- eval_always
+ query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
+ storage(ArenaCacheSelector<'tcx>)
desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
}
}
/// Try to build an abstract representation of the given constant.
- query mir_abstract_const(
+ query thir_abstract_const(
key: DefId
- ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+ ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
desc {
|tcx| "building an abstract representation for {}", tcx.def_path_str(key),
}
}
/// Try to build an abstract representation of the given constant.
- query mir_abstract_const_of_const_arg(
+ query thir_abstract_const_of_const_arg(
key: (LocalDefId, DefId)
- ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+ ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
desc {
|tcx|
"building an abstract representation for the const argument {}",
desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
}
- /// Returns `true` if this is a const `impl`. **Do not call this function manually.**
- ///
- /// This query caches the base data for the `is_const_impl` helper function, which also
- /// takes into account stability attributes (e.g., `#[rustc_const_unstable]`).
- query is_const_impl_raw(key: DefId) -> bool {
- desc { |tcx| "checking if item is const impl: `{}`", tcx.def_path_str(key) }
- }
-
query asyncness(key: DefId) -> hir::IsAsync {
desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
}
desc { "computing layout of `{}`", key.value }
}
+ /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
+ ///
+ /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
+ /// instead, where the instance is an `InstanceDef::Virtual`.
+ query fn_abi_of_fn_ptr(
+ key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+ ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+ desc { "computing call ABI of `{}` function pointers", key.value.0 }
+ }
+
+ /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
+ /// direct calls to an `fn`.
+ ///
+ /// NB: that includes virtual calls, which are represented by "direct calls"
+ /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+ query fn_abi_of_instance(
+ key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+ ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+ desc { "computing call ABI of `{}`", key.value.0 }
+ }
+
query dylib_dependency_formats(_: CrateNum)
-> &'tcx [(CrateNum, LinkagePreference)] {
desc { "dylib dependency formats of crate" }
fatal_cycle
desc { "query a crate's configured panic strategy" }
}
+ query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
+ fatal_cycle
+ desc { "query a crate's configured panic-in-drop strategy" }
+ }
query is_no_builtins(_: CrateNum) -> bool {
fatal_cycle
desc { "test whether a crate has `#![no_builtins]`" }
desc { "traits in scope at a block" }
}
- query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export<LocalDefId>]> {
+ query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> {
desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
eval_always
desc { "fetching what a crate is named" }
}
- query item_children(def_id: DefId) -> &'tcx [Export<hir::HirId>] {
+ query item_children(def_id: DefId) -> &'tcx [Export] {
desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
}
query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
use std::fmt;
use std::ops::Index;
+pub mod abstract_const;
+pub mod visit;
+
newtype_index! {
/// An index to an [`Arm`] stored in [`Thir::arms`]
#[derive(HashStable)]
--- /dev/null
+//! A subset of a mir body used for const evaluatability checking.
+use crate::mir;
+use crate::ty::{self, Ty, TyCtxt};
+use rustc_errors::ErrorReported;
+
+rustc_index::newtype_index! {
+ /// An index into an `AbstractConst`.
+ pub struct NodeId {
+ derive [HashStable]
+ DEBUG_FORMAT = "n{}",
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum CastKind {
+ /// thir::ExprKind::As
+ As,
+ /// thir::ExprKind::Use
+ Use,
+}
+
+/// A node of an `AbstractConst`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum Node<'tcx> {
+ Leaf(&'tcx ty::Const<'tcx>),
+ Binop(mir::BinOp, NodeId, NodeId),
+ UnaryOp(mir::UnOp, NodeId),
+ FunctionCall(NodeId, &'tcx [NodeId]),
+ Cast(CastKind, NodeId, Ty<'tcx>),
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum NotConstEvaluatable {
+ Error(ErrorReported),
+ MentionsInfer,
+ MentionsParam,
+}
+
+impl From<ErrorReported> for NotConstEvaluatable {
+ fn from(e: ErrorReported) -> NotConstEvaluatable {
+ NotConstEvaluatable::Error(e)
+ }
+}
+
+TrivialTypeFoldableAndLiftImpls! {
+ NotConstEvaluatable,
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+ #[inline]
+ pub fn thir_abstract_const_opt_const_arg(
+ self,
+ def: ty::WithOptConstParam<rustc_hir::def_id::DefId>,
+ ) -> Result<Option<&'tcx [Node<'tcx>]>, ErrorReported> {
+ if let Some((did, param_did)) = def.as_const_arg() {
+ self.thir_abstract_const_of_const_arg((did, param_did))
+ } else {
+ self.thir_abstract_const(def.did)
+ }
+ }
+}
--- /dev/null
+use super::{
+ Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
+};
+use rustc_middle::ty::Const;
+
+pub trait Visitor<'a, 'tcx: 'a>: Sized {
+ fn thir(&self) -> &'a Thir<'tcx>;
+
+ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+ walk_expr(self, expr);
+ }
+
+ fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
+ walk_stmt(self, stmt);
+ }
+
+ fn visit_block(&mut self, block: &Block) {
+ walk_block(self, block);
+ }
+
+ fn visit_arm(&mut self, arm: &Arm<'tcx>) {
+ walk_arm(self, arm);
+ }
+
+ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+ walk_pat(self, pat);
+ }
+
+ fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
+}
+
+pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
+ use ExprKind::*;
+ match expr.kind {
+ Scope { value, region_scope: _, lint_level: _ } => {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ Box { value } => visitor.visit_expr(&visitor.thir()[value]),
+ If { cond, then, else_opt, if_then_scope: _ } => {
+ visitor.visit_expr(&visitor.thir()[cond]);
+ visitor.visit_expr(&visitor.thir()[then]);
+ if let Some(else_expr) = else_opt {
+ visitor.visit_expr(&visitor.thir()[else_expr]);
+ }
+ }
+ Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
+ visitor.visit_expr(&visitor.thir()[fun]);
+ for &arg in &**args {
+ visitor.visit_expr(&visitor.thir()[arg]);
+ }
+ }
+ Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
+ Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[rhs]);
+ }
+ Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
+ Use { source } => visitor.visit_expr(&visitor.thir()[source]),
+ NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
+ Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
+ Let { expr, .. } => {
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+ Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
+ Match { scrutinee, ref arms } => {
+ visitor.visit_expr(&visitor.thir()[scrutinee]);
+ for &arm in &**arms {
+ visitor.visit_arm(&visitor.thir()[arm]);
+ }
+ }
+ Block { ref body } => visitor.visit_block(body),
+ Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[rhs]);
+ }
+ Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
+ Index { lhs, index } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[index]);
+ }
+ VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
+ Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ Break { value, label: _ } => {
+ if let Some(value) = value {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ }
+ Continue { label: _ } => {}
+ Return { value } => {
+ if let Some(value) = value {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ }
+ ConstBlock { value } => visitor.visit_const(value),
+ Repeat { value, count } => {
+ visitor.visit_expr(&visitor.thir()[value]);
+ visitor.visit_const(count);
+ }
+ Array { ref fields } | Tuple { ref fields } => {
+ for &field in &**fields {
+ visitor.visit_expr(&visitor.thir()[field]);
+ }
+ }
+ Adt(box crate::thir::Adt {
+ ref fields,
+ ref base,
+ adt_def: _,
+ variant_index: _,
+ substs: _,
+ user_ty: _,
+ }) => {
+ for field in &**fields {
+ visitor.visit_expr(&visitor.thir()[field.expr]);
+ }
+ if let Some(base) = base {
+ visitor.visit_expr(&visitor.thir()[base.base]);
+ }
+ }
+ PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
+ visitor.visit_expr(&visitor.thir()[source])
+ }
+ Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
+ Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
+ StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
+ InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
+ for op in &**operands {
+ use InlineAsmOperand::*;
+ match op {
+ In { expr, reg: _ }
+ | Out { expr: Some(expr), reg: _, late: _ }
+ | InOut { expr, reg: _, late: _ }
+ | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
+ SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
+ visitor.visit_expr(&visitor.thir()[*in_expr]);
+ if let Some(out_expr) = out_expr {
+ visitor.visit_expr(&visitor.thir()[*out_expr]);
+ }
+ }
+ Out { expr: None, reg: _, late: _ }
+ | Const { value: _, span: _ }
+ | SymStatic { def_id: _ } => {}
+ }
+ }
+ }
+ ThreadLocalRef(_) => {}
+ LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
+ for &out_expr in &**outputs {
+ visitor.visit_expr(&visitor.thir()[out_expr]);
+ }
+ for &in_expr in &**inputs {
+ visitor.visit_expr(&visitor.thir()[in_expr]);
+ }
+ }
+ Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
+ }
+}
+
+pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
+ match &stmt.kind {
+ StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
+ StmtKind::Let {
+ initializer,
+ remainder_scope: _,
+ init_scope: _,
+ ref pattern,
+ lint_level: _,
+ } => {
+ if let Some(init) = initializer {
+ visitor.visit_expr(&visitor.thir()[*init]);
+ }
+ visitor.visit_pat(pattern);
+ }
+ }
+}
+
+pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
+ for &stmt in &*block.stmts {
+ visitor.visit_stmt(&visitor.thir()[stmt]);
+ }
+ if let Some(expr) = block.expr {
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+}
+
+pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
+ match arm.guard {
+ Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
+ Some(Guard::IfLet(ref pat, expr)) => {
+ visitor.visit_pat(pat);
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+ None => {}
+ }
+ visitor.visit_pat(&arm.pattern);
+ visitor.visit_expr(&visitor.thir()[arm.body]);
+}
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+ use PatKind::*;
+ match pat.kind.as_ref() {
+ AscribeUserType { subpattern, ascription: _ }
+ | Deref { subpattern }
+ | Binding {
+ subpattern: Some(subpattern),
+ mutability: _,
+ mode: _,
+ var: _,
+ ty: _,
+ is_primary: _,
+ name: _,
+ } => visitor.visit_pat(&subpattern),
+ Binding { .. } | Wild => {}
+ Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+ for subpattern in subpatterns {
+ visitor.visit_pat(&subpattern.pattern);
+ }
+ }
+ Constant { value } => visitor.visit_const(value),
+ Range(range) => {
+ visitor.visit_const(range.lo);
+ visitor.visit_const(range.hi);
+ }
+ Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+ for subpattern in prefix {
+ visitor.visit_pat(&subpattern);
+ }
+ if let Some(pat) = slice {
+ visitor.visit_pat(pat);
+ }
+ for subpattern in suffix {
+ visitor.visit_pat(&subpattern);
+ }
+ }
+ Or { pats } => {
+ for pat in pats {
+ visitor.visit_pat(&pat);
+ }
+ }
+ };
+}
mod structural_impls;
use crate::infer::canonical::Canonical;
-use crate::mir::abstract_const::NotConstEvaluatable;
+use crate::thir::abstract_const::NotConstEvaluatable;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, AdtKind, Ty, TyCtxt};
DerivedObligation(DerivedObligationCause<'tcx>),
+ FunctionArgumentObligation {
+ /// The node of the relevant argument in the function call.
+ arg_hir_id: hir::HirId,
+ /// The node of the function call.
+ call_hir_id: hir::HirId,
+ /// The obligation introduced by this argument.
+ parent_code: Lrc<ObligationCauseCode<'tcx>>,
+ },
+
/// Error derived when matching traits/impls; see ObligationCause for more details
CompareImplConstObligation,
WellFormed(Option<WellFormedLoc>),
/// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
- MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId),
+ MatchImpl(ObligationCause<'tcx>, DefId),
}
/// The 'location' at which we try to perform HIR-based wf checking.
// Return the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self {
let mut base_cause = self;
- while let BuiltinDerivedObligation(cause)
- | ImplDerivedObligation(cause)
- | DerivedObligation(cause) = base_cause
+ while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
+ | ImplDerivedObligation(DerivedObligationCause { parent_code, .. })
+ | DerivedObligation(DerivedObligationCause { parent_code, .. })
+ | FunctionArgumentObligation { parent_code, .. } = base_cause
{
- base_cause = &cause.parent_code;
+ base_cause = &parent_code;
}
base_cause
}
/// ImplSource for a trait alias.
TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
+
+ /// ImplSource for a `const Drop` implementation.
+ ConstDrop(ImplSourceConstDropData),
}
impl<'tcx, N> ImplSource<'tcx, N> {
ImplSource::Object(d) => d.nested,
ImplSource::FnPointer(d) => d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
+ | ImplSource::Pointee(ImplSourcePointeeData)
+ | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(),
ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested,
}
ImplSource::Object(d) => &d.nested[..],
ImplSource::FnPointer(d) => &d.nested[..],
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData) => &[],
+ | ImplSource::Pointee(ImplSourcePointeeData)
+ | ImplSource::ConstDrop(ImplSourceConstDropData) => &[],
ImplSource::TraitAlias(d) => &d.nested[..],
ImplSource::TraitUpcasting(d) => &d.nested[..],
}
nested: d.nested.into_iter().map(f).collect(),
})
}
+ ImplSource::ConstDrop(ImplSourceConstDropData) => {
+ ImplSource::ConstDrop(ImplSourceConstDropData)
+ }
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub struct ImplSourcePointeeData;
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
+pub struct ImplSourceConstDropData;
+
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceTraitAliasData<'tcx, N> {
pub alias_def_id: DefId,
pub nested: Vec<N>,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
pub enum ObjectSafetyViolation {
/// `Self: Sized` declared on the trait.
SizedSelf(SmallVec<[Span; 1]>),
}
/// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
pub enum MethodViolationCode {
/// e.g., `fn foo()`
StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
BuiltinObjectCandidate,
BuiltinUnsizeCandidate,
+
+ /// Implementation of `const Drop`.
+ ConstDropCandidate,
}
/// The result of trait evaluation. The order is important
super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
+
+ super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d),
}
}
}
super::IfExpressionCause,
super::ImplSourceDiscriminantKindData,
super::ImplSourcePointeeData,
+ super::ImplSourceConstDropData,
}
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorReported;
+use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec};
self.destructor(tcx).is_some()
}
+ pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
+ matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. }))
+ }
+
/// Asserts this is a struct or union and returns its unique variant.
pub fn non_enum_variant(&self) -> &VariantDef {
assert!(self.is_struct() || self.is_union());
self,
interpret::{AllocId, Allocation},
};
+use crate::thir;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, List, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
}
}
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
Ok(decoder.tcx().arena.alloc_from_iter(
(0..decoder.read_usize()?)
}
}
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] {
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
Ok(decoder.tcx().arena.alloc_from_iter(
(0..decoder.read_usize()?)
//! Type context book-keeping.
use crate::arena::Arena;
-use crate::dep_graph::{DepGraph, DepNode};
+use crate::dep_graph::DepGraph;
use crate::hir::place::Place as HirPlace;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
/// session, if it still exists. This is used during incremental compilation to
/// turn a deserialized `DefPathHash` into its current `DefId`.
- fn def_path_hash_to_def_id(
- &self,
- tcx: TyCtxt<'tcx>,
- def_path_hash: DefPathHash,
- ) -> Option<DefId>;
-
- /// If the given `dep_node`'s hash still exists in the current compilation,
- /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
- ///
- /// Normally, `store_foreign_def_id_hash` can be called directly by
- /// the dependency graph when we construct a `DepNode`. However,
- /// when we re-use a deserialized `DepNode` from the previous compilation
- /// session, we only have the `DefPathHash` available. This method is used
- /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
- /// out for usage in the next compilation session.
- 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 def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId;
fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
/// The arena that types, regions, etc. are allocated from.
arena: &'tcx WorkerLocal<Arena<'tcx>>,
- /// Specifically use a speedy hash algorithm for these hash sets, since
- /// they're accessed quite often.
+ // Specifically use a speedy hash algorithm for these hash sets, since
+ // they're accessed quite often.
type_: InternedSet<'tcx, TyS<'tcx>>,
type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
const_: InternedSet<'tcx, Const<'tcx>>,
- /// Const allocations.
- allocation: InternedSet<'tcx, Allocation>,
+ const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
+ layout: InternedSet<'tcx, Layout>,
}
impl<'tcx> CtxtInterners<'tcx> {
projs: Default::default(),
place_elems: Default::default(),
const_: Default::default(),
- allocation: Default::default(),
+ const_allocation: Default::default(),
bound_variable_kinds: Default::default(),
+ layout: Default::default(),
}
}
/// Stores memory for globals (statics/consts).
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
- layout_interner: ShardedHashMap<&'tcx Layout, ()>,
-
output_filenames: Arc<OutputFilenames>,
+ // FIXME(eddyb) this doesn't belong here and should be using a query.
pub(super) vtables_cache:
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
}
self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr))
}
- pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation {
- self.interners
- .allocation
- .intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc)))
- .0
- }
-
/// Allocates a read-only byte or string literal for `mir::interpret`.
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
// Create an allocation that just contains these bytes.
self.create_memory_alloc(alloc)
}
+ // FIXME(eddyb) move to `direct_interners!`.
pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
self.stability_interner.intern(stab, |stab| self.arena.alloc(stab))
}
+ // FIXME(eddyb) move to `direct_interners!`.
pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability {
self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab))
}
- pub fn intern_layout(self, layout: Layout) -> &'tcx Layout {
- self.layout_interner.intern(layout, |layout| self.arena.alloc(layout))
- }
-
/// Returns a range of the start/end indices specified with the
/// `rustc_layout_scalar_valid_range` attribute.
+ // FIXME(eddyb) this is an awkward spot for this method, maybe move it?
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
let attrs = self.get_attrs(def_id);
let get = |name| {
evaluation_cache: Default::default(),
crate_name: Symbol::intern(crate_name),
data_layout,
- layout_interner: Default::default(),
stability_interner: Default::default(),
const_stability_interner: Default::default(),
alloc_map: Lock::new(interpret::AllocMap::new()),
}
}
+ /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
+ /// that the crate in question has already been loaded by the CrateStore.
+ #[inline]
+ pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
+ if stable_crate_id == self.sess.local_stable_crate_id() {
+ LOCAL_CRATE
+ } else {
+ self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ }
+ }
+
pub fn def_path_debug_str(self, def_id: DefId) -> String {
// We are explicitly not going through queries here in order to get
// crate name and stable crate id since this code is called from debug!()
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
-nop_lift! {allocation; &'a Allocation => &'tcx Allocation}
+nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation}
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
"Const Stability interner: #{}",
self.0.const_stability_interner.len()
)?;
- writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?;
- writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?;
+ writeln!(
+ fmt,
+ "Const Allocation interner: #{}",
+ self.0.interners.const_allocation.len()
+ )?;
+ writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
Ok(())
}
}
}
-impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
- fn borrow(&self) -> &RegionKind {
- &self.0
- }
-}
-
-impl<'tcx> Borrow<Const<'tcx>> for Interned<'tcx, Const<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a Const<'tcx> {
- &self.0
- }
-}
-
-impl<'tcx> Borrow<Allocation> for Interned<'tcx, Allocation> {
- fn borrow<'a>(&'a self) -> &'a Allocation {
- &self.0
- }
-}
-
-impl<'tcx> PartialEq for Interned<'tcx, Allocation> {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
-}
-
-impl<'tcx> Eq for Interned<'tcx, Allocation> {}
-
-impl<'tcx> Hash for Interned<'tcx, Allocation> {
- fn hash<H: Hasher>(&self, s: &mut H) {
- self.0.hash(s)
- }
-}
-
macro_rules! direct_interners {
($($name:ident: $method:ident($ty:ty),)+) => {
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
}
}
+ impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> {
+ fn borrow<'a>(&'a self) -> &'a $ty {
+ &self.0
+ }
+ }
+
impl<'tcx> TyCtxt<'tcx> {
pub fn $method(self, v: $ty) -> &'tcx $ty {
- self.interners.$name.intern_ref(&v, || {
+ self.interners.$name.intern(v, |v| {
Interned(self.interners.arena.alloc(v))
}).0
}
direct_interners! {
region: mk_region(RegionKind),
const_: mk_const(Const<'tcx>),
+ const_allocation: intern_const_alloc(Allocation),
+ layout: intern_layout(Layout),
}
macro_rules! slice_interners {
{
let (span, sugg) = if has_params {
let pos = span.hi() - BytePos(1);
- let span = Span::new(pos, pos, span.ctxt());
+ let span = Span::new(pos, pos, span.ctxt(), span.parent());
(span, format!(", {} = {}", assoc.ident, ty))
} else {
let item_args = self.format_generic_args(assoc_substs);
-use crate::ich::StableHashingContext;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
use crate::ty::subst::Subst;
use rustc_ast as ast;
use rustc_attr as attr;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet;
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
};
use rustc_target::abi::*;
-use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy};
+use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
use std::cmp;
use std::fmt;
use std::iter;
-use std::mem;
use std::num::NonZeroUsize;
use std::ops::Bound;
+pub fn provide(providers: &mut ty::query::Providers) {
+ *providers =
+ ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+}
+
pub trait IntegerExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
-#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>),
})
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { layout_of, ..*providers };
-}
-
pub struct LayoutCx<'tcx, C> {
pub tcx: C,
pub param_env: ty::ParamEnv<'tcx>,
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
// returns the last maximum.
- let largest_niche = Niche::from_scalar(dl, b_offset, b.clone())
+ let largest_niche = Niche::from_scalar(dl, b_offset, b)
.into_iter()
- .chain(Niche::from_scalar(dl, Size::ZERO, a.clone()))
+ .chain(Niche::from_scalar(dl, Size::ZERO, a))
.max_by_key(|niche| niche.available(dl));
Layout {
offsets[i as usize] = offset;
if !repr.hide_niche() {
- if let Some(mut niche) = field.largest_niche.clone() {
+ if let Some(mut niche) = field.largest_niche {
let available = niche.available(dl);
if available > largest_niche_available {
largest_niche_available = available;
// For plain scalars, or vectors of them, we can't unpack
// newtypes for `#[repr(C)]`, as that affects C ABIs.
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
- abi = field.abi.clone();
+ abi = field.abi;
}
// But scalar pairs are Rust-specific and get
// treated as aggregates by C ABIs anyway.
Abi::ScalarPair(..) => {
- abi = field.abi.clone();
+ abi = field.abi;
}
_ => {}
}
// Two non-ZST fields, and they're both scalars.
(
- Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref a), .. }, .. })),
- Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref b), .. }, .. })),
+ Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })),
+ Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })),
None,
) => {
// Order by the memory placement, not source order.
let ((i, a), (j, b)) =
if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) };
- let pair = self.scalar_pair(a.clone(), b.clone());
+ let pair = self.scalar_pair(a, b);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
let param_env = self.param_env;
let dl = self.data_layout();
let scalar_unit = |value: Primitive| {
- let bits = value.size(dl).bits();
- assert!(bits <= 128);
- Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } }
+ let size = value.size(dl);
+ assert!(size.bits() <= 128);
+ Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
};
let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
Abi::Aggregate { sized: true }
};
- let largest_niche = if count != 0 { element.largest_niche.clone() } else { None };
+ let largest_niche = if count != 0 { element.largest_niche } else { None };
tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
// Compute the ABI of the element type:
let e_ly = self.layout_of(e_ty)?;
- let e_abi = if let Abi::Scalar(ref scalar) = e_ly.abi {
- scalar.clone()
+ let e_abi = if let Abi::Scalar(scalar) = e_ly.abi {
+ scalar
} else {
// This error isn't caught in typeck, e.g., if
// the element type of the vector is generic.
variants: Variants::Single { index: VariantIdx::new(0) },
fields,
abi: Abi::Vector { element: e_abi, count: e_len },
- largest_niche: e_ly.largest_niche.clone(),
+ largest_niche: e_ly.largest_niche,
size,
align,
})
// If all non-ZST fields have the same ABI, forward this ABI
if optimize && !field.is_zst() {
// Normalize scalar_unit to the maximal valid range
- let field_abi = match &field.abi {
+ let field_abi = match field.abi {
Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
Abi::ScalarPair(x, y) => {
Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value))
}
Abi::Vector { element: x, count } => {
- Abi::Vector { element: scalar_unit(x.value), count: *count }
+ Abi::Vector { element: scalar_unit(x.value), count }
}
Abi::Uninhabited | Abi::Aggregate { .. } => {
Abi::Aggregate { sized: true }
Niche::from_scalar(dl, Size::ZERO, scalar.clone())
};
if let Some(niche) = niche {
- match &st.largest_niche {
+ match st.largest_niche {
Some(largest_niche) => {
// Replace the existing niche even if they're equal,
// because this one is at a lower offset.
let niche_candidate = variants[i]
.iter()
.enumerate()
- .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?)))
+ .filter_map(|(j, field)| Some((j, field.largest_niche?)))
.max_by_key(|(_, niche)| niche.available(dl));
if let Some((field_index, niche, (niche_start, niche_scalar))) =
Abi::Uninhabited
} else {
match st[i].abi {
- Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()),
- Abi::ScalarPair(ref first, ref second) => {
+ Abi::Scalar(_) => Abi::Scalar(niche_scalar),
+ Abi::ScalarPair(first, second) => {
// We need to use scalar_unit to reset the
// valid range to the maximal one for that
// primitive, because only the niche is
// guaranteed to be initialised, not the
// other primitive.
if offset.bytes() == 0 {
- Abi::ScalarPair(
- niche_scalar.clone(),
- scalar_unit(second.value),
- )
+ Abi::ScalarPair(niche_scalar, scalar_unit(second.value))
} else {
- Abi::ScalarPair(
- scalar_unit(first.value),
- niche_scalar.clone(),
- )
+ Abi::ScalarPair(scalar_unit(first.value), niche_scalar)
}
}
_ => Abi::Aggregate { sized: true },
}
};
- let largest_niche =
- Niche::from_scalar(dl, offset, niche_scalar.clone());
+ let largest_niche = Niche::from_scalar(dl, offset, niche_scalar);
niche_filling_layout = Some(Layout {
variants: Variants::Multiple {
}
}
- let tag_mask = !0u128 >> (128 - ity.size().bits());
+ let tag_mask = ity.size().unsigned_int_max();
let tag = Scalar {
value: Int(ity, signed),
valid_range: WrappingRange {
};
let mut abi = Abi::Aggregate { sized: true };
if tag.value.size(dl) == size {
- abi = Abi::Scalar(tag.clone());
+ abi = Abi::Scalar(tag);
} else {
// Try to use a ScalarPair for all tagged enums.
let mut common_prim = None;
}
};
let prim = match field.abi {
- Abi::Scalar(ref scalar) => scalar.value,
+ Abi::Scalar(scalar) => scalar.value,
_ => {
common_prim = None;
break;
}
}
if let Some((prim, offset)) = common_prim {
- let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
+ let pair = self.scalar_pair(tag, scalar_unit(prim));
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
abi = Abi::Uninhabited;
}
- let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone());
+ let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
let tagged_layout = Layout {
variants: Variants::Multiple {
// pick the layout with the larger niche; otherwise,
// pick tagged as it has simpler codegen.
cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| {
- let niche_size =
- layout.largest_niche.as_ref().map_or(0, |n| n.available(dl));
+ let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl));
(layout.size, cmp::Reverse(niche_size))
})
}
value: Primitive::Int(discr_int, false),
valid_range: WrappingRange { start: 0, end: max_discr },
};
- let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
+ let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag));
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
let promoted_layouts = ineligible_locals
}
}
- Variants::Multiple { ref tag, ref tag_encoding, .. } => {
+ Variants::Multiple { tag, ref tag_encoding, .. } => {
debug!(
"print-type-size `{:#?}` adt general variants def {}",
layout.ty,
}
}
+impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
+ fn target_spec(&self) -> &Target {
+ &self.sess.target
+ }
+}
+
impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
}
}
+impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+ fn target_spec(&self) -> &Target {
+ &self.sess.target
+ }
+}
+
impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
}
}
+impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> {
+ fn target_spec(&self) -> &Target {
+ self.tcx.target_spec()
+ }
+}
+
impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx.tcx()
#[inline]
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
+ let tcx = self.tcx().at(span);
+
MaybeResult::from(
- self.tcx()
- .at(span)
- .layout_of(self.param_env().and(ty))
+ tcx.layout_of(self.param_env().and(ty))
.map_err(|err| self.handle_layout_err(err, span, ty)),
)
}
i: usize,
) -> TyMaybeWithLayout<'tcx> {
let tcx = cx.tcx();
- let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> {
+ let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
let layout = Layout::scalar(cx, tag.clone());
TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
};
.nth(i)
.unwrap(),
),
- Variants::Multiple { ref tag, tag_field, .. } => {
+ Variants::Multiple { tag, tag_field, .. } => {
if i == tag_field {
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
}
}
// Discriminant field for enums (where applicable).
- Variants::Multiple { ref tag, .. } => {
+ Variants::Multiple { tag, .. } => {
assert_eq!(i, 0);
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
}
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
- #[inline]
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- use crate::ty::layout::LayoutError::*;
- mem::discriminant(self).hash_stable(hcx, hasher);
-
- match *self {
- Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher),
- }
- }
-}
-
impl<'tcx> ty::Instance<'tcx> {
// NOTE(eddyb) this is private to avoid using it from outside of
- // `FnAbi::of_instance` - any other uses are either too high-level
+ // `fn_abi_of_instance` - any other uses are either too high-level
// for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
// or should go through `FnAbi` instead, to avoid losing any
- // adjustments `FnAbi::of_instance` might be performing.
+ // adjustments `fn_abi_of_instance` might be performing.
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
// FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
}
}
-pub trait FnAbiExt<'tcx, C>
-where
- C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
-{
- /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
- ///
- /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance`
- /// instead, where the instance is an `InstanceDef::Virtual`.
- fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
-
- /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
- /// direct calls to an `fn`.
- ///
- /// NB: that includes virtual calls, which are represented by "direct calls"
- /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
- fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
-
- fn new_internal(
- cx: &C,
- sig: ty::PolyFnSig<'tcx>,
- extra_args: &[Ty<'tcx>],
- caller_location: Option<Ty<'tcx>>,
- codegen_fn_attr_flags: CodegenFnAttrFlags,
- make_self_ptr_thin: bool,
- ) -> Self;
- fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
-}
-
/// Calculates whether a function's ABI can unwind or not.
///
/// This takes two primary parameters:
}
}
-impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
-where
- C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
-{
- fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
- call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
+/// Error produced by attempting to compute or adjust a `FnAbi`.
+#[derive(Clone, Debug, HashStable)]
+pub enum FnAbiError<'tcx> {
+ /// Error produced by a `layout_of` call, while computing `FnAbi` initially.
+ Layout(LayoutError<'tcx>),
+
+ /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
+ AdjustForForeignAbi(call::AdjustForForeignAbiError),
+}
+
+impl From<LayoutError<'tcx>> for FnAbiError<'tcx> {
+ fn from(err: LayoutError<'tcx>) -> Self {
+ Self::Layout(err)
}
+}
- fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
- let sig = instance.fn_sig_for_fn_abi(cx.tcx());
+impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
+ fn from(err: call::AdjustForForeignAbiError) -> Self {
+ Self::AdjustForForeignAbi(err)
+ }
+}
- let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
- Some(cx.tcx().caller_location_ty())
- } else {
- None
- };
+impl<'tcx> fmt::Display for FnAbiError<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Layout(err) => err.fmt(f),
+ Self::AdjustForForeignAbi(err) => err.fmt(f),
+ }
+ }
+}
+
+// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
+// just for error handling.
+#[derive(Debug)]
+pub enum FnAbiRequest<'tcx> {
+ OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
+ OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
+}
+
+/// Trait for contexts that want to be able to compute `FnAbi`s.
+/// This automatically gives access to `FnAbiOf`, through a blanket `impl`.
+pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
+ /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be
+ /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`).
+ type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>;
- let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
+ /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a
+ /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
+ ///
+ /// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`,
+ /// but this hook allows e.g. codegen to return only `&FnAbi` from its
+ /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with
+ /// (and any `FnAbiError`s are turned into fatal errors or ICEs).
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error;
+}
+
+/// Blanket extension trait for contexts that can compute `FnAbi`s.
+pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
+ /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
+ ///
+ /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
+ /// instead, where the instance is an `InstanceDef::Virtual`.
+ #[inline]
+ fn fn_abi_of_fn_ptr(
+ &self,
+ sig: ty::PolyFnSig<'tcx>,
+ extra_args: &'tcx ty::List<Ty<'tcx>>,
+ ) -> Self::FnAbiOfResult {
+ // FIXME(eddyb) get a better `span` here.
+ let span = self.layout_tcx_at_span();
+ let tcx = self.tcx().at(span);
+
+ MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
+ |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+ ))
+ }
- call::FnAbi::new_internal(
- cx,
- sig,
- extra_args,
- caller_location,
- attrs,
- matches!(instance.def, ty::InstanceDef::Virtual(..)),
+ /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
+ /// direct calls to an `fn`.
+ ///
+ /// NB: that includes virtual calls, which are represented by "direct calls"
+ /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+ #[inline]
+ fn fn_abi_of_instance(
+ &self,
+ instance: ty::Instance<'tcx>,
+ extra_args: &'tcx ty::List<Ty<'tcx>>,
+ ) -> Self::FnAbiOfResult {
+ // FIXME(eddyb) get a better `span` here.
+ let span = self.layout_tcx_at_span();
+ let tcx = self.tcx().at(span);
+
+ MaybeResult::from(
+ tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
+ // HACK(eddyb) at least for definitions of/calls to `Instance`s,
+ // we can get some kind of span even if one wasn't provided.
+ // However, we don't do this early in order to avoid calling
+ // `def_span` unconditionally (which may have a perf penalty).
+ let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
+ self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
+ }),
)
}
+}
- fn new_internal(
- cx: &C,
+impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
+
+fn fn_abi_of_fn_ptr<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ let (param_env, (sig, extra_args)) = query.into_parts();
+
+ LayoutCx { tcx, param_env }.fn_abi_new_uncached(
+ sig,
+ extra_args,
+ None,
+ CodegenFnAttrFlags::empty(),
+ false,
+ )
+}
+
+fn fn_abi_of_instance<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ let (param_env, (instance, extra_args)) = query.into_parts();
+
+ let sig = instance.fn_sig_for_fn_abi(tcx);
+
+ let caller_location = if instance.def.requires_caller_location(tcx) {
+ Some(tcx.caller_location_ty())
+ } else {
+ None
+ };
+
+ let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;
+
+ LayoutCx { tcx, param_env }.fn_abi_new_uncached(
+ sig,
+ extra_args,
+ caller_location,
+ attrs,
+ matches!(instance.def, ty::InstanceDef::Virtual(..)),
+ )
+}
+
+impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
+ // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
+ // arguments of this method, into a separate `struct`.
+ fn fn_abi_new_uncached(
+ &self,
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
+ // FIXME(eddyb) replace this with something typed, like an `enum`.
force_thin_self_ptr: bool,
- ) -> Self {
- debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
+ ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args);
- let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+ let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
- let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
+ let conv = conv_from_spec_abi(self.tcx(), sig.abi);
let mut inputs = sig.inputs();
let extra_args = if sig.abi == RustCall {
extra_args.to_vec()
};
- let target = &cx.tcx().sess.target;
+ let target = &self.tcx.sess.target;
let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
let linux_s390x_gnu_like =
// Handle safe Rust thin and fat pointers.
let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
- scalar: &Scalar,
+ scalar: Scalar,
layout: TyAndLayout<'tcx>,
offset: Size,
is_return: bool| {
return;
}
- if !scalar.valid_range.contains_zero() {
+ if !scalar.valid_range.contains(0) {
attrs.set(ArgAttribute::NonNull);
}
- if let Some(pointee) = layout.pointee_info_at(cx, offset) {
+ if let Some(pointee) = layout.pointee_info_at(self, offset) {
if let Some(kind) = pointee.safe {
attrs.pointee_align = Some(pointee.align);
}
};
- let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
+ let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
let is_return = arg_idx.is_none();
- let layout = cx.layout_of(ty);
+ let layout = self.layout_of(ty)?;
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
- make_thin_self_ptr(cx, layout)
+ make_thin_self_ptr(self, layout)
} else {
layout
};
- let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
+ let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
let mut attrs = ArgAttributes::new();
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
attrs
}
}
- arg
+ Ok(arg)
};
let mut fn_abi = FnAbi {
- ret: arg_of(sig.output(), None),
+ ret: arg_of(sig.output(), None)?,
args: inputs
.iter()
.cloned()
.chain(caller_location)
.enumerate()
.map(|(i, ty)| arg_of(ty, Some(i)))
- .collect(),
+ .collect::<Result<_, _>>()?,
c_variadic: sig.c_variadic,
fixed_count: inputs.len(),
conv,
- can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi),
+ can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
};
- fn_abi.adjust_for_abi(cx, sig.abi);
- debug!("FnAbi::new_internal = {:?}", fn_abi);
- fn_abi
+ self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
+ debug!("fn_abi_new_uncached = {:?}", fn_abi);
+ Ok(self.tcx.arena.alloc(fn_abi))
}
- fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
+ fn fn_abi_adjust_for_abi(
+ &self,
+ fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
+ abi: SpecAbi,
+ ) -> Result<(), FnAbiError<'tcx>> {
if abi == SpecAbi::Unadjusted {
- return;
+ return Ok(());
}
if abi == SpecAbi::Rust
// anyway, we control all calls to it in libstd.
Abi::Vector { .. }
if abi != SpecAbi::PlatformIntrinsic
- && cx.tcx().sess.target.simd_types_indirect =>
+ && self.tcx.sess.target.simd_types_indirect =>
{
arg.make_indirect();
return;
// Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`.
// LLVM will usually pass these in 2 registers, which is more efficient than by-ref.
- let max_by_val_size = Pointer.size(cx) * 2;
+ let max_by_val_size = Pointer.size(self) * 2;
let size = arg.layout.size;
if arg.layout.is_unsized() || size > max_by_val_size {
arg.cast_to(Reg { kind: RegKind::Integer, size });
}
};
- fixup(&mut self.ret);
- for arg in &mut self.args {
+ fixup(&mut fn_abi.ret);
+ for arg in &mut fn_abi.args {
fixup(arg);
}
- return;
+ } else {
+ fn_abi.adjust_for_foreign_abi(self, abi)?;
}
- if let Err(msg) = self.adjust_for_cabi(cx, abi) {
- cx.tcx().sess.fatal(&msg);
- }
+ Ok(())
}
}
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
- pub export_map: ExportMap<LocalDefId>,
+ pub export_map: ExportMap,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub struct Destructor {
/// The `DefId` of the destructor method
pub did: DefId,
+ /// The constness of the destructor method
+ pub constness: hir::Constness,
}
bitflags! {
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
+use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
use rustc_ast as ast;
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
}
+ (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
+ if a.ty.is_ref() || b.ty.is_ref() =>
+ {
+ if a.ty.is_ref() && b.ty.is_ref() {
+ alloc_a == alloc_b
+ } else {
+ false
+ }
+ }
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
}
}
-fn signed_min(size: Size) -> i128 {
- size.sign_extend(1_u128 << (size.bits() - 1)) as i128
-}
-
-fn signed_max(size: Size) -> i128 {
- i128::MAX >> (128 - size.bits())
-}
-
-fn unsigned_max(size: Size) -> u128 {
- u128::MAX >> (128 - size.bits())
-}
-
fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
let (int, signed) = match *ty.kind() {
Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
let (size, signed) = int_size_and_signed(tcx, self.ty);
let (val, oflo) = if signed {
- let min = signed_min(size);
- let max = signed_max(size);
+ let min = size.signed_int_min();
+ let max = size.signed_int_max();
let val = size.sign_extend(self.val) as i128;
assert!(n < (i128::MAX as u128));
let n = n as i128;
let val = size.truncate(val);
(val, oflo)
} else {
- let max = unsigned_max(size);
+ let max = size.unsigned_int_max();
let val = self.val;
let oflo = val > max - n;
let val = if oflo { n - (max - val) - 1 } else { val + n };
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did);
- let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
+ let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
if validate(self, impl_did).is_ok() {
- return Some(item.def_id);
+ return Some((item.def_id, self.impl_constness(impl_did)));
}
}
None
- });
+ })?;
- Some(ty::Destructor { did: dtor_did? })
+ Some(ty::Destructor { did, constness })
}
/// Returns the set of types that are required to be alive in
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
let (size, signed) = int_size_and_signed(tcx, self);
- let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+ let val =
+ if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() };
Some(val)
}
ty::Char => Some(std::char::MAX as u128),
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
let (size, signed) = int_size_and_signed(tcx, self);
- let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
+ let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 };
Some(val)
}
ty::Char => Some(0),
[package]
name = "rustc_mir_build"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
- self.as_operand(block, Some(local_scope), expr)
+ self.as_operand(block, Some(local_scope), expr, None)
}
/// Returns an operand suitable for use until the end of the current scope expression and
/// temporary `tmp = x`, so that we capture the value of `x` at
/// this time.
///
+ /// If we end up needing to create a temporary, then we will use
+ /// `local_info` as its `LocalInfo`, unless `as_temporary`
+ /// has already assigned it a non-`None` `LocalInfo`.
+ /// Normally, you should use `None` for `local_info`
+ ///
/// The operand is known to be live until the end of `scope`.
///
/// Like `as_local_call_operand`, except that the argument will
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: &Expr<'tcx>,
+ local_info: Option<Box<LocalInfo<'tcx>>>,
) -> BlockAnd<Operand<'tcx>> {
- debug!("as_operand(block={:?}, expr={:?})", block, expr);
+ debug!("as_operand(block={:?}, expr={:?} local_info={:?})", block, expr, local_info);
let this = self;
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
let source_info = this.source_info(expr.span);
let region_scope = (region_scope, source_info);
return this.in_scope(region_scope, lint_level, |this| {
- this.as_operand(block, scope, &this.thir[value])
+ this.as_operand(block, scope, &this.thir[value], local_info)
});
}
}
Category::Place | Category::Rvalue(..) => {
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
+ if this.local_decls[operand].local_info.is_none() {
+ this.local_decls[operand].local_info = local_info;
+ }
block.and(Operand::Move(Place::from(operand)))
}
}
}
}
- this.as_operand(block, scope, expr)
+ this.as_operand(block, scope, expr, None)
}
}
}
ExprKind::Repeat { value, count } => {
let value_operand =
- unpack!(block = this.as_operand(block, scope, &this.thir[value]));
+ unpack!(block = this.as_operand(block, scope, &this.thir[value], None));
block.and(Rvalue::Repeat(value_operand, count))
}
ExprKind::Binary { op, lhs, rhs } => {
- let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs]));
- let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs]));
+ let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs], None));
+ let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs], None));
this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
}
ExprKind::Unary { op, arg } => {
- let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg]));
+ let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg], None));
// Check for -MIN on signed integers
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
let bool_ty = this.tcx.types.bool;
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
}
ExprKind::Cast { source } => {
- let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
+ let source =
+ unpack!(block = this.as_operand(block, scope, &this.thir[source], None));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
}
ExprKind::Pointer { cast, source } => {
- let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
+ let source =
+ unpack!(block = this.as_operand(block, scope, &this.thir[source], None));
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
}
ExprKind::Array { ref fields } => {
let fields: Vec<_> = fields
.into_iter()
.copied()
- .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
+ .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None)))
.collect();
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(el_ty)), fields))
let fields: Vec<_> = fields
.into_iter()
.copied()
- .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
+ .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None)))
.collect();
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields))
&this.thir[arg],
)
),
- _ => unpack!(block = this.as_operand(block, scope, upvar)),
+ _ => {
+ unpack!(block = this.as_operand(block, scope, upvar, None))
+ }
}
}
}
Category::of(&expr.kind),
Some(Category::Rvalue(RvalueFunc::AsRvalue))
));
- let operand = unpack!(block = this.as_operand(block, scope, expr));
+ let operand = unpack!(block = this.as_operand(block, scope, expr, None));
block.and(Rvalue::Use(operand))
}
}
// Helper to get a `-1` value of the appropriate type
fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
let param_ty = ty::ParamEnv::empty().and(ty);
- let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
- let n = (!0u128) >> (128 - bits);
- let literal = ty::Const::from_bits(self.tcx, n, param_ty);
+ let size = self.tcx.layout_of(param_ty).unwrap().size;
+ let literal = ty::Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
self.literal_operand(span, literal)
}
let fields_map: FxHashMap<_, _> = fields
.into_iter()
.map(|f| {
+ let local_info = Box::new(LocalInfo::AggregateTemp);
(
f.name,
unpack!(
- block = this.as_operand(block, Some(scope), &this.thir[f.expr])
+ block = this.as_operand(
+ block,
+ Some(scope),
+ &this.thir[f.expr],
+ Some(local_info)
+ )
),
)
})
ExprKind::Yield { value } => {
let scope = this.local_scope();
- let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value]));
+ let value =
+ unpack!(block = this.as_operand(block, Some(scope), &this.thir[value], None));
let resume = this.cfg.start_new_block();
this.cfg.terminate(
block,
struct Binding<'tcx> {
span: Span,
source: Place<'tcx>,
- name: Symbol,
var_id: HirId,
- var_ty: Ty<'tcx>,
- mutability: Mutability,
binding_mode: BindingMode,
}
source_info.span, ascription.source, ascription.user_ty,
);
- let user_ty = ascription.user_ty.clone().user_ty(
+ let user_ty = ascription.user_ty.user_ty(
&mut self.canonical_user_type_annotations,
ascription.source.ty(&self.local_decls, self.tcx).ty,
source_info.span,
Ok(())
}
- PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
+ PatKind::Binding {
+ name: _,
+ mutability: _,
+ mode,
+ var,
+ ty: _,
+ ref subpattern,
+ is_primary: _,
+ } => {
if let Ok(place_resolved) =
match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
{
candidate.bindings.push(Binding {
- name,
- mutability,
span: match_pair.pattern.span,
source: place_resolved.into_place(self.tcx, self.typeck_results),
var_id: var,
- var_ty: ty,
binding_mode: mode,
});
}
let body_owner_kind = tcx.hir().body_owner_kind(id);
let typeck_results = tcx.typeck_opt_const_arg(def);
- // Ensure unsafeck is ran before we steal the THIR.
+ // Ensure unsafeck and abstract const building is ran before we steal the THIR.
+ // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
+ // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
+ // THIR has been stolen if we haven't computed this query yet.
match def {
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
- tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did))
+ tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
+ drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did)));
}
ty::WithOptConstParam { did, const_param_did: None } => {
- tcx.ensure().thir_check_unsafety(did)
+ tcx.ensure().thir_check_unsafety(did);
+ drop(tcx.thir_abstract_const(did));
}
}
/// the region span of this scope within source code.
region_scope: region::Scope,
- /// the span of that region_scope
- region_scope_span: Span,
-
/// set of places to drop when exiting this scope. This starts
/// out empty but grows as variables are declared during the
/// building process. This is a stack, so we always drop from the
self.scopes.push(Scope {
source_scope: vis_scope,
region_scope: region_scope.0,
- region_scope_span: region_scope.1.span,
drops: vec![],
moved_locals: vec![],
cached_unwind_block: None,
use crate::build::ExprCategory;
-use crate::thir::visit::{self, Visitor};
+use rustc_middle::thir::visit::{self, Visitor};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
crate mod pattern;
mod util;
-pub mod visit;
use rustc_hir::{HirId, Pat};
use rustc_middle::thir::PatKind;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
-use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
+use rustc_session::lint::builtin::{
+ BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
+};
use rustc_session::Session;
use rustc_span::{DesugaringKind, ExpnKind, Span};
use std::slice;
err.emit();
}
-fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
+crate fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
const LIMIT: usize = 3;
match witnesses {
[] => bug!(),
}
}
-fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
+crate fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns)
}
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
- let msg = format!(
- "to use a constant of type `{}` in a pattern, \
- `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
- cv.ty, cv.ty,
- );
tcx.struct_span_lint_hir(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id,
span,
- |lint| lint.build(&msg).emit(),
+ |lint| {
+ let msg = format!(
+ "to use a constant of type `{}` in a pattern, \
+ `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+ cv.ty, cv.ty,
+ );
+ lint.build(&msg).emit()
+ },
);
}
// Since we are behind a reference, we can just bubble the error up so we get a
/// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
NonExhaustive,
/// Stands for constructors that are not seen in the matrix, as explained in the documentation
- /// for [`SplitWildcard`].
- Missing,
+ /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns`
+ /// lint.
+ Missing { nonexhaustive_enum_missing_real_variants: bool },
/// Wildcard pattern.
Wildcard,
}
matches!(self, Wildcard)
}
+ pub(super) fn is_non_exhaustive(&self) -> bool {
+ matches!(self, NonExhaustive)
+ }
+
fn as_int_range(&self) -> Option<&IntRange> {
match self {
IntRange(range) => Some(range),
// Wildcards cover anything
(_, Wildcard) => true,
// The missing ctors are not covered by anything in the matrix except wildcards.
- (Missing | Wildcard, _) => false,
+ (Missing { .. } | Wildcard, _) => false,
(Single, Single) => true,
(Variant(self_id), Variant(other_id)) => self_id == other_id,
.any(|other| slice.is_covered_by(other)),
// This constructor is never covered by anything else
NonExhaustive => false,
- Str(..) | FloatRange(..) | Opaque | Missing | Wildcard => {
+ Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard => {
span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self)
}
}
&& !cx.tcx.features().exhaustive_patterns
&& !pcx.is_top_level;
- if is_secretly_empty || is_declared_nonexhaustive {
+ if is_secretly_empty {
smallvec![NonExhaustive]
+ } else if is_declared_nonexhaustive {
+ def.variants
+ .indices()
+ .map(|idx| Variant(idx))
+ .chain(Some(NonExhaustive))
+ .collect()
} else if cx.tcx.features().exhaustive_patterns {
// If `exhaustive_patterns` is enabled, we exclude variants known to be
// uninhabited.
// This type is one for which we cannot list constructors, like `str` or `f64`.
_ => smallvec![NonExhaustive],
};
+
SplitWildcard { matrix_ctors: Vec::new(), all_ctors }
}
// sometimes prefer reporting the list of constructors instead of just `_`.
let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing {
- Missing
+ if pcx.is_non_exhaustive {
+ Missing {
+ nonexhaustive_enum_missing_real_variants: self
+ .iter_missing(pcx)
+ .filter(|c| !c.is_non_exhaustive())
+ .next()
+ .is_some(),
+ }
+ } else {
+ Missing { nonexhaustive_enum_missing_real_variants: false }
+ }
} else {
Wildcard
};
}
_ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
},
- Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Missing
+ Str(..)
+ | FloatRange(..)
+ | IntRange(..)
+ | NonExhaustive
+ | Opaque
+ | Missing { .. }
| Wildcard => Fields::Slice(&[]),
};
debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
/// This is roughly the inverse of `specialize_constructor`.
///
/// Examples:
- /// `ctor`: `Constructor::Single`
- /// `ty`: `Foo(u32, u32, u32)`
- /// `self`: `[10, 20, _]`
+ ///
+ /// ```text
+ /// ctor: `Constructor::Single`
+ /// ty: `Foo(u32, u32, u32)`
+ /// self: `[10, 20, _]`
/// returns `Foo(10, 20, _)`
///
- /// `ctor`: `Constructor::Variant(Option::Some)`
- /// `ty`: `Option<bool>`
- /// `self`: `[false]`
+ /// ctor: `Constructor::Variant(Option::Some)`
+ /// ty: `Option<bool>`
+ /// self: `[false]`
/// returns `Some(false)`
+ /// ```
pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Pat<'tcx> {
let subpatterns_and_indices = self.patterns_and_indices();
let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p).cloned();
NonExhaustive => PatKind::Wild,
Wildcard => return Pat::wildcard_from_ty(pcx.ty),
Opaque => bug!("we should not try to apply an opaque constructor"),
- Missing => bug!(
+ Missing { .. } => bug!(
"trying to apply the `Missing` constructor; this should have been done in `apply_constructors`"
),
};
//! The details are not necessary to understand this file, so we explain them in
//! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function.
+use self::ArmType::*;
use self::Usefulness::*;
-use self::WitnessPreference::*;
+use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
use super::deconstruct_pat::{Constructor, Fields, SplitWildcard};
use super::{PatternFoldable, PatternFolder};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
+use hir::def_id::DefId;
+use hir::HirId;
use rustc_arena::TypedArena;
-use rustc_hir::def_id::DefId;
-use rustc_hir::HirId;
+use rustc_hir as hir;
use rustc_middle::thir::{Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
/// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
/// subpattern.
pub(super) is_top_level: bool,
+ /// Wether the current pattern is from a `non_exhaustive` enum.
+ pub(super) is_non_exhaustive: bool,
}
impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
/// of potential unreachable sub-patterns (in the presence of or-patterns). When checking
/// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of
/// witnesses of non-exhaustiveness when there are any.
-/// Which variant to use is dictated by `WitnessPreference`.
+/// Which variant to use is dictated by `ArmType`.
#[derive(Clone, Debug)]
enum Usefulness<'p, 'tcx> {
/// Carries a set of subpatterns that have been found to be reachable. If empty, this indicates
}
impl<'p, 'tcx> Usefulness<'p, 'tcx> {
- fn new_useful(preference: WitnessPreference) -> Self {
+ fn new_useful(preference: ArmType) -> Self {
match preference {
- ConstructWitness => WithWitnesses(vec![Witness(vec![])]),
- LeaveOutWitness => NoWitnesses(SubPatSet::full()),
+ FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]),
+ RealArm => NoWitnesses(SubPatSet::full()),
}
}
- fn new_not_useful(preference: WitnessPreference) -> Self {
+
+ fn new_not_useful(preference: ArmType) -> Self {
match preference {
- ConstructWitness => WithWitnesses(vec![]),
- LeaveOutWitness => NoWitnesses(SubPatSet::empty()),
+ FakeExtraWildcard => WithWitnesses(vec![]),
+ RealArm => NoWitnesses(SubPatSet::empty()),
+ }
+ }
+
+ fn is_useful(&self) -> bool {
+ match self {
+ Usefulness::NoWitnesses(set) => !set.is_empty(),
+ Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(),
}
}
/// When trying several branches and each returns a `Usefulness`, we need to combine the
/// results together.
- fn merge(pref: WitnessPreference, usefulnesses: impl Iterator<Item = Self>) -> Self {
+ fn merge(pref: ArmType, usefulnesses: impl Iterator<Item = Self>) -> Self {
let mut ret = Self::new_not_useful(pref);
for u in usefulnesses {
ret.extend(u);
}
}
- /// After calculating usefulness after a specialization, call this to recontruct a usefulness
+ /// After calculating usefulness after a specialization, call this to reconstruct a usefulness
/// that makes sense for the matrix pre-specialization. This new usefulness can then be merged
/// with the results of specializing with the other constructors.
fn apply_constructor(
match self {
WithWitnesses(witnesses) if witnesses.is_empty() => WithWitnesses(witnesses),
WithWitnesses(witnesses) => {
- let new_witnesses = if matches!(ctor, Constructor::Missing) {
- let mut split_wildcard = SplitWildcard::new(pcx);
- split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
- // Construct for each missing constructor a "wild" version of this
- // constructor, that matches everything that can be built with
- // it. For example, if `ctor` is a `Constructor::Variant` for
- // `Option::Some`, we get the pattern `Some(_)`.
- let new_patterns: Vec<_> = split_wildcard
- .iter_missing(pcx)
- .map(|missing_ctor| {
- Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
- })
- .collect();
+ let new_witnesses = if let Constructor::Missing { .. } = ctor {
+ // We got the special `Missing` constructor, so each of the missing constructors
+ // gives a new pattern that is not caught by the match. We list those patterns.
+ let new_patterns = if pcx.is_non_exhaustive {
+ // Here we don't want the user to try to list all variants, we want them to add
+ // a wildcard, so we only suggest that.
+ vec![
+ Fields::wildcards(pcx, &Constructor::NonExhaustive)
+ .apply(pcx, &Constructor::NonExhaustive),
+ ]
+ } else {
+ let mut split_wildcard = SplitWildcard::new(pcx);
+ split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+ // Construct for each missing constructor a "wild" version of this
+ // constructor, that matches everything that can be built with
+ // it. For example, if `ctor` is a `Constructor::Variant` for
+ // `Option::Some`, we get the pattern `Some(_)`.
+ split_wildcard
+ .iter_missing(pcx)
+ .map(|missing_ctor| {
+ Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+ })
+ .collect()
+ };
+
witnesses
.into_iter()
.flat_map(|witness| {
}
#[derive(Copy, Clone, Debug)]
-enum WitnessPreference {
- ConstructWitness,
- LeaveOutWitness,
+enum ArmType {
+ FakeExtraWildcard,
+ RealArm,
}
/// A witness of non-exhaustiveness for error reporting, represented
}
}
+/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+/// is not exhaustive enough.
+///
+/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
+fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ scrut_ty: Ty<'tcx>,
+ sp: Span,
+ hir_id: HirId,
+ witnesses: Vec<Pat<'tcx>>,
+) {
+ let joined_patterns = joined_uncovered_patterns(&witnesses);
+ cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| {
+ let mut lint = build.build("some variants are not matched explicitly");
+ lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+ lint.help(
+ "ensure that all variants are matched explicitly by adding the suggested match arms",
+ );
+ lint.note(&format!(
+ "the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+ scrut_ty,
+ ));
+ lint.emit();
+ });
+}
+
/// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
/// The algorithm from the paper has been modified to correctly handle empty
/// types. The changes are:
cx: &MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
v: &PatStack<'p, 'tcx>,
- witness_preference: WitnessPreference,
+ witness_preference: ArmType,
hir_id: HirId,
is_under_guard: bool,
is_top_level: bool,
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
let ty = matrix.heads().next().map_or(v.head().ty, |r| r.ty);
- let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
+ let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
+ let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level, is_non_exhaustive };
// If the first pattern is an or-pattern, expand it.
let ret = if is_or_pat(v.head()) {
}
// We split the head constructor of `v`.
let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx));
+ let is_non_exhaustive_and_wild = is_non_exhaustive && v_ctor.is_wildcard();
// For each constructor, we compute whether there's a value that starts with it that would
// witness the usefulness of `v`.
let start_matrix = &matrix;
let v = v.pop_head_constructor(&ctor_wild_subpatterns);
let usefulness =
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
+
+ // When all the conditions are met we have a match with a `non_exhaustive` enum
+ // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
+ // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
+ if is_non_exhaustive_and_wild
+ // We check that the match has a wildcard pattern and that that wildcard is useful,
+ // meaning there are variants that are covered by the wildcard. Without the check
+ // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
+ && usefulness.is_useful() && matches!(witness_preference, RealArm)
+ && matches!(
+ &ctor,
+ Constructor::Missing { nonexhaustive_enum_missing_real_variants: true }
+ )
+ {
+ let patterns = {
+ let mut split_wildcard = SplitWildcard::new(pcx);
+ split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+ // Construct for each missing constructor a "wild" version of this
+ // constructor, that matches everything that can be built with
+ // it. For example, if `ctor` is a `Constructor::Variant` for
+ // `Option::Some`, we get the pattern `Some(_)`.
+ split_wildcard
+ .iter_missing(pcx)
+ // Filter out the `Constructor::NonExhaustive` variant it's meaningless
+ // to our lint
+ .filter(|c| !c.is_non_exhaustive())
+ .map(|missing_ctor| {
+ Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+ })
+ .collect::<Vec<_>>()
+ };
+
+ lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns);
+ }
+
usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
});
Usefulness::merge(witness_preference, usefulnesses)
};
+
debug!(?ret);
ret
}
.copied()
.map(|arm| {
let v = PatStack::from_pattern(arm.pat);
- let usefulness =
- is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true);
+ let usefulness = is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true);
if !arm.has_guard {
matrix.push(v);
}
let wild_pattern = cx.pattern_arena.alloc(Pat::wildcard_from_ty(scrut_ty));
let v = PatStack::from_pattern(wild_pattern);
- let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
+ let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true);
let non_exhaustiveness_witnesses = match usefulness {
WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
NoWitnesses(_) => bug!(),
+++ /dev/null
-use rustc_middle::thir::{self, *};
-use rustc_middle::ty::Const;
-
-pub trait Visitor<'a, 'tcx: 'a>: Sized {
- fn thir(&self) -> &'a Thir<'tcx>;
-
- fn visit_expr(&mut self, expr: &Expr<'tcx>) {
- walk_expr(self, expr);
- }
-
- fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
- walk_stmt(self, stmt);
- }
-
- fn visit_block(&mut self, block: &Block) {
- walk_block(self, block);
- }
-
- fn visit_arm(&mut self, arm: &Arm<'tcx>) {
- walk_arm(self, arm);
- }
-
- fn visit_pat(&mut self, pat: &Pat<'tcx>) {
- walk_pat(self, pat);
- }
-
- fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
-}
-
-pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
- use ExprKind::*;
- match expr.kind {
- Scope { value, region_scope: _, lint_level: _ } => {
- visitor.visit_expr(&visitor.thir()[value])
- }
- Box { value } => visitor.visit_expr(&visitor.thir()[value]),
- If { cond, then, else_opt, if_then_scope: _ } => {
- visitor.visit_expr(&visitor.thir()[cond]);
- visitor.visit_expr(&visitor.thir()[then]);
- if let Some(else_expr) = else_opt {
- visitor.visit_expr(&visitor.thir()[else_expr]);
- }
- }
- Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
- visitor.visit_expr(&visitor.thir()[fun]);
- for &arg in &**args {
- visitor.visit_expr(&visitor.thir()[arg]);
- }
- }
- Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
- Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
- visitor.visit_expr(&visitor.thir()[lhs]);
- visitor.visit_expr(&visitor.thir()[rhs]);
- }
- Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
- Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
- Use { source } => visitor.visit_expr(&visitor.thir()[source]),
- NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
- Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
- Let { expr, .. } => {
- visitor.visit_expr(&visitor.thir()[expr]);
- }
- Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
- Match { scrutinee, ref arms } => {
- visitor.visit_expr(&visitor.thir()[scrutinee]);
- for &arm in &**arms {
- visitor.visit_arm(&visitor.thir()[arm]);
- }
- }
- Block { ref body } => visitor.visit_block(body),
- Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
- visitor.visit_expr(&visitor.thir()[lhs]);
- visitor.visit_expr(&visitor.thir()[rhs]);
- }
- Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
- Index { lhs, index } => {
- visitor.visit_expr(&visitor.thir()[lhs]);
- visitor.visit_expr(&visitor.thir()[index]);
- }
- VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
- Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
- AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
- Break { value, label: _ } => {
- if let Some(value) = value {
- visitor.visit_expr(&visitor.thir()[value])
- }
- }
- Continue { label: _ } => {}
- Return { value } => {
- if let Some(value) = value {
- visitor.visit_expr(&visitor.thir()[value])
- }
- }
- ConstBlock { value } => visitor.visit_const(value),
- Repeat { value, count } => {
- visitor.visit_expr(&visitor.thir()[value]);
- visitor.visit_const(count);
- }
- Array { ref fields } | Tuple { ref fields } => {
- for &field in &**fields {
- visitor.visit_expr(&visitor.thir()[field]);
- }
- }
- Adt(box thir::Adt {
- ref fields,
- ref base,
- adt_def: _,
- variant_index: _,
- substs: _,
- user_ty: _,
- }) => {
- for field in &**fields {
- visitor.visit_expr(&visitor.thir()[field.expr]);
- }
- if let Some(base) = base {
- visitor.visit_expr(&visitor.thir()[base.base]);
- }
- }
- PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
- visitor.visit_expr(&visitor.thir()[source])
- }
- Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
- Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
- StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
- InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
- for op in &**operands {
- use InlineAsmOperand::*;
- match op {
- In { expr, reg: _ }
- | Out { expr: Some(expr), reg: _, late: _ }
- | InOut { expr, reg: _, late: _ }
- | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
- SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
- visitor.visit_expr(&visitor.thir()[*in_expr]);
- if let Some(out_expr) = out_expr {
- visitor.visit_expr(&visitor.thir()[*out_expr]);
- }
- }
- Out { expr: None, reg: _, late: _ }
- | Const { value: _, span: _ }
- | SymStatic { def_id: _ } => {}
- }
- }
- }
- ThreadLocalRef(_) => {}
- LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
- for &out_expr in &**outputs {
- visitor.visit_expr(&visitor.thir()[out_expr]);
- }
- for &in_expr in &**inputs {
- visitor.visit_expr(&visitor.thir()[in_expr]);
- }
- }
- Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
- }
-}
-
-pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
- match &stmt.kind {
- StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
- StmtKind::Let {
- initializer,
- remainder_scope: _,
- init_scope: _,
- ref pattern,
- lint_level: _,
- } => {
- if let Some(init) = initializer {
- visitor.visit_expr(&visitor.thir()[*init]);
- }
- visitor.visit_pat(pattern);
- }
- }
-}
-
-pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
- for &stmt in &*block.stmts {
- visitor.visit_stmt(&visitor.thir()[stmt]);
- }
- if let Some(expr) = block.expr {
- visitor.visit_expr(&visitor.thir()[expr]);
- }
-}
-
-pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
- match arm.guard {
- Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
- Some(Guard::IfLet(ref pat, expr)) => {
- visitor.visit_pat(pat);
- visitor.visit_expr(&visitor.thir()[expr]);
- }
- None => {}
- }
- visitor.visit_pat(&arm.pattern);
- visitor.visit_expr(&visitor.thir()[arm.body]);
-}
-
-pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
- use PatKind::*;
- match pat.kind.as_ref() {
- AscribeUserType { subpattern, ascription: _ }
- | Deref { subpattern }
- | Binding {
- subpattern: Some(subpattern),
- mutability: _,
- mode: _,
- var: _,
- ty: _,
- is_primary: _,
- name: _,
- } => visitor.visit_pat(&subpattern),
- Binding { .. } | Wild => {}
- Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
- for subpattern in subpatterns {
- visitor.visit_pat(&subpattern.pattern);
- }
- }
- Constant { value } => visitor.visit_const(value),
- Range(range) => {
- visitor.visit_const(range.lo);
- visitor.visit_const(range.hi);
- }
- Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
- for subpattern in prefix {
- visitor.visit_pat(&subpattern);
- }
- if let Some(pat) = slice {
- visitor.visit_pat(pat);
- }
- for subpattern in suffix {
- visitor.visit_pat(&subpattern);
- }
- }
- Or { pats } => {
- for pat in pats {
- visitor.visit_pat(&pat);
- }
- }
- };
-}
[package]
name = "rustc_mir_dataflow"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
on_lookup_result_bits,
};
pub use self::framework::{
- fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, Forward,
- GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
+ fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
+ Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
ResultsVisitable, ResultsVisitor,
};
| Rvalue::AddressOf(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(..)
- | Rvalue::NullaryOp(NullOp::SizeOf, _)
+ | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
| Rvalue::NullaryOp(NullOp::Box, _) => {
// This returns an rvalue with uninitialized contents. We can't
// move out of it here because it is an rvalue - assignments always
[package]
name = "rustc_mir_transform"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use rustc_middle::ty::layout;
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::spec::abi::Abi;
+use rustc_target::spec::PanicStrategy;
/// A pass that runs which is targeted at ensuring that codegen guarantees about
/// unwinding are upheld for compilations of panic=abort programs.
};
layout::fn_can_unwind(tcx, flags, sig.abi())
}
- TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
- | TerminatorKind::Assert { .. }
- | TerminatorKind::FalseUnwind { .. } => {
+ TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+ tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
+ && layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
+ }
+ TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
}
_ => continue,
}
if let Err(e) = result {
- bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e)
+ bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message)
};
// Depending on current `debug_options()`, `alert_on_unused_expressions()` could panic, so
/// body_span), returns the macro name symbol.
pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
if let Some(current_macro) = self.current_macro() {
- if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt()
+ if self
+ .expn_span
+ .parent_callsite()
+ .unwrap_or_else(|| bug!("macro must have a parent"))
+ .ctxt()
== body_span.ctxt()
{
return Some(current_macro);
[package]
name = "coverage_test_macros"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
use rustc_const_eval::transform::check_consts;
use rustc_const_eval::transform::promote_consts;
use rustc_const_eval::transform::validate;
-use rustc_const_eval::transform::MirPass;
+pub use rustc_const_eval::transform::MirPass;
use rustc_mir_dataflow::rustc_peek;
pub fn provide(providers: &mut Providers) {
// this point, before we steal the mir-const result.
// Also this means promotion can rely on all const checks having been done.
let _ = tcx.mir_const_qualif_opt_const_arg(def);
- let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global());
let mut body = tcx.mir_const(def).steal();
let mut required_consts = Vec::new();
// since their semantics depend on the value of overflow-checks flag used
// during codegen. Issue #35310.
}
- sym::size_of => {
+ sym::size_of | sym::min_align_of => {
if let Some((destination, target)) = *destination {
let tp_ty = substs.type_at(0);
+ let null_op = match intrinsic_name {
+ sym::size_of => NullOp::SizeOf,
+ sym::min_align_of => NullOp::AlignOf,
+ _ => bug!("unexpected intrinsic"),
+ };
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((
destination,
- Rvalue::NullaryOp(NullOp::SizeOf, tp_ty),
+ Rvalue::NullaryOp(null_op, tp_ty),
))),
});
terminator.kind = TerminatorKind::Goto { target };
let deref_arg = tcx.mk_place_deref(arg);
let r_value = Rvalue::Len(deref_arg);
let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
- let add_statement = Statement {
- kind: len_statement_kind,
- source_info: terminator.source_info.clone(),
- };
+ let add_statement =
+ Statement { kind: len_statement_kind, source_info: terminator.source_info };
// modify terminator into simple Goto
- let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() };
+ let new_terminator_kind = TerminatorKind::Goto { target: *bb };
let patch = SliceLenPatchInformation { add_statement, new_terminator_kind };
impl<'tcx> MirPass<'tcx> for RemoveZsts {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ // Avoid query cycles (generators require optimized MIR for layout).
+ if tcx.type_of(body.source.def_id()).is_generator() {
+ return;
+ }
let param_env = tcx.param_env(body.source.def_id());
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
for block in basic_blocks.iter_mut() {
pub fn simplify(mut self) {
self.strip_nops();
- let mut start = START_BLOCK;
-
// Vec of the blocks that should be merged. We store the indices here, instead of the
// statements itself to avoid moving the (relatively) large statements twice.
// We do not push the statements directly into the target block (`bb`) as that is slower
loop {
let mut changed = false;
- self.collapse_goto_chain(&mut start, &mut changed);
-
for bb in self.basic_blocks.indices() {
if self.pred_count[bb] == 0 {
continue;
break;
}
}
-
- if start != START_BLOCK {
- debug_assert!(self.pred_count[START_BLOCK] == 0);
- self.basic_blocks.swap(START_BLOCK, start);
- self.pred_count.swap(START_BLOCK, start);
-
- // pred_count == 1 if the start block has no predecessor _blocks_.
- if self.pred_count[START_BLOCK] > 1 {
- for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
- if self.pred_count[bb] == 0 {
- continue;
- }
-
- for target in data.terminator_mut().successors_mut() {
- if *target == start {
- *target = START_BLOCK;
- }
- }
- }
- }
- }
}
/// This function will return `None` if
[package]
name = "rustc_monomorphize"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
/// Determine which generic parameters are used by the function/method/closure represented by
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
/// indicates all parameters are used).
-#[instrument(skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
if !tcx.sess.opts.debugging_opts.polymorphize {
// If polymorphization disabled, then all parameters are used.
/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
-#[instrument(skip(tcx, def_id, generics, unused_parameters))]
+#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))]
fn mark_used_by_default_parameters<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
/// Search the predicates on used generic parameters for any unused generic parameters, and mark
/// those as used.
-#[instrument(skip(tcx, def_id))]
+#[instrument(level = "debug", skip(tcx, def_id))]
fn mark_used_by_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
/// parameter which was unused.
-#[instrument(skip(tcx, generics))]
+#[instrument(level = "debug", skip(tcx, generics))]
fn emit_unused_generic_params_error<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
/// Invoke `unused_generic_params` on a body contained within the current item (e.g.
/// a closure, generator or constant).
- #[instrument(skip(self, def_id, substs))]
+ #[instrument(level = "debug", skip(self, def_id, substs))]
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
let unused = self.tcx.unused_generic_params(def_id);
debug!(?self.unused_parameters, ?unused);
}
impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
- #[instrument(skip(self, local))]
+ #[instrument(level = "debug", skip(self, local))]
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
if local == Local::from_usize(1) {
let def_kind = self.tcx.def_kind(self.def_id);
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
- #[instrument(skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.potentially_has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
}
- #[instrument(skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if !ty.potentially_has_param_types_or_consts() {
return ControlFlow::CONTINUE;
Some(self.tcx)
}
- #[instrument(skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.potentially_has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
}
- #[instrument(skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if !ty.potentially_has_param_types_or_consts() {
return ControlFlow::CONTINUE;
[package]
name = "rustc_parse"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use std::iter::once;
use std::ops::Range;
-use rustc_errors::{Applicability, Handler};
+use rustc_errors::{pluralize, Applicability, Handler};
use rustc_lexer::unescape::{EscapeError, Mode};
use rustc_span::{BytePos, Span};
.emit();
}
EscapeError::MoreThanOneChar => {
- let (prefix, msg) = if mode.is_bytes() {
- ("b", "if you meant to write a byte string literal, use double quotes")
- } else {
- ("", "if you meant to write a `str` literal, use double quotes")
- };
+ use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
- handler
- .struct_span_err(
- span_with_quotes,
- "character literal may only contain one codepoint",
- )
- .span_suggestion(
+ let mut has_help = false;
+ let mut handler = handler.struct_span_err(
+ span_with_quotes,
+ "character literal may only contain one codepoint",
+ );
+
+ if lit.chars().skip(1).all(|c| is_combining_mark(c)) {
+ let escaped_marks =
+ lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>();
+ handler.span_note(
+ span,
+ &format!(
+ "this `{}` is followed by the combining mark{} `{}`",
+ lit.chars().next().unwrap(),
+ pluralize!(escaped_marks.len()),
+ escaped_marks.join(""),
+ ),
+ );
+ let normalized = lit.nfc().to_string();
+ if normalized.chars().count() == 1 {
+ has_help = true;
+ handler.span_suggestion(
+ span,
+ &format!(
+ "consider using the normalized form `{}` of this character",
+ normalized.chars().next().unwrap().escape_default()
+ ),
+ normalized,
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ if !has_help {
+ let (prefix, msg) = if mode.is_bytes() {
+ ("b", "if you meant to write a byte string literal, use double quotes")
+ } else {
+ ("", "if you meant to write a `str` literal, use double quotes")
+ };
+
+ handler.span_suggestion(
span_with_quotes,
msg,
format!("{}\"{}\"", prefix, lit),
Applicability::MachineApplicable,
- )
- .emit();
+ );
+ }
+
+ handler.emit();
}
EscapeError::EscapeOnlyChar => {
let (c, char_span) = last_char();
let mut parser = stream_to_parser(sess, stream, None);
parser.unclosed_delims = unclosed_delims;
if parser.token == token::Eof {
- parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
+ parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
}
Ok(parser)
// This struct is passed around very frequently,
// so make sure it doesn't accidentally get larger
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(AttrWrapper, 16);
impl AttrWrapper {
pub(super) fn recover_parens_around_for_head(
&mut self,
pat: P<Pat>,
- expr: &Expr,
begin_paren: Option<Span>,
) -> P<Pat> {
match (&self.token.kind, begin_paren) {
(token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
self.bump();
- let pat_str = self
- // Remove the `(` from the span of the pattern:
- .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
- .unwrap_or_else(|_| pprust::pat_to_string(&pat));
-
- self.struct_span_err(self.prev_token.span, "unexpected closing `)`")
- .span_label(begin_par_sp, "opening `(`")
- .span_suggestion(
- begin_par_sp.to(self.prev_token.span),
- "remove parenthesis in `for` loop",
- format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
- // With e.g. `for (x) in y)` this would replace `(x) in y)`
- // with `x) in y)` which is syntactically invalid.
- // However, this is prevented before we get here.
- Applicability::MachineApplicable,
- )
- .emit();
+ self.struct_span_err(
+ MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
+ "unexpected parenthesis surrounding `for` loop head",
+ )
+ .multipart_suggestion(
+ "remove parenthesis in `for` loop",
+ vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
+ // With e.g. `for (x) in y)` this would replace `(x) in y)`
+ // with `x) in y)` which is syntactically invalid.
+ // However, this is prevented before we get here.
+ Applicability::MachineApplicable,
+ )
+ .emit();
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
pat.and_then(|pat| match pat.kind {
{
let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
- let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
- PatKind::Ident(_, ident, _) => (
- ident,
- format!("self: {}", ident),
- format!("{}: TypeName", ident),
- format!("_: {}", ident),
- ),
- // Also catches `fn foo(&a)`.
- PatKind::Ref(ref pat, mutab)
- if matches!(pat.clone().into_inner().kind, PatKind::Ident(..)) =>
- {
- match pat.clone().into_inner().kind {
- PatKind::Ident(_, ident, _) => {
- let mutab = mutab.prefix_str();
- (
- ident,
- format!("self: &{}{}", mutab, ident),
- format!("{}: &{}TypeName", ident, mutab),
- format!("_: &{}{}", mutab, ident),
- )
+ let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
+ match pat.kind {
+ PatKind::Ident(_, ident, _) => (
+ ident,
+ "self: ".to_string(),
+ ": TypeName".to_string(),
+ "_: ".to_string(),
+ pat.span.shrink_to_lo(),
+ pat.span.shrink_to_hi(),
+ pat.span.shrink_to_lo(),
+ ),
+ // Also catches `fn foo(&a)`.
+ PatKind::Ref(ref inner_pat, mutab)
+ if matches!(inner_pat.clone().into_inner().kind, PatKind::Ident(..)) =>
+ {
+ match inner_pat.clone().into_inner().kind {
+ PatKind::Ident(_, ident, _) => {
+ let mutab = mutab.prefix_str();
+ (
+ ident,
+ "self: ".to_string(),
+ format!("{}: &{}TypeName", ident, mutab),
+ "_: ".to_string(),
+ pat.span.shrink_to_lo(),
+ pat.span,
+ pat.span.shrink_to_lo(),
+ )
+ }
+ _ => unreachable!(),
}
- _ => unreachable!(),
- }
- }
- _ => {
- // Otherwise, try to get a type and emit a suggestion.
- if let Some(ty) = pat.to_ty() {
- err.span_suggestion_verbose(
- pat.span,
- "explicitly ignore the parameter name",
- format!("_: {}", pprust::ty_to_string(&ty)),
- Applicability::MachineApplicable,
- );
- err.note(rfc_note);
}
+ _ => {
+ // Otherwise, try to get a type and emit a suggestion.
+ if let Some(ty) = pat.to_ty() {
+ err.span_suggestion_verbose(
+ pat.span,
+ "explicitly ignore the parameter name",
+ format!("_: {}", pprust::ty_to_string(&ty)),
+ Applicability::MachineApplicable,
+ );
+ err.note(rfc_note);
+ }
- return None;
- }
- };
+ return None;
+ }
+ };
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
if first_param {
err.span_suggestion(
- pat.span,
+ self_span,
"if this is a `self` type, give it a parameter name",
self_sugg,
Applicability::MaybeIncorrect,
// `fn foo(HashMap: TypeName<u32>)`.
if self.token != token::Lt {
err.span_suggestion(
- pat.span,
+ param_span,
"if this is a parameter name, give it a type",
param_sugg,
Applicability::HasPlaceholders,
);
}
err.span_suggestion(
- pat.span,
+ type_span,
"if this is a type, explicitly ignore the parameter name",
type_sugg,
Applicability::MachineApplicable,
}
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
Ok(expr) => {
- if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() {
+ // Find a mistake like `MyTrait<Assoc == S::Assoc>`.
+ if token::EqEq == snapshot.token.kind {
+ err.span_suggestion(
+ snapshot.token.span,
+ "if you meant to use an associated type binding, replace `==` with `=`",
+ "=".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ let value = self.mk_expr_err(start.to(expr.span));
+ err.emit();
+ return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
+ } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
+ {
// Avoid the following output by checking that we consumed a full const arg:
// help: expressions must be enclosed in braces to be used as const generic
// arguments
use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType};
+use super::{
+ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+};
use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
use crate::maybe_recover_from_interpolated_ty_qpath;
+use ast::token::DelimToken;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Token, TokenKind};
use rustc_ast::tokenstream::Spacing;
/// Parses an expression.
#[inline]
pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
+ self.current_closure.take();
+
self.parse_expr_res(Restrictions::empty(), None)
}
}
}
+ fn look_ahead_type_ascription_as_field(&mut self) -> bool {
+ self.look_ahead(1, |t| t.is_ident())
+ && self.look_ahead(2, |t| t == &token::Colon)
+ && self.look_ahead(3, |t| t.can_begin_expr())
+ }
+
fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
match self.token.uninterpolate().kind {
token::Ident(..) => self.parse_dot_suffix(base, lo),
/// Parse a function call expression, `expr(...)`.
fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
- let seq = self.parse_paren_expr_seq().map(|args| {
+ let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
+ && self.look_ahead_type_ascription_as_field()
+ {
+ Some((self.clone(), fun.kind.clone()))
+ } else {
+ None
+ };
+ let open_paren = self.token.span;
+
+ let mut seq = self.parse_paren_expr_seq().map(|args| {
self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new())
});
+ if let Some(expr) =
+ self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
+ {
+ return expr;
+ }
self.recover_seq_parse_error(token::Paren, lo, seq)
}
+ /// If we encounter a parser state that looks like the user has written a `struct` literal with
+ /// parentheses instead of braces, recover the parser state and provide suggestions.
+ fn maybe_recover_struct_lit_bad_delims(
+ &mut self,
+ lo: Span,
+ open_paren: Span,
+ seq: &mut PResult<'a, P<Expr>>,
+ snapshot: Option<(Self, ExprKind)>,
+ ) -> Option<P<Expr>> {
+ match (seq.as_mut(), snapshot) {
+ (Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
+ let name = pprust::path_to_string(&path);
+ snapshot.bump(); // `(`
+ match snapshot.parse_struct_fields(path.clone(), false, token::Paren) {
+ Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
+ // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
+ // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
+ *self = snapshot;
+ let close_paren = self.prev_token.span;
+ let span = lo.to(self.prev_token.span);
+ err.cancel();
+ self.struct_span_err(
+ span,
+ "invalid `struct` delimiters or `fn` call arguments",
+ )
+ .multipart_suggestion(
+ &format!("if `{}` is a struct, use braces as delimiters", name),
+ vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
+ Applicability::MaybeIncorrect,
+ )
+ .multipart_suggestion(
+ &format!("if `{}` is a function, use the arguments directly", name),
+ fields
+ .into_iter()
+ .map(|field| (field.span.until(field.expr.span), String::new()))
+ .collect(),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ return Some(self.mk_expr_err(span));
+ }
+ Ok(_) => {}
+ Err(mut err) => err.emit(),
+ }
+ }
+ _ => {}
+ }
+ None
+ }
+
/// Parse an indexing expression `expr[...]`.
fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
self.bump(); // `[`
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
self.parse_closure_expr(attrs)
} else if self.check(&token::OpenDelim(token::Bracket)) {
- self.parse_array_or_repeat_expr(attrs)
+ self.parse_array_or_repeat_expr(attrs, token::Bracket)
} else if self.check_path() {
self.parse_path_start_expr(attrs)
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
self.maybe_recover_from_bad_qpath(expr, true)
}
- fn parse_array_or_repeat_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+ fn parse_array_or_repeat_expr(
+ &mut self,
+ attrs: AttrVec,
+ close_delim: token::DelimToken,
+ ) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
- self.bump(); // `[`
+ self.bump(); // `[` or other open delim
- let close = &token::CloseDelim(token::Bracket);
+ let close = &token::CloseDelim(close_delim);
let kind = if self.eat(close) {
// Empty vector
ExprKind::Array(Vec::new())
}
}
+ fn is_array_like_block(&mut self) -> bool {
+ self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
+ && self.look_ahead(2, |t| t == &token::Comma)
+ && self.look_ahead(3, |t| t.can_begin_expr())
+ }
+
+ /// Emits a suggestion if it looks like the user meant an array but
+ /// accidentally used braces, causing the code to be interpreted as a block
+ /// expression.
+ fn maybe_suggest_brackets_instead_of_braces(
+ &mut self,
+ lo: Span,
+ attrs: AttrVec,
+ ) -> Option<P<Expr>> {
+ let mut snapshot = self.clone();
+ match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
+ Ok(arr) => {
+ let hi = snapshot.prev_token.span;
+ self.struct_span_err(
+ arr.span,
+ "this code is interpreted as a block expression, not an array",
+ )
+ .multipart_suggestion(
+ "try using [] instead of {}",
+ vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
+ Applicability::MaybeIncorrect,
+ )
+ .note("to define an array, one would use square brackets instead of curly braces")
+ .emit();
+
+ *self = snapshot;
+ Some(self.mk_expr_err(arr.span))
+ }
+ Err(mut e) => {
+ e.cancel();
+ None
+ }
+ }
+ }
+
/// Parses a block or unsafe block.
pub(super) fn parse_block_expr(
&mut self,
blk_mode: BlockCheckMode,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
+ if self.is_array_like_block() {
+ if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo, attrs.clone()) {
+ return Ok(arr);
+ }
+ }
+
if let Some(label) = opt_label {
self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
}
let capture_clause = self.parse_capture_clause()?;
let decl = self.parse_fn_block_decl()?;
let decl_hi = self.prev_token.span;
- let body = match decl.output {
+ let mut body = match decl.output {
FnRetTy::Default(_) => {
let restrictions = self.restrictions - Restrictions::STMT_EXPR;
self.parse_expr_res(restrictions, None)?
self.sess.gated_spans.gate(sym::async_closure, span);
}
- Ok(self.mk_expr(
+ if self.token.kind == TokenKind::Semi && self.token_cursor.frame.delim == DelimToken::Paren
+ {
+ // It is likely that the closure body is a block but where the
+ // braces have been removed. We will recover and eat the next
+ // statements later in the parsing process.
+ body = self.mk_expr_err(body.span);
+ }
+
+ let body_span = body.span;
+
+ let closure = self.mk_expr(
lo.to(body.span),
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
attrs,
- ))
+ );
+
+ // Disable recovery for closure body
+ let spans =
+ ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
+ self.current_closure = Some(spans);
+
+ Ok(closure)
}
/// Parses an optional `move` prefix to a closure-like construct.
self.check_for_for_in_in_typo(self.prev_token.span);
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
- let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);
+ let pat = self.recover_parens_around_for_head(pat, begin_paren);
let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
.emit();
}
- /// Precondition: already parsed the '{'.
- pub(super) fn parse_struct_expr(
+ pub(super) fn parse_struct_fields(
&mut self,
- qself: Option<ast::QSelf>,
pth: ast::Path,
- attrs: AttrVec,
recover: bool,
- ) -> PResult<'a, P<Expr>> {
+ close_delim: token::DelimToken,
+ ) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
let mut fields = Vec::new();
let mut base = ast::StructRest::None;
let mut recover_async = false;
e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
};
- while self.token != token::CloseDelim(token::Brace) {
+ while self.token != token::CloseDelim(close_delim) {
if self.eat(&token::DotDot) {
let exp_span = self.prev_token.span;
// We permit `.. }` on the left-hand side of a destructuring assignment.
- if self.check(&token::CloseDelim(token::Brace)) {
+ if self.check(&token::CloseDelim(close_delim)) {
self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span);
base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi());
break;
}
};
- match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) {
+ match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
Ok(_) => {
if let Some(f) = parsed_field.or(recovery_field) {
// Only include the field if there's no parse error for the field name.
}
}
}
+ Ok((fields, base, recover_async))
+ }
- let span = pth.span.to(self.token.span);
+ /// Precondition: already parsed the '{'.
+ pub(super) fn parse_struct_expr(
+ &mut self,
+ qself: Option<ast::QSelf>,
+ pth: ast::Path,
+ attrs: AttrVec,
+ recover: bool,
+ ) -> PResult<'a, P<Expr>> {
+ let lo = pth.span;
+ let (fields, base, recover_async) =
+ self.parse_struct_fields(pth.clone(), recover, token::Brace)?;
+ let span = lo.to(self.token.span);
self.expect(&token::CloseDelim(token::Brace))?;
let expr = if recover_async {
ExprKind::Err
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
{
let span = self.prev_token.span.between(self.token.span);
- self.struct_span_err(span, "missing trait in a trait impl").emit();
+ self.struct_span_err(span, "missing trait in a trait impl")
+ .span_suggestion(
+ span,
+ "add a trait here",
+ " Trait ".into(),
+ Applicability::HasPlaceholders,
+ )
+ .span_suggestion(
+ span.to(self.token.span),
+ "for an inherent impl, drop this `for`",
+ "".into(),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
P(Ty {
kind: TyKind::Path(None, err_path(span)),
span,
Ok((class_name, ItemKind::Union(vdata, generics)))
}
- pub(super) fn parse_record_struct_body(
+ fn parse_record_struct_body(
&mut self,
adt_ty: &str,
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err()?;
if !is_raw && ident.is_reserved() {
- if ident.name == kw::Underscore {
- self.sess.gated_spans.gate(sym::unnamed_fields, lo);
+ let err = if self.check_fn_front_matter(false) {
+ // We use `parse_fn` to get a span for the function
+ if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
+ db.delay_as_bug();
+ }
+ let mut err = self.struct_span_err(
+ lo.to(self.prev_token.span),
+ &format!("functions are not allowed in {} definitions", adt_ty),
+ );
+ err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
+ err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+ err
} else {
- let err = if self.check_fn_front_matter(false) {
- // We use `parse_fn` to get a span for the function
- if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
- db.delay_as_bug();
- }
- let mut err = self.struct_span_err(
- lo.to(self.prev_token.span),
- &format!("functions are not allowed in {} definitions", adt_ty),
- );
- err.help(
- "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
- );
- err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
- err
- } else {
- self.expected_ident_found()
- };
- return Err(err);
- }
+ self.expected_ident_found()
+ };
+ return Err(err);
}
self.bump();
Ok(ident)
/// If present, this `Parser` is not parsing Rust code but rather a macro call.
subparser_name: Option<&'static str>,
capture_state: CaptureState,
+ /// This allows us to recover when the user forget to add braces around
+ /// multiple statements in the closure body.
+ pub current_closure: Option<ClosureSpans>,
+}
+
+/// Stores span informations about a closure.
+#[derive(Clone)]
+pub struct ClosureSpans {
+ pub whole_closure: Span,
+ pub closing_pipe: Span,
+ pub body: Span,
}
/// Indicates a range of tokens that should be replaced by
replace_ranges: Vec::new(),
inner_attr_ranges: Default::default(),
},
+ current_closure: None,
};
// Make parser point to the first token.
first = false;
} else {
match self.expect(t) {
- Ok(false) => {}
+ Ok(false) => {
+ self.current_closure.take();
+ }
Ok(true) => {
+ self.current_closure.take();
recovered = true;
break;
}
let sp = self.prev_token.span.shrink_to_hi();
let token_str = pprust::token_kind_to_string(t);
- // Attempt to keep parsing if it was a similar separator.
- if let Some(ref tokens) = t.similar_tokens() {
- if tokens.contains(&self.token.kind) && !unclosed_delims {
- self.bump();
+ match self.current_closure.take() {
+ Some(closure_spans) if self.token.kind == TokenKind::Semi => {
+ // Finding a semicolon instead of a comma
+ // after a closure body indicates that the
+ // closure body may be a block but the user
+ // forgot to put braces around its
+ // statements.
+
+ self.recover_missing_braces_around_closure_body(
+ closure_spans,
+ expect_err,
+ )?;
+
+ continue;
+ }
+
+ _ => {
+ // Attempt to keep parsing if it was a similar separator.
+ if let Some(ref tokens) = t.similar_tokens() {
+ if tokens.contains(&self.token.kind) && !unclosed_delims {
+ self.bump();
+ }
+ }
}
}
Ok((v, trailing, recovered))
}
+ fn recover_missing_braces_around_closure_body(
+ &mut self,
+ closure_spans: ClosureSpans,
+ mut expect_err: DiagnosticBuilder<'_>,
+ ) -> PResult<'a, ()> {
+ let initial_semicolon = self.token.span;
+
+ while self.eat(&TokenKind::Semi) {
+ let _ = self.parse_stmt(ForceCollect::Yes)?;
+ }
+
+ expect_err.set_primary_message(
+ "closure bodies that contain statements must be surrounded by braces",
+ );
+
+ let preceding_pipe_span = closure_spans.closing_pipe;
+ let following_token_span = self.token.span;
+
+ let mut first_note = MultiSpan::from(vec![initial_semicolon]);
+ first_note.push_span_label(
+ initial_semicolon,
+ "this `;` turns the preceding closure into a statement".to_string(),
+ );
+ first_note.push_span_label(
+ closure_spans.body,
+ "this expression is a statement because of the trailing semicolon".to_string(),
+ );
+ expect_err.span_note(first_note, "statement found outside of a block");
+
+ let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]);
+ second_note.push_span_label(
+ closure_spans.whole_closure,
+ "this is the parsed closure...".to_string(),
+ );
+ second_note.push_span_label(
+ following_token_span,
+ "...but likely you meant the closure to end here".to_string(),
+ );
+ expect_err.span_note(second_note, "the closure body may be incorrectly delimited");
+
+ expect_err.set_span(vec![preceding_pipe_span, following_token_span]);
+
+ let opening_suggestion_str = " {".to_string();
+ let closing_suggestion_str = "}".to_string();
+
+ expect_err.multipart_suggestion(
+ "try adding braces",
+ vec![
+ (preceding_pipe_span.shrink_to_hi(), opening_suggestion_str),
+ (following_token_span.shrink_to_lo(), closing_suggestion_str),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+
+ expect_err.emit();
+
+ Ok(())
+ }
+
/// Parses a sequence, not including the closing delimiter. The function
/// `f` must consume tokens until reaching the next separator or
/// closing bracket.
let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
- let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
- {
- StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
- } else {
- // Since none of the above applied, this is an expression statement macro.
- let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
- let e = self.maybe_recover_from_bad_qpath(e, true)?;
- let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
- let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
- StmtKind::Expr(e)
- };
+ let kind =
+ if (delim == token::Brace && self.token != token::Dot && self.token != token::Question)
+ || self.token == token::Semi
+ || self.token == token::Eof
+ {
+ StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
+ } else {
+ // Since none of the above applied, this is an expression statement macro.
+ let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
+ let e = self.maybe_recover_from_bad_qpath(e, true)?;
+ let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+ let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+ StmtKind::Expr(e)
+ };
Ok(self.mk_stmt(lo.to(hi), kind))
}
}
} else if self.eat_keyword(kw::Impl) {
self.parse_impl_ty(&mut impl_dyn_multi)?
- } else if self.token.is_keyword(kw::Union)
- && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
- {
- self.bump();
- let (fields, recovered) = self.parse_record_struct_body("union")?;
- let span = lo.to(self.prev_token.span);
- self.sess.gated_spans.gate(sym::unnamed_fields, span);
- TyKind::AnonymousUnion(fields, recovered)
- } else if self.eat_keyword(kw::Struct) {
- let (fields, recovered) = self.parse_record_struct_body("struct")?;
- let span = lo.to(self.prev_token.span);
- self.sess.gated_spans.gate(sym::unnamed_fields, span);
- TyKind::AnonymousStruct(fields, recovered)
} else if self.is_explicit_dyn_type() {
self.parse_dyn_ty(&mut impl_dyn_multi)?
} else if self.eat_lt() {
[package]
name = "rustc_parse_format"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_span = { path = "../rustc_span" }
[package]
name = "rustc_passes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
}
}
+ /// Automatically generated items marked with `rustc_trivial_field_reads`
+ /// will be ignored for the purposes of dead code analysis (see PR #85200
+ /// for discussion).
+ fn should_ignore_item(&self, def_id: DefId) -> bool {
+ if !self.tcx.has_attr(def_id, sym::automatically_derived)
+ && !self
+ .tcx
+ .impl_of_method(def_id)
+ .map_or(false, |impl_id| self.tcx.has_attr(impl_id, sym::automatically_derived))
+ {
+ return false;
+ }
+
+ let has_attr = |def_id| self.tcx.has_attr(def_id, sym::rustc_trivial_field_reads);
+
+ if has_attr(def_id) {
+ return true;
+ }
+
+ if let Some(impl_of) = self.tcx.impl_of_method(def_id) {
+ if has_attr(impl_of) {
+ return true;
+ }
+
+ if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) {
+ if has_attr(trait_of) {
+ return true;
+ }
+
+ if let Some(method_ident) = self.tcx.opt_item_name(def_id) {
+ if let Some(trait_method) = self
+ .tcx
+ .associated_items(trait_of)
+ .find_by_name_and_kind(self.tcx, method_ident, ty::AssocKind::Fn, trait_of)
+ {
+ if has_attr(trait_method.def_id) {
+ return true;
+ }
+ }
+ }
+ }
+ } else if let Some(trait_of) = self.tcx.trait_of_item(def_id) {
+ if has_attr(trait_of) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
fn visit_node(&mut self, node: Node<'tcx>) {
+ if let Some(item_def_id) = match node {
+ Node::Item(hir::Item { def_id, .. })
+ | Node::ForeignItem(hir::ForeignItem { def_id, .. })
+ | Node::TraitItem(hir::TraitItem { def_id, .. })
+ | Node::ImplItem(hir::ImplItem { def_id, .. }) => Some(def_id.to_def_id()),
+ _ => None,
+ } {
+ if self.should_ignore_item(item_def_id) {
+ return;
+ }
+ }
+
let had_repr_c = self.repr_has_repr_c;
let had_inherited_pub_visibility = self.inherited_pub_visibility;
let had_pub_visibility = self.pub_visibility;
use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
+use rustc_data_structures::sync::Lock;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
use rustc_hir::intravisit;
let errors = Lock::new(Vec::new());
let hir_map = tcx.hir();
- par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
+ hir_map.par_for_each_module(|module_id| {
hir_map
- .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
+ .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors })
});
let errors = errors.into_inner();
self.hir_ids_seen.insert(hir_id.local_id);
}
- fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef<'hir>) {
+ fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) {
// Explicitly do nothing here. ImplItemRefs contain hir::Visibility
// values that actually belong to an ImplItem instead of the ItemKind::Impl
// we are currently in. So for those it's correct that they have a
// different owner.
}
- fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef<'hir>) {
+ fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef) {
// Explicitly do nothing here. ForeignItemRefs contain hir::Visibility
// values that actually belong to an ForeignItem instead of the ItemKind::ForeignMod
// we are currently in. So for those it's correct that they have a
if blk.targeted_by_break {
self.break_ln.insert(blk.hir_id, succ);
}
- let succ = self.propagate_through_opt_expr(blk.expr.as_deref(), succ);
+ let succ = self.propagate_through_opt_expr(blk.expr, succ);
blk.stmts.iter().rev().fold(succ, |succ, stmt| self.propagate_through_stmt(stmt, succ))
}
// initialization, which is mildly more complex than checking
// once at the func header but otherwise equivalent.
- let succ = self.propagate_through_opt_expr(local.init.as_deref(), succ);
+ let succ = self.propagate_through_opt_expr(local.init, succ);
self.define_bindings_in_pat(&local.pat, succ)
}
hir::StmtKind::Item(..) => succ,
resolve_expr(self, ex);
}
fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
- resolve_local(self, Some(&l.pat), l.init.as_deref());
+ resolve_local(self, Some(&l.pat), l.init);
}
}
let declared_lib_features = &tcx.features().declared_lib_features;
let mut remaining_lib_features = FxHashMap::default();
for (feature, span) in declared_lib_features {
+ if !tcx.sess.opts.unstable_features.is_nightly_build() {
+ struct_span_err!(
+ tcx.sess,
+ *span,
+ E0554,
+ "`#![feature]` may not be used on the {} release channel",
+ env!("CFG_RELEASE_CHANNEL")
+ )
+ .emit();
+ }
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
duplicate_feature_err(tcx.sess, *span, *feature);
name = "rustc_plugin_impl"
version = "0.0.0"
build = false
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_privacy"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_middle = { path = "../rustc_middle" }
use rustc_middle::bug;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::mir::abstract_const::Node as ACNode;
use rustc_middle::span_bug;
+use rustc_middle::thir::abstract_const::Node as ACNode;
use rustc_middle::ty::fold::TypeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
}
hir::ItemKind::Impl(ref impl_) => {
for impl_item_ref in impl_.items {
- if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
+ if impl_.of_trait.is_some()
+ || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public
+ {
self.update(impl_item_ref.id.def_id, item_level);
}
}
}
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- if foreign_item.vis.node.is_pub() {
+ if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public {
self.update(foreign_item.id.def_id, item_level);
}
}
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for impl_item_ref in impl_.items {
- if self.item_is_public(impl_item_ref.id.def_id, &impl_item_ref.vis) {
+ if self.access_levels.is_reachable(impl_item_ref.id.def_id)
+ || self.tcx.visibility(impl_item_ref.id.def_id)
+ == ty::Visibility::Public
+ {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
AssocItemKind::Const => {
[package]
name = "rustc_query_impl"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
DUMMY_SP
}
}
+
+impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+
+ fn default_span(&self, _: TyCtxt<'_>) -> Span {
+ DUMMY_SP
+ }
+}
+
+impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ self.0.default_span(tcx)
+ }
+}
use crate::QueryCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell, RwLock};
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
use rustc_data_structures::unhash::UnhashMap;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
+use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, interpret};
+use rustc_middle::thir;
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext;
};
use rustc_span::source_map::{SourceMap, StableSourceFileId};
use rustc_span::CachingSourceMapView;
-use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP};
-use std::collections::hash_map::Entry;
+use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
const TAG_FULL_SPAN: u8 = 0;
// A partial span with no location information, encoded only with a `SyntaxContext`
const TAG_PARTIAL_SPAN: u8 = 1;
+const TAG_RELATIVE_SPAN: u8 = 2;
const TAG_SYNTAX_CONTEXT: u8 = 0;
const TAG_EXPN_DATA: u8 = 1;
// session.
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
- cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>,
-
source_map: &'sess SourceMap,
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
// Additional information used when decoding hygiene data.
hygiene_context: HygieneDecodeContext,
- // Maps `DefPathHash`es to their `RawDefId`s from the *previous*
+ // Maps `ExpnHash`es to their raw value from the *previous*
// compilation session. This is used as an initial 'guess' when
- // we try to map a `DefPathHash` to its `DefId` in the current compilation
- // session.
- foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
- // Likewise for ExpnId.
+ // we try to map an `ExpnHash` to its value in the current
+ // compilation session.
foreign_expn_data: UnhashMap<ExpnHash, u32>,
-
- // The *next* compilation sessison's `foreign_def_path_hashes` - at
- // the end of our current compilation session, this will get written
- // out to the `foreign_def_path_hashes` field of the `Footer`, which
- // will become `foreign_def_path_hashes` of the next compilation session.
- // This stores any `DefPathHash` that we may need to map to a `DefId`
- // during the next compilation session.
- latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
-
- // Caches all lookups of `DefPathHashes`, both for local and foreign
- // definitions. A definition from the previous compilation session
- // may no longer exist in the current compilation session, so
- // we use `Option<DefId>` so that we can cache a lookup failure.
- def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
}
// This type is used only for serialization and deserialization.
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
// See `OnDiskCache.expn_data`
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
- foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
foreign_expn_data: UnhashMap<ExpnHash, u32>,
}
}
}
-/// Represents a potentially invalid `DefId`. This is used during incremental
-/// compilation to represent a `DefId` from the *previous* compilation session,
-/// which may no longer be valid. This is used to help map a `DefPathHash`
-/// to a `DefId` in the current compilation session.
-#[derive(Encodable, Decodable, Copy, Clone, Debug)]
-crate struct RawDefId {
- // We deliberately do not use `CrateNum` and `DefIndex`
- // here, since a crate/index from the previous compilation
- // session may no longer exist.
- pub krate: u32,
- pub index: u32,
-}
-
/// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that
/// the source crate is represented as a [StableCrateId] instead of as a
/// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded
}
impl EncodedSourceFileId {
- fn translate(&self, cnum_map: &UnhashMap<StableCrateId, CrateNum>) -> StableSourceFileId {
- let cnum = cnum_map[&self.stable_crate_id];
+ fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId {
+ let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id);
StableSourceFileId { file_name_hash: self.file_name_hash, cnum }
}
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(),
source_map: sess.source_map(),
current_side_effects: Default::default(),
query_result_index: footer.query_result_index.into_iter().collect(),
expn_data: footer.expn_data,
foreign_expn_data: footer.foreign_expn_data,
hygiene_context: Default::default(),
- foreign_def_path_hashes: footer.foreign_def_path_hashes,
- latest_foreign_def_path_hashes: Default::default(),
- def_path_hash_to_def_id_cache: Default::default(),
}
}
serialized_data: RwLock::new(None),
file_index_to_stable_id: Default::default(),
file_index_to_file: Default::default(),
- cnum_map: OnceCell::new(),
source_map,
current_side_effects: Default::default(),
query_result_index: Default::default(),
expn_data: UnhashMap::default(),
foreign_expn_data: UnhashMap::default(),
hygiene_context: Default::default(),
- foreign_def_path_hashes: Default::default(),
- latest_foreign_def_path_hashes: Default::default(),
- def_path_hash_to_def_id_cache: Default::default(),
}
}
/// 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.
(file_to_file_index, file_index_to_stable_id)
};
- let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
let hygiene_encode_context = HygieneEncodeContext::default();
let mut encoder = CacheEncoder {
source_map: CachingSourceMapView::new(tcx.sess.source_map()),
file_to_file_index,
hygiene_context: &hygiene_encode_context,
- latest_foreign_def_path_hashes,
};
// Encode query results.
},
)?;
- let foreign_def_path_hashes =
- std::mem::take(&mut encoder.latest_foreign_def_path_hashes);
-
// `Encode the file footer.
let footer_pos = encoder.position() as u64;
encoder.encode_tagged(
syntax_contexts,
expn_data,
foreign_expn_data,
- foreign_def_path_hashes,
},
)?;
})
}
- fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option<DefId> {
- let mut cache = self.def_path_hash_to_def_id_cache.lock();
- match cache.entry(hash) {
- Entry::Occupied(e) => *e.get(),
- Entry::Vacant(e) => {
- debug!("def_path_hash_to_def_id({:?})", hash);
- // Check if the `DefPathHash` corresponds to a definition in the current
- // crate
- if let Some(def_id) =
- tcx.definitions_untracked().local_def_path_hash_to_def_id(hash)
- {
- let def_id = def_id.to_def_id();
- e.insert(Some(def_id));
- return Some(def_id);
- }
- // This `raw_def_id` represents the `DefId` of this `DefPathHash` in
- // the *previous* compliation session. The `DefPathHash` includes the
- // owning crate, so if the corresponding definition still exists in the
- // current compilation session, the crate is guaranteed to be the same
- // (otherwise, we would compute a different `DefPathHash`).
- let raw_def_id = self.get_raw_def_id(&hash)?;
- debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
- // If the owning crate no longer exists, the corresponding definition definitely
- // no longer exists.
- let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
- debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
- // If our `DefPathHash` corresponded to a definition in the local crate,
- // we should have either found it in `local_def_path_hash_to_def_id`, or
- // never attempted to load it in the first place. Any query result or `DepNode`
- // that references a local `DefId` should depend on some HIR-related `DepNode`.
- // If a local definition is removed/modified such that its old `DefPathHash`
- // no longer has a corresponding definition, that HIR-related `DepNode` should
- // end up red. This should prevent us from ever calling
- // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
- // queries involved.
- debug_assert_ne!(krate, LOCAL_CRATE);
- // Try to find a definition in the current session, using the previous `DefIndex`
- // as an initial guess.
- let opt_def_id =
- tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash);
- debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
- e.insert(opt_def_id);
- opt_def_id
- }
- }
- }
+ fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> DefId {
+ debug!("def_path_hash_to_def_id({:?})", hash);
- fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) {
- // For reused dep nodes, we only need to store the mapping if the node
- // is one whose query key we can reconstruct from the hash. We use the
- // mapping to aid that reconstruction in the next session. While we also
- // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
- // they're already registered during `DefId` encoding.
- if dep_node.kind.can_reconstruct_query_key() {
- let hash = DefPathHash(dep_node.hash.into());
-
- // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
- // `latest_foreign_def_path_hashes`, since the `RawDefId` might have
- // changed in the current compilation session (e.g. we've added/removed crates,
- // or added/removed definitions before/after the target definition).
- if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
- if !def_id.is_local() {
- self.store_foreign_def_id_hash(def_id, hash);
- }
- }
- }
- }
+ let stable_crate_id = hash.stable_crate_id();
- fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
- // We may overwrite an existing entry, but it will have the same value,
- // so it's fine
- self.latest_foreign_def_path_hashes
- .lock()
- .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
+ // If this is a DefPathHash from the local crate, we can look up the
+ // DefId in the tcx's `Definitions`.
+ if stable_crate_id == tcx.sess.local_stable_crate_id() {
+ tcx.definitions_untracked().local_def_path_hash_to_def_id(hash).to_def_id()
+ } else {
+ // If this is a DefPathHash from an upstream crate, let the CrateStore map
+ // it to a DefId.
+ let cnum = tcx.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id);
+ tcx.cstore_untracked().def_path_hash_to_def_id(cnum, hash)
+ }
}
}
debug_assert!(prev.is_none());
}
- fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> {
- self.foreign_def_path_hashes.get(hash).copied()
- }
-
- fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> {
- let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
- debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map);
-
- cnum_map.get(&stable_crate_id).copied()
- }
-
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
where
T: Decodable<CacheDecoder<'a, 'tcx>>,
{
- 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(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,
file_index_to_stable_id: &self.file_index_to_stable_id,
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
};
f(&mut decoder)
}
-
- // This function builds mapping from previous-session-`CrateNum` to
- // current-session-`CrateNum`. There might be `CrateNum`s from the previous
- // `Session` that don't occur in the current one. For these, the mapping
- // maps to None.
- fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> {
- tcx.dep_graph.with_ignore(|| {
- tcx.crates(())
- .iter()
- .chain(std::iter::once(&LOCAL_CRATE))
- .map(|&cnum| {
- let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
- (hash, cnum)
- })
- .collect()
- })
- }
}
//- DECODING -------------------------------------------------------------------
tcx: TyCtxt<'tcx>,
opaque: opaque::Decoder<'a>,
source_map: &'a SourceMap,
- cnum_map: &'a UnhashMap<StableCrateId, CrateNum>,
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
alloc_decoding_session: AllocDecodingSession<'a>,
impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
let CacheDecoder {
+ tcx,
ref file_index_to_file,
ref file_index_to_stable_id,
ref source_map,
- ref cnum_map,
..
} = *self;
.borrow_mut()
.entry(index)
.or_insert_with(|| {
- let stable_id = file_index_to_stable_id[&index].translate(cnum_map);
+ let stable_id = file_index_to_stable_id[&index].translate(tcx);
source_map
.source_file_by_stable_id(stable_id)
.expect("failed to lookup `SourceFile` in new context")
return Ok(expn_id);
}
- let krate = decoder.cnum_map[&hash.stable_crate_id()];
+ let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
let expn_id = if krate == LOCAL_CRATE {
// We look up the position of the associated `ExpnData` and decode it.
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ let ctxt = SyntaxContext::decode(decoder)?;
+ let parent = Option::<LocalDefId>::decode(decoder)?;
let tag: u8 = Decodable::decode(decoder)?;
if tag == TAG_PARTIAL_SPAN {
- let ctxt = SyntaxContext::decode(decoder)?;
- return Ok(DUMMY_SP.with_ctxt(ctxt));
+ return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent));
+ } else if tag == TAG_RELATIVE_SPAN {
+ let dlo = u32::decode(decoder)?;
+ let dto = u32::decode(decoder)?;
+
+ let enclosing =
+ decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data_untracked();
+ let span = Span::new(
+ enclosing.lo + BytePos::from_u32(dlo),
+ enclosing.lo + BytePos::from_u32(dto),
+ ctxt,
+ parent,
+ );
+
+ return Ok(span);
} else {
debug_assert_eq!(tag, TAG_FULL_SPAN);
}
let line_lo = usize::decode(decoder)?;
let col_lo = BytePos::decode(decoder)?;
let len = BytePos::decode(decoder)?;
- let ctxt = SyntaxContext::decode(decoder)?;
let file_lo = decoder.file_index_to_file(file_lo_index);
let lo = file_lo.lines[line_lo - 1] + col_lo;
let hi = lo + len;
- Ok(Span::new(lo, hi, ctxt))
+ Ok(Span::new(lo, hi, ctxt, parent))
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
let stable_id = StableCrateId::decode(d)?;
- let cnum = d.cnum_map[&stable_id];
+ let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id);
Ok(cnum)
}
}
// If we get to this point, then all of the query inputs were green,
// which means that the definition with this hash is guaranteed to
// still exist in the current compilation session.
- Ok(d.tcx()
- .on_disk_cache
- .as_ref()
- .unwrap()
- .def_path_hash_to_def_id(d.tcx(), def_path_hash)
- .unwrap())
+ Ok(d.tcx().on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(d.tcx(), def_path_hash))
}
}
}
}
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
RefDecodable::decode(d)
}
source_map: CachingSourceMapView<'tcx>,
file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
hygiene_context: &'a HygieneEncodeContext,
- latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
}
impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
E: 'a + OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
- let span_data = self.data();
- if self.is_dummy() {
- TAG_PARTIAL_SPAN.encode(s)?;
- return span_data.ctxt.encode(s);
+ let span_data = self.data_untracked();
+ span_data.ctxt.encode(s)?;
+ span_data.parent.encode(s)?;
+
+ if span_data.is_dummy() {
+ return TAG_PARTIAL_SPAN.encode(s);
+ }
+
+ if let Some(parent) = span_data.parent {
+ let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked();
+ if enclosing.contains(span_data) {
+ TAG_RELATIVE_SPAN.encode(s)?;
+ (span_data.lo - enclosing.lo).to_u32().encode(s)?;
+ (span_data.hi - enclosing.lo).to_u32().encode(s)?;
+ return Ok(());
+ }
}
let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
};
if partial_span {
- TAG_PARTIAL_SPAN.encode(s)?;
- return span_data.ctxt.encode(s);
+ return TAG_PARTIAL_SPAN.encode(s);
}
let (file_lo, line_lo, col_lo) = pos.unwrap();
source_file_index.encode(s)?;
line_lo.encode(s)?;
col_lo.encode(s)?;
- len.encode(s)?;
- span_data.ctxt.encode(s)
+ len.encode(s)
}
}
E: 'a + OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
- let def_path_hash = s.tcx.def_path_hash(*self);
- // Store additional information when we encode a foreign `DefId`,
- // so that we can map its `DefPathHash` back to a `DefId` in the next
- // compilation session.
- if !self.is_local() {
- s.latest_foreign_def_path_hashes.insert(
- def_path_hash,
- RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() },
- );
- }
- def_path_hash.encode(s)
+ s.tcx.def_path_hash(*self).encode(s)
}
}
[package]
name = "rustc_query_system"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
pub struct DepNode<K> {
pub kind: K,
- // Important - whenever a `DepNode` is constructed, we need to make
- // sure to register a `DefPathHash -> DefId` mapping if needed.
- // This is currently done in two places:
- //
- // * When a `DepNode::construct` is called, `arg.to_fingerprint()`
- // is responsible for calling `OnDiskCache::store_foreign_def_id_hash`
- // if needed
- // * When we serialize the on-disk cache, `OnDiskCache::serialize` is
- // responsible for calling `DepGraph::register_reused_dep_nodes`.
- //
- // FIXME: Enforce this by preventing manual construction of `DefNode`
- // (e.g. add a `_priv: ()` field)
pub hash: PackedFingerprint,
}
use parking_lot::Mutex;
use smallvec::{smallvec, SmallVec};
use std::collections::hash_map::Entry;
+use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
use std::sync::atomic::Ordering::Relaxed;
/// `arg` parameter.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
- pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
+ pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
cx: Ctxt,
arg: A,
task: fn(Ctxt, A) -> R,
- hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+ hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) {
- self.with_task_impl(
- key,
- cx,
- arg,
- task,
- |_key| {
- Some(TaskDeps {
- #[cfg(debug_assertions)]
- node: Some(_key),
- reads: SmallVec::new(),
- read_set: Default::default(),
- phantom_data: PhantomData,
- })
- },
- hash_result,
- )
+ if self.is_fully_enabled() {
+ self.with_task_impl(key, cx, arg, task, hash_result)
+ } else {
+ // Incremental compilation is turned off. We just execute the task
+ // without tracking. We still provide a dep-node index that uniquely
+ // identifies the task so that we have a cheap way of referring to
+ // the query for self-profiling.
+ (task(cx, arg), self.next_virtual_depnode_index())
+ }
}
- fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A, R>(
+ fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
cx: Ctxt,
arg: A,
task: fn(Ctxt, A) -> R,
- create_task: fn(DepNode<K>) -> Option<TaskDeps<K>>,
- hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+ hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) {
- if let Some(ref data) = self.data {
- let dcx = cx.dep_context();
- let task_deps = create_task(key).map(Lock::new);
- let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
- let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
-
- let mut hcx = dcx.create_stable_hashing_context();
- let hashing_timer = dcx.profiler().incr_result_hashing();
- let current_fingerprint = hash_result(&mut hcx, &result);
-
- let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
-
- // Get timer for profiling `DepNode` interning
- let node_intern_timer = self
- .node_intern_event_id
- .map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
- // Intern the new `DepNode`.
- let (dep_node_index, prev_and_color) = data.current.intern_node(
- dcx.profiler(),
- &data.previous,
- key,
- edges,
- current_fingerprint,
- print_status,
- );
- drop(node_intern_timer);
+ // This function is only called when the graph is enabled.
+ let data = self.data.as_ref().unwrap();
- hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
+ // If the following assertion triggers, it can have two reasons:
+ // 1. Something is wrong with DepNode creation, either here or
+ // in `DepGraph::try_mark_green()`.
+ // 2. Two distinct query keys get mapped to the same `DepNode`
+ // (see for example #48923).
+ assert!(
+ !self.dep_node_exists(&key),
+ "forcing query with already existing `DepNode`\n\
+ - query-key: {:?}\n\
+ - dep-node: {:?}",
+ arg,
+ key
+ );
- if let Some((prev_index, color)) = prev_and_color {
- debug_assert!(
- data.colors.get(prev_index).is_none(),
- "DepGraph::with_task() - Duplicate DepNodeColor \
- insertion for {:?}",
- key
- );
+ let task_deps = if key.kind.is_eval_always() {
+ None
+ } else {
+ Some(Lock::new(TaskDeps {
+ #[cfg(debug_assertions)]
+ node: Some(key),
+ reads: SmallVec::new(),
+ read_set: Default::default(),
+ phantom_data: PhantomData,
+ }))
+ };
+ let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
+ let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
+
+ let dcx = cx.dep_context();
+ let mut hcx = dcx.create_stable_hashing_context();
+ let hashing_timer = dcx.profiler().incr_result_hashing();
+ let current_fingerprint = hash_result(&mut hcx, &result);
+
+ let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
+
+ // Get timer for profiling `DepNode` interning
+ let node_intern_timer =
+ self.node_intern_event_id.map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
+ // Intern the new `DepNode`.
+ let (dep_node_index, prev_and_color) = data.current.intern_node(
+ dcx.profiler(),
+ &data.previous,
+ key,
+ edges,
+ current_fingerprint,
+ print_status,
+ );
+ drop(node_intern_timer);
- data.colors.insert(prev_index, color);
- }
+ hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
- (result, dep_node_index)
- } else {
- // Incremental compilation is turned off. We just execute the task
- // without tracking. We still provide a dep-node index that uniquely
- // identifies the task so that we have a cheap way of referring to
- // the query for self-profiling.
- (task(cx, arg), self.next_virtual_depnode_index())
+ if let Some((prev_index, color)) = prev_and_color {
+ debug_assert!(
+ data.colors.get(prev_index).is_none(),
+ "DepGraph::with_task() - Duplicate DepNodeColor \
+ insertion for {:?}",
+ key
+ );
+
+ data.colors.insert(prev_index, color);
}
+
+ (result, dep_node_index)
}
/// Executes something within an "anonymous" task, that is, a task the
}
}
- /// Executes something within an "eval-always" task which is a task
- /// that runs whenever anything changes.
- pub fn with_eval_always_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
- &self,
- key: DepNode<K>,
- cx: Ctxt,
- arg: A,
- task: fn(Ctxt, A) -> R,
- hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
- ) -> (R, DepNodeIndex) {
- self.with_task_impl(key, cx, arg, task, |_| None, hash_result)
- }
-
#[inline]
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
if let Some(ref data) = self.data {
None
}
- /// Try to read a node index for the node dep_node.
+ /// Try to mark a node index for the node dep_node.
+ ///
/// A node will have an index, when it's already been marked green, or when we can mark it
/// green. This function will mark the current task as a reader of the specified node, when
/// a node index can be found for that node.
- pub fn try_mark_green_and_read<Ctxt: QueryContext<DepKind = K>>(
- &self,
- tcx: Ctxt,
- dep_node: &DepNode<K>,
- ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
- self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
- debug_assert!(self.is_green(&dep_node));
- self.read_index(dep_node_index);
- (prev_index, dep_node_index)
- })
- }
-
pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>(
&self,
tcx: Ctxt,
}
}
- // Register reused dep nodes (i.e. nodes we've marked red or green) with the context.
- pub fn register_reused_dep_nodes<Ctxt: DepContext<DepKind = K>>(&self, tcx: Ctxt) {
- let data = self.data.as_ref().unwrap();
- for prev_index in data.colors.values.indices() {
- match data.colors.get(prev_index) {
- Some(DepNodeColor::Red) | Some(DepNodeColor::Green(_)) => {
- let dep_node = data.previous.index_to_node(prev_index);
- tcx.register_reused_dep_node(&dep_node);
- }
- None => {}
- }
- }
- }
-
pub fn print_incremental_info(&self) {
if let Some(data) = &self.data {
data.current.encoder.borrow().print_incremental_info(
/// Access the DepGraph.
fn dep_graph(&self) -> &DepGraph<Self::DepKind>;
- fn register_reused_dep_node(&self, dep_node: &DepNode<Self::DepKind>);
-
/// Access the profiler.
fn profiler(&self) -> &SelfProfilerRef;
impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
for SerializedDepGraph<K>
{
- #[instrument(skip(d))]
+ #[instrument(level = "debug", skip(d))]
fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String> {
let start_position = d.position();
}
}
- #[instrument(skip(self, record_graph))]
+ #[instrument(level = "debug", skip(self, record_graph))]
fn encode_node(
&mut self,
node: &NodeInfo<K>,
where
D: Copy + Clone + Eq + Hash,
{
+ #[cold]
+ #[inline(never)]
pub(super) fn find_cycle_in_stack(
&self,
query_map: QueryMap<D>,
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
-use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeParams};
-use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
use crate::query::caches::QueryCache;
use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt};
use crate::query::job::{
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded};
use rustc_data_structures::sync::{Lock, LockGuard};
use rustc_data_structures::thin_vec::ThinVec;
-#[cfg(not(parallel_compiler))]
-use rustc_errors::DiagnosticBuilder;
-use rustc_errors::{Diagnostic, FatalError};
+use rustc_errors::{DiagnosticBuilder, FatalError};
use rustc_span::{Span, DUMMY_SP};
use std::cell::Cell;
use std::collections::hash_map::Entry;
/// A type representing the responsibility to execute the job in the `job` field.
/// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, D, C>
+struct JobOwner<'tcx, D, K>
where
D: Copy + Clone + Eq + Hash,
- C: QueryCache,
+ K: Eq + Hash + Clone,
{
- state: &'tcx QueryState<D, C::Key>,
- cache: &'tcx QueryCacheStore<C>,
- key: C::Key,
+ state: &'tcx QueryState<D, K>,
+ key: K,
id: QueryJobId<D>,
}
#[cold]
#[inline(never)]
-#[cfg(not(parallel_compiler))]
fn mk_cycle<CTX, V, R>(
tcx: CTX,
- root: QueryJobId<CTX::DepKind>,
- span: Span,
+ error: CycleError,
handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
) -> R
V: std::fmt::Debug,
R: Clone,
{
- let error: CycleError = root.find_cycle_in_stack(
- tcx.try_collect_active_jobs().unwrap(),
- &tcx.current_query_job(),
- span,
- );
let error = report_cycle(tcx.dep_context().sess(), error);
let value = handle_cycle_error(tcx, error);
cache.store_nocache(value)
}
-impl<'tcx, D, C> JobOwner<'tcx, D, C>
+impl<'tcx, D, K> JobOwner<'tcx, D, K>
where
D: Copy + Clone + Eq + Hash,
- C: QueryCache,
+ K: Eq + Hash + Clone,
{
/// Either gets a `JobOwner` corresponding the query, allowing us to
/// start executing the query, or returns with the result of the query.
/// for some compile-time benchmarks.
#[inline(always)]
fn try_start<'b, CTX>(
- tcx: CTX,
- state: &'b QueryState<CTX::DepKind, C::Key>,
- cache: &'b QueryCacheStore<C>,
+ tcx: &'b CTX,
+ state: &'b QueryState<CTX::DepKind, K>,
span: Span,
- key: C::Key,
+ key: K,
lookup: QueryLookup,
- query: &QueryVtable<CTX, C::Key, C::Value>,
- ) -> TryGetJob<'b, CTX::DepKind, C>
+ dep_kind: CTX::DepKind,
+ ) -> TryGetJob<'b, CTX::DepKind, K>
where
CTX: QueryContext,
{
let key = entry.key().clone();
entry.insert(QueryResult::Started(job));
- let global_id = QueryJobId::new(id, shard, query.dep_kind);
- let owner = JobOwner { state, cache, id: global_id, key };
+ let global_id = QueryJobId::new(id, shard, dep_kind);
+ let owner = JobOwner { state, id: global_id, key };
return TryGetJob::NotYetStarted(owner);
}
Entry::Occupied(mut entry) => {
match entry.get_mut() {
#[cfg(not(parallel_compiler))]
QueryResult::Started(job) => {
- let id = QueryJobId::new(job.id, shard, query.dep_kind);
+ let id = QueryJobId::new(job.id, shard, dep_kind);
drop(state_lock);
// If we are single-threaded we know that we have cycle error,
// so we just return the error.
- return TryGetJob::Cycle(mk_cycle(
- tcx,
- id,
+ return TryGetJob::Cycle(id.find_cycle_in_stack(
+ tcx.try_collect_active_jobs().unwrap(),
+ &tcx.current_query_job(),
span,
- query.handle_cycle_error,
- &cache.cache,
));
}
#[cfg(parallel_compiler)]
// Get the latch out
let latch = job.latch();
- let key = entry.key().clone();
drop(state_lock);
// thread.
let result = latch.wait_on(tcx.current_query_job(), span);
- if let Err(cycle) = result {
- let cycle = report_cycle(tcx.dep_context().sess(), cycle);
- let value = (query.handle_cycle_error)(tcx, cycle);
- let value = cache.cache.store_nocache(value);
- return TryGetJob::Cycle(value);
+ match result {
+ Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer),
+ Err(cycle) => TryGetJob::Cycle(cycle),
}
-
- let cached = cache
- .cache
- .lookup(cache, &key, |value, index| {
- if unlikely!(tcx.dep_context().profiler().enabled()) {
- tcx.dep_context().profiler().query_cache_hit(index.into());
- }
- #[cfg(debug_assertions)]
- {
- cache.cache_hits.fetch_add(1, Ordering::Relaxed);
- }
- (value.clone(), index)
- })
- .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
-
- query_blocked_prof_timer.finish_with_query_invocation_id(cached.1.into());
-
- return TryGetJob::JobCompleted(cached);
}
QueryResult::Poisoned => FatalError.raise(),
}
/// Completes the query by updating the query cache with the `result`,
/// signals the waiter and forgets the JobOwner, so it won't poison the query
- fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
+ fn complete<C>(
+ self,
+ cache: &QueryCacheStore<C>,
+ result: C::Value,
+ dep_node_index: DepNodeIndex,
+ ) -> C::Stored
+ where
+ C: QueryCache<Key = K>,
+ {
// We can move out of `self` here because we `mem::forget` it below
let key = unsafe { ptr::read(&self.key) };
let state = self.state;
- let cache = self.cache;
// Forget ourself so our destructor won't poison the query
mem::forget(self);
}
}
-fn with_diagnostics<F, R>(f: F) -> (R, ThinVec<Diagnostic>)
-where
- F: FnOnce(Option<&Lock<ThinVec<Diagnostic>>>) -> R,
-{
- let diagnostics = Lock::new(ThinVec::new());
- let result = f(Some(&diagnostics));
- (result, diagnostics.into_inner())
-}
-
-impl<'tcx, D, C> Drop for JobOwner<'tcx, D, C>
+impl<'tcx, D, K> Drop for JobOwner<'tcx, D, K>
where
D: Copy + Clone + Eq + Hash,
- C: QueryCache,
+ K: Eq + Hash + Clone,
{
#[inline(never)]
#[cold]
}
/// The result of `try_start`.
-enum TryGetJob<'tcx, D, C>
+enum TryGetJob<'tcx, D, K>
where
D: Copy + Clone + Eq + Hash,
- C: QueryCache,
+ K: Eq + Hash + Clone,
{
/// The query is not yet started. Contains a guard to the cache eventually used to start it.
- NotYetStarted(JobOwner<'tcx, D, C>),
+ NotYetStarted(JobOwner<'tcx, D, K>),
/// The query was already completed.
/// Returns the result of the query and its dep-node index
/// if it succeeded or a cycle error if it failed.
#[cfg(parallel_compiler)]
- JobCompleted((C::Stored, DepNodeIndex)),
+ JobCompleted(TimingGuard<'tcx>),
/// Trying to execute the query resulted in a cycle.
- Cycle(C::Stored),
+ Cycle(CycleError),
}
/// Checks if the query is already computed and in the cache.
span: Span,
key: C::Key,
lookup: QueryLookup,
+ dep_node: Option<DepNode<CTX::DepKind>>,
query: &QueryVtable<CTX, C::Key, C::Value>,
compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
+) -> (C::Stored, Option<DepNodeIndex>)
where
C: QueryCache,
- C::Key: DepNodeParams<CTX::DepContext>,
+ C::Key: Clone + DepNodeParams<CTX::DepContext>,
CTX: QueryContext,
{
- let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
- tcx,
+ match JobOwner::<'_, CTX::DepKind, C::Key>::try_start(
+ &tcx,
state,
- cache,
span,
key.clone(),
lookup,
- query,
+ query.dep_kind,
) {
- TryGetJob::NotYetStarted(job) => job,
- TryGetJob::Cycle(result) => return result,
+ TryGetJob::NotYetStarted(job) => {
+ let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id, compute);
+ let result = job.complete(cache, result, dep_node_index);
+ (result, Some(dep_node_index))
+ }
+ TryGetJob::Cycle(error) => {
+ let result = mk_cycle(tcx, error, query.handle_cycle_error, &cache.cache);
+ (result, None)
+ }
#[cfg(parallel_compiler)]
- TryGetJob::JobCompleted((v, index)) => {
- tcx.dep_context().dep_graph().read_index(index);
- return v;
+ TryGetJob::JobCompleted(query_blocked_prof_timer) => {
+ let (v, index) = cache
+ .cache
+ .lookup(cache, &key, |value, index| (value.clone(), index))
+ .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+
+ if unlikely!(tcx.dep_context().profiler().enabled()) {
+ tcx.dep_context().profiler().query_cache_hit(index.into());
+ }
+ #[cfg(debug_assertions)]
+ {
+ cache.cache_hits.fetch_add(1, Ordering::Relaxed);
+ }
+ query_blocked_prof_timer.finish_with_query_invocation_id(index.into());
+
+ (v, Some(index))
}
- };
+ }
+}
+fn execute_job<CTX, K, V>(
+ tcx: CTX,
+ key: K,
+ mut dep_node_opt: Option<DepNode<CTX::DepKind>>,
+ query: &QueryVtable<CTX, K, V>,
+ job_id: QueryJobId<CTX::DepKind>,
+ compute: fn(CTX::DepContext, K) -> V,
+) -> (V, DepNodeIndex)
+where
+ K: Clone + DepNodeParams<CTX::DepContext>,
+ V: Debug,
+ CTX: QueryContext,
+{
let dep_graph = tcx.dep_context().dep_graph();
// Fast path for when incr. comp. is off.
if !dep_graph.is_fully_enabled() {
let prof_timer = tcx.dep_context().profiler().query_provider();
- let result = tcx.start_query(job.id, None, || compute(*tcx.dep_context(), key));
+ let result = tcx.start_query(job_id, None, || compute(*tcx.dep_context(), key));
let dep_node_index = dep_graph.next_virtual_depnode_index();
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
- return job.complete(result, dep_node_index);
+ return (result, dep_node_index);
}
- if query.anon {
- let prof_timer = tcx.dep_context().profiler().query_provider();
+ if !query.anon && !query.eval_always {
+ // `to_dep_node` is expensive for some `DepKind`s.
+ let dep_node =
+ dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key));
- let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
- tcx.start_query(job.id, diagnostics, || {
- dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
- compute(*tcx.dep_context(), key)
- })
- })
- });
+ // The diagnostics for this query will be promoted to the current session during
+ // `try_mark_green()`, so we can ignore them here.
+ if let Some(ret) = tcx.start_query(job_id, None, || {
+ try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query, compute)
+ }) {
+ return ret;
+ }
+ }
- prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+ let prof_timer = tcx.dep_context().profiler().query_provider();
+ let diagnostics = Lock::new(ThinVec::new());
- dep_graph.read_index(dep_node_index);
+ let (result, dep_node_index) = tcx.start_query(job_id, Some(&diagnostics), || {
+ if query.anon {
+ return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
+ compute(*tcx.dep_context(), key)
+ });
+ }
- let side_effects = QuerySideEffects { diagnostics };
+ // `to_dep_node` is expensive for some `DepKind`s.
+ let dep_node = dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key));
- if unlikely!(!side_effects.is_empty()) {
- tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
- }
+ dep_graph.with_task(dep_node, *tcx.dep_context(), key, compute, query.hash_result)
+ });
- return job.complete(result, dep_node_index);
- }
+ prof_timer.finish_with_query_invocation_id(dep_node_index.into());
- let dep_node = query.to_dep_node(*tcx.dep_context(), &key);
+ let diagnostics = diagnostics.into_inner();
+ let side_effects = QuerySideEffects { diagnostics };
- if !query.eval_always {
- // The diagnostics for this query will be
- // promoted to the current session during
- // `try_mark_green()`, so we can ignore them here.
- let loaded = tcx.start_query(job.id, None, || {
- let marked = dep_graph.try_mark_green_and_read(tcx, &dep_node);
- marked.map(|(prev_dep_node_index, dep_node_index)| {
- (
- load_from_disk_and_cache_in_memory(
- tcx,
- key.clone(),
- prev_dep_node_index,
- dep_node_index,
- &dep_node,
- query,
- compute,
- ),
- dep_node_index,
- )
- })
- });
- if let Some((result, dep_node_index)) = loaded {
- return job.complete(result, dep_node_index);
+ if unlikely!(!side_effects.is_empty()) {
+ if query.anon {
+ tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
+ } else {
+ tcx.store_side_effects(dep_node_index, side_effects);
}
}
- let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute);
- dep_graph.read_index(dep_node_index);
- result
+ (result, dep_node_index)
}
-fn load_from_disk_and_cache_in_memory<CTX, K, V: Debug>(
+fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
tcx: CTX,
- key: K,
- prev_dep_node_index: SerializedDepNodeIndex,
- dep_node_index: DepNodeIndex,
+ key: &K,
dep_node: &DepNode<CTX::DepKind>,
query: &QueryVtable<CTX, K, V>,
compute: fn(CTX::DepContext, K) -> V,
-) -> V
+) -> Option<(V, DepNodeIndex)>
where
+ K: Clone,
CTX: QueryContext,
+ V: Debug,
{
// Note this function can be called concurrently from the same query
// We must ensure that this is handled correctly.
- debug_assert!(tcx.dep_context().dep_graph().is_green(dep_node));
+ let dep_graph = tcx.dep_context().dep_graph();
+ let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?;
+
+ debug_assert!(dep_graph.is_green(dep_node));
// First we try to load the result from the on-disk cache.
- let result = if query.cache_on_disk(tcx, &key, None) {
+ // Some things are never cached on disk.
+ if query.cache_on_disk(tcx, key, None) {
let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
let result = query.try_load_from_disk(tcx, prev_dep_node_index);
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
"missing on-disk cache entry for {:?}",
dep_node
);
- result
- } else {
- // Some things are never cached on disk.
- None
- };
- if let Some(result) = result {
- // If `-Zincremental-verify-ich` is specified, re-hash results from
- // the cache and make sure that they have the expected fingerprint.
- if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
- incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+ if let Some(result) = result {
+ // If `-Zincremental-verify-ich` is specified, re-hash results from
+ // the cache and make sure that they have the expected fingerprint.
+ if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+ incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+ }
+
+ return Some((result, dep_node_index));
}
+ }
- result
- } else {
- // We could not load a result from the on-disk cache, so
- // recompute.
- let prof_timer = tcx.dep_context().profiler().query_provider();
+ // We could not load a result from the on-disk cache, so
+ // recompute.
+ let prof_timer = tcx.dep_context().profiler().query_provider();
- // The dep-graph for this computation is already in-place.
- let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key));
+ // The dep-graph for this computation is already in-place.
+ let result = dep_graph.with_ignore(|| compute(*tcx.dep_context(), key.clone()));
- prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
- // Verify that re-running the query produced a result with the expected hash
- // This catches bugs in query implementations, turning them into ICEs.
- // For example, a query might sort its result by `DefId` - since `DefId`s are
- // not stable across compilation sessions, the result could get up getting sorted
- // in a different order when the query is re-run, even though all of the inputs
- // (e.g. `DefPathHash` values) were green.
- //
- // See issue #82920 for an example of a miscompilation that would get turned into
- // an ICE by this check
- incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+ prof_timer.finish_with_query_invocation_id(dep_node_index.into());
- result
- }
+ // Verify that re-running the query produced a result with the expected hash
+ // This catches bugs in query implementations, turning them into ICEs.
+ // For example, a query might sort its result by `DefId` - since `DefId`s are
+ // not stable across compilation sessions, the result could get up getting sorted
+ // in a different order when the query is re-run, even though all of the inputs
+ // (e.g. `DefPathHash` values) were green.
+ //
+ // See issue #82920 for an example of a miscompilation that would get turned into
+ // an ICE by this check
+ incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+
+ Some((result, dep_node_index))
}
fn incremental_verify_ich<CTX, K, V: Debug>(
}
}
-fn force_query_with_job<C, CTX>(
- tcx: CTX,
- key: C::Key,
- job: JobOwner<'_, CTX::DepKind, C>,
- dep_node: DepNode<CTX::DepKind>,
- query: &QueryVtable<CTX, C::Key, C::Value>,
- compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> (C::Stored, DepNodeIndex)
-where
- C: QueryCache,
- CTX: QueryContext,
-{
- // If the following assertion triggers, it can have two reasons:
- // 1. Something is wrong with DepNode creation, either here or
- // in `DepGraph::try_mark_green()`.
- // 2. Two distinct query keys get mapped to the same `DepNode`
- // (see for example #48923).
- assert!(
- !tcx.dep_context().dep_graph().dep_node_exists(&dep_node),
- "forcing query with already existing `DepNode`\n\
- - query-key: {:?}\n\
- - dep-node: {:?}",
- key,
- dep_node
- );
-
- let prof_timer = tcx.dep_context().profiler().query_provider();
-
- let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
- tcx.start_query(job.id, diagnostics, || {
- if query.eval_always {
- tcx.dep_context().dep_graph().with_eval_always_task(
- dep_node,
- *tcx.dep_context(),
- key,
- compute,
- query.hash_result,
- )
- } else {
- tcx.dep_context().dep_graph().with_task(
- dep_node,
- *tcx.dep_context(),
- key,
- compute,
- query.hash_result,
- )
- }
- })
- });
-
- prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
- let side_effects = QuerySideEffects { diagnostics };
-
- if unlikely!(!side_effects.is_empty()) && dep_node.kind != DepKind::NULL {
- tcx.store_side_effects(dep_node_index, side_effects);
- }
-
- let result = job.complete(result, dep_node_index);
-
- (result, dep_node_index)
-}
-
-#[inline(never)]
-fn get_query_impl<CTX, C>(
- tcx: CTX,
- state: &QueryState<CTX::DepKind, C::Key>,
- cache: &QueryCacheStore<C>,
- span: Span,
- key: C::Key,
- lookup: QueryLookup,
- query: &QueryVtable<CTX, C::Key, C::Value>,
- compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
-where
- CTX: QueryContext,
- C: QueryCache,
- C::Key: DepNodeParams<CTX::DepContext>,
-{
- try_execute_query(tcx, state, cache, span, key, lookup, query, compute)
-}
-
/// Ensure that either this query has all green inputs or been executed.
/// Executing `query::ensure(D)` is considered a read of the dep-node `D`.
/// Returns true if the query should still run.
///
/// Note: The optimization is only available during incr. comp.
#[inline(never)]
-fn ensure_must_run<CTX, K, V>(tcx: CTX, key: &K, query: &QueryVtable<CTX, K, V>) -> bool
+fn ensure_must_run<CTX, K, V>(
+ tcx: CTX,
+ key: &K,
+ query: &QueryVtable<CTX, K, V>,
+) -> (bool, Option<DepNode<CTX::DepKind>>)
where
K: crate::dep_graph::DepNodeParams<CTX::DepContext>,
CTX: QueryContext,
{
if query.eval_always {
- return true;
+ return (true, None);
}
// Ensuring an anonymous query makes no sense
let dep_node = query.to_dep_node(*tcx.dep_context(), key);
- match tcx.dep_context().dep_graph().try_mark_green_and_read(tcx, &dep_node) {
+ let dep_graph = tcx.dep_context().dep_graph();
+ match dep_graph.try_mark_green(tcx, &dep_node) {
None => {
- // A None return from `try_mark_green_and_read` means that this is either
+ // A None return from `try_mark_green` means that this is either
// a new dep node or that the dep node has already been marked red.
// Either way, we can't call `dep_graph.read()` as we don't have the
// DepNodeIndex. We must invoke the query itself. The performance cost
// this introduces should be negligible as we'll immediately hit the
// in-memory cache, or another query down the line will.
- true
+ (true, Some(dep_node))
}
Some((_, dep_node_index)) => {
+ dep_graph.read_index(dep_node_index);
tcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
- false
+ (false, None)
}
}
}
Err(lookup) => lookup,
};
- let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
- tcx,
- state,
- cache,
- DUMMY_SP,
- key.clone(),
- lookup,
- query,
- ) {
- TryGetJob::NotYetStarted(job) => job,
- TryGetJob::Cycle(_) => return true,
- #[cfg(parallel_compiler)]
- TryGetJob::JobCompleted(_) => return true,
- };
-
- force_query_with_job(tcx, key, job, dep_node, query, compute);
-
+ let _ =
+ try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), query, compute);
true
}
CTX: QueryContext,
{
let query = &Q::VTABLE;
- if let QueryMode::Ensure = mode {
- if !ensure_must_run(tcx, &key, query) {
+ let dep_node = if let QueryMode::Ensure = mode {
+ let (must_run, dep_node) = ensure_must_run(tcx, &key, query);
+ if !must_run {
return None;
}
- }
+ dep_node
+ } else {
+ None
+ };
debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
let compute = Q::compute_fn(tcx, &key);
- let value = get_query_impl(
+ let (result, dep_node_index) = try_execute_query(
tcx,
Q::query_state(tcx),
Q::query_cache(tcx),
span,
key,
lookup,
+ dep_node,
query,
compute,
);
- Some(value)
+ if let Some(dep_node_index) = dep_node_index {
+ tcx.dep_context().dep_graph().read_index(dep_node_index)
+ }
+ Some(result)
}
pub fn force_query<Q, CTX>(tcx: CTX, dep_node: &DepNode<CTX::DepKind>) -> bool
[package]
name = "rustc_resolve"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
let def_id = module.def_id().expect("unpopulated module without a def-id");
for child in self.cstore().item_children_untracked(def_id, self.session) {
- let child = child.map_id(|_| panic!("unexpected id"));
let parent_scope = ParentScope::module(module, self);
BuildReducedGraphVisitor { r: self, parent_scope }
.build_reduced_graph_for_external_crate_res(child);
}
/// Builds the reduced graph for a single item in an external crate.
- fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
+ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
let parent = self.parent_scope.module;
let Export { ident, res, vis, span } = child;
+ let res = res.expect_non_local();
let expansion = self.parent_scope.expansion;
// Record primary definitions.
match res {
fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
let parent_def = self.parent_def;
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
- self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span)
+ self.resolver.create_def(
+ parent_def,
+ node_id,
+ data,
+ self.expansion.to_expn_id(),
+ span.with_parent(None),
+ )
}
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
use rustc_ast::unwrap_or;
use rustc_ast::NodeId;
-use rustc_ast_lowering::ResolverAstLowering;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::ptr_key::PtrKey;
use rustc_errors::{pluralize, struct_span_err, Applicability};
let mut reexports = Vec::new();
- module.for_each_child(self.r, |this, ident, _, binding| {
+ module.for_each_child(self.r, |_, ident, _, binding| {
// Filter away ambiguous imports and anything that has def-site hygiene.
// FIXME: Implement actual cross-crate hygiene.
let is_good_import =
binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion();
if is_good_import || binding.is_macro_def() {
- let res = binding.res().map_id(|id| this.local_def_id(id));
+ let res = binding.res().expect_non_local();
if res != def::Res::Err {
reexports.push(Export { ident, res, span: binding.span, vis: binding.vis });
}
};
use rustc_ast_pretty::pprust::path_segment_to_string;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, SuggestionStyle};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
args[1].span.lo(),
args.last().unwrap().span.hi(),
call_span.ctxt(),
+ None,
))
} else {
None
introduce_suggestion.push((*span, formatter(<_name)));
}
}
- err.multipart_suggestion_with_style(
+ err.multipart_suggestion_verbose(
&msg,
introduce_suggestion,
Applicability::MaybeIncorrect,
- SuggestionStyle::ShowAlways,
);
}
})
.map(|(formatter, span)| (*span, formatter(name)))
.collect();
- err.multipart_suggestion_with_style(
+ err.multipart_suggestion_verbose(
&format!(
"consider using the `{}` lifetime",
lifetime_names.iter().next().unwrap()
),
spans_suggs,
Applicability::MaybeIncorrect,
- SuggestionStyle::ShowAlways,
);
};
let suggest_new = |err: &mut DiagnosticBuilder<'_>, suggs: Vec<Option<String>>| {
};
spans_suggs.push((span, sugg.to_string()));
}
- err.multipart_suggestion_with_style(
+ err.multipart_suggestion_verbose(
"consider using the `'static` lifetime",
spans_suggs,
Applicability::MaybeIncorrect,
- SuggestionStyle::ShowAlways,
);
continue;
}
.unwrap_or((span, sugg));
introduce_suggestion.push((span, sugg.to_string()));
}
- err.multipart_suggestion_with_style(
+ err.multipart_suggestion_verbose(
&msg,
introduce_suggestion,
Applicability::MaybeIncorrect,
- SuggestionStyle::ShowAlways,
);
if should_break {
break;
if spans_suggs.len() > 0 {
// This happens when we have `Foo<T>` where we point at the space before `T`,
// but this can be confusing so we give a suggestion with placeholders.
- err.multipart_suggestion_with_style(
+ err.multipart_suggestion_verbose(
"consider using one of the available lifetimes here",
spans_suggs,
Applicability::HasPlaceholders,
- SuggestionStyle::ShowAlways,
);
}
}
_ => {}
}
let item = {
- let hir = tcx.hir();
- let mut parent_iter = hir.parent_iter(hir_id);
+ let mut parent_iter = tcx.hir().parent_iter(hir_id);
loop {
let node = parent_iter.next().map(|n| n.1);
match node {
}
fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> {
- if let hir::ExprKind::Loop(_, Some(label), ..) = ex.kind { Some(label.ident) } else { None }
+ match ex.kind {
+ hir::ExprKind::Loop(_, Some(label), ..) => Some(label.ident),
+ hir::ExprKind::Block(_, Some(label)) => Some(label.ident),
+ _ => None,
+ }
}
fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) {
// ensure that we issue lints in a repeatable order
def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id));
- for def_id in def_ids {
+ 'lifetimes: for def_id in def_ids {
debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id);
let lifetimeuseset = self.lifetime_uses.remove(&def_id);
{
continue;
}
+
+ // opaque types generated when desugaring an async function can have a single
+ // use lifetime even if it is explicitly denied (Issue #77175)
+ if let hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::OpaqueTy(ref opaque),
+ ..
+ }) = self.tcx.hir().get(parent_hir_id)
+ {
+ if opaque.origin != hir::OpaqueTyOrigin::AsyncFn {
+ continue 'lifetimes;
+ }
+ // We want to do this only if the liftime identifier is already defined
+ // in the async function that generated this. Otherwise it could be
+ // an opaque type defined by the developer and we still want this
+ // lint to fail compilation
+ for p in opaque.generics.params {
+ if defined_by.contains_key(&p.name) {
+ continue 'lifetimes;
+ }
+ }
+ }
}
}
#![feature(crate_visibility_modifier)]
#![feature(format_args_capture)]
#![feature(iter_zip)]
+#![feature(never_type)]
#![feature(nll)]
#![recursion_limit = "256"]
#![allow(rustdoc::private_intra_doc_links)]
/// `CrateNum` resolutions of `extern crate` items.
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
- export_map: ExportMap<LocalDefId>,
+ export_map: ExportMap,
trait_map: Option<NodeMap<Vec<TraitCandidate>>>,
/// A map from nodes to anonymous modules.
next_node_id: NodeId,
- def_id_to_span: IndexVec<LocalDefId, Span>,
-
node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
}
}
+ #[inline]
+ fn def_span(&self, id: LocalDefId) -> Span {
+ self.definitions.def_span(id)
+ }
+
fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
if let Some(def_id) = def_id.as_local() {
self.item_generics_num_lifetimes[&def_id]
disambiguator
};
- let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator);
-
- assert_eq!(self.def_id_to_span.push(span), def_id);
+ let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator, span);
// Some things for which we allocate `LocalDefId`s don't correspond to
// anything in the AST, so they don't have a `NodeId`. For these cases
true
}
+ #[inline]
+ fn def_span(&self, id: LocalDefId) -> Span {
+ self.resolver.def_span(id)
+ }
+
#[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
self.resolver.def_path_hash(def_id)
let mut module_map = FxHashMap::default();
module_map.insert(root_local_def_id, graph_root);
- let definitions = Definitions::new(session.local_stable_crate_id());
+ let definitions = Definitions::new(session.local_stable_crate_id(), krate.span);
let root = definitions.get_root_def();
let mut visibilities = FxHashMap::default();
visibilities.insert(root_local_def_id, ty::Visibility::Public);
- let mut def_id_to_span = IndexVec::default();
- assert_eq!(def_id_to_span.push(rustc_span::DUMMY_SP), root);
let mut def_id_to_node_id = IndexVec::default();
assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
let mut node_id_to_def_id = FxHashMap::default();
.collect(),
lint_buffer: LintBuffer::default(),
next_node_id: NodeId::from_u32(1),
- def_id_to_span,
node_id_to_def_id,
def_id_to_node_id,
placeholder_field_indices: Default::default(),
.iter()
.map(|(ident, entry)| (ident.name, entry.introduced_by_item))
.collect(),
- main_def: self.main_def.clone(),
+ main_def: self.main_def,
trait_impls: self.trait_impls.clone(),
proc_macros,
confused_type_with_std_module: self.confused_type_with_std_module.clone(),
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
#[inline]
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
- if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
+ def_id.as_local().map(|def_id| self.definitions.def_span(def_id))
}
/// Checks if an expression refers to a function marked with
self.next_node_id()
}
+ fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId {
+ self.invocation_parents[&id].0
+ }
+
fn resolve_dollar_crates(&mut self) {
hygiene::update_dollar_crate_names(|ctxt| {
let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
[package]
name = "rustc_save_analysis"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
[package]
name = "rustc_serialize"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
indexmap = "1"
char emit_char read_char
}
+impl<S: Encoder> Encodable<S> for ! {
+ fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
+ unreachable!()
+ }
+}
+
+impl<D: Decoder> Decodable<D> for ! {
+ fn decode(_d: &mut D) -> Result<!, D::Error> {
+ unreachable!()
+ }
+}
+
impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.get())
[package]
name = "rustc_session"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
getopts = "0.2"
fn parse_remap_path_prefix(
matches: &getopts::Matches,
+ debugging_opts: &DebuggingOptions,
error_format: ErrorOutputType,
) -> Vec<(PathBuf, PathBuf)> {
- matches
+ let mut mapping: Vec<(PathBuf, PathBuf)> = matches
.opt_strs("remap-path-prefix")
.into_iter()
.map(|remap| match remap.rsplit_once('=') {
),
Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
})
- .collect()
+ .collect();
+ match &debugging_opts.remap_cwd_prefix {
+ Some(to) => match std::env::current_dir() {
+ Ok(cwd) => mapping.push((cwd, to.clone())),
+ Err(_) => (),
+ },
+ None => (),
+ };
+ mapping
}
pub fn build_session_options(matches: &getopts::Matches) -> Options {
let crate_name = matches.opt_str("crate-name");
- let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
+ let remap_path_prefix = parse_remap_path_prefix(matches, &debugging_opts, error_format);
let pretty = parse_pretty(&debugging_opts, error_format);
+//! A module for searching for libraries
+
pub use self::FileMatch::*;
use std::env;
FileDoesntMatch,
}
-// A module for searching for libraries
-
#[derive(Clone)]
pub struct FileSearch<'a> {
sysroot: &'a Path,
FileSearch { sysroot, triple, search_paths, tlib_path, kind }
}
- // Returns just the directories within the search paths.
+ /// Returns just the directories within the search paths.
pub fn search_path_dirs(&self) -> Vec<PathBuf> {
self.search_paths().map(|sp| sp.dir.to_path_buf()).collect()
}
-
- // Returns a list of directories where target-specific tool binaries are located.
- pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
- let rustlib_path = rustc_target::target_rustlib_path(self.sysroot, &self.triple);
- let p = std::array::IntoIter::new([
- Path::new(&self.sysroot),
- Path::new(&rustlib_path),
- Path::new("bin"),
- ])
- .collect::<PathBuf>();
- if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
- }
}
pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
.collect::<PathBuf>()
}
-// This function checks if sysroot is found using env::args().next(), and if it
-// is not found, uses env::current_exe() to imply sysroot.
+/// This function checks if sysroot is found using env::args().next(), and if it
+/// is not found, uses env::current_exe() to imply sysroot.
pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: PathBuf) -> PathBuf {
pub const parse_threads: &str = parse_number;
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
+ pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
pub const parse_sanitizers: &str =
"comma separated list of sanitizers: `address`, `hwaddress`, `leak`, `memory` or `thread`";
}
}
- crate fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
+ crate fn parse_opt_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
match v {
Some("unwind") => *slot = Some(PanicStrategy::Unwind),
Some("abort") => *slot = Some(PanicStrategy::Abort),
true
}
+ crate fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
+ match v {
+ Some("unwind") => *slot = PanicStrategy::Unwind,
+ Some("abort") => *slot = PanicStrategy::Abort,
+ _ => return false,
+ }
+ true
+ }
+
crate fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
match v {
Some(s) => match s.parse::<RelroLevel>() {
"optimization level (0-3, s, or z; default: 0)"),
overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use overflow checks for integer arithmetic"),
- panic: Option<PanicStrategy> = (None, parse_panic_strategy, [TRACKED],
+ panic: Option<PanicStrategy> = (None, parse_opt_panic_strategy, [TRACKED],
"panic strategy to compile crate with"),
passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list of extra LLVM passes to run (space separated)"),
incremental_info: bool = (false, parse_bool, [UNTRACKED],
"print high-level information about incremental reuse (or the lack thereof) \
(default: no)"),
+ incremental_relative_spans: bool = (false, parse_bool, [TRACKED],
+ "hash spans relative to their parent item for incr. comp. (default: no)"),
incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
"verify incr. comp. hashes of green query instances (default: no)"),
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
"pass `-install_name @rpath/...` to the macOS linker (default: no)"),
panic_abort_tests: bool = (false, parse_bool, [TRACKED],
"support compiling tests with panic=abort (default: no)"),
+ panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
+ "panic strategy for panics in drops"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link (default: no)"),
partially_uninit_const_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"whether ELF relocations can be relaxed"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
+ remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+ "remap paths under the current working directory to this path prefix"),
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
to rust's source base directory. only meant for testing purposes"),
pub files: Vec<SearchPathFile>,
}
-// The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But
-// it is searched repeatedly by `find_library_crate`, and the searches involve
-// checking the prefix and suffix of the filename of each `PathBuf`. This is
-// doable, but very slow, because it involves calls to `file_name` and
-// `extension` that are themselves slow.
-//
-// This type augments the `PathBuf` with an `Option<String>` containing the
-// `PathBuf`'s filename. The prefix and suffix checking is much faster on the
-// `Option<String>` than the `PathBuf`. (It's an `Option` because
-// `Path::file_name` can fail; if that happens then all subsequent checking
-// will also fail, which is fine.)
+/// The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But
+/// it is searched repeatedly by `find_library_crate`, and the searches involve
+/// checking the prefix and suffix of the filename of each `PathBuf`. This is
+/// doable, but very slow, because it involves calls to `file_name` and
+/// `extension` that are themselves slow.
+///
+/// This type augments the `PathBuf` with an `Option<String>` containing the
+/// `PathBuf`'s filename. The prefix and suffix checking is much faster on the
+/// `Option<String>` than the `PathBuf`. (It's an `Option` because
+/// `Path::file_name` can fail; if that happens then all subsequent checking
+/// will also fail, which is fine.)
#[derive(Clone, Debug)]
pub struct SearchPathFile {
pub path: PathBuf,
use std::io::Write;
use std::num::NonZeroU32;
use std::ops::{Div, Mul};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
pub target: Target,
pub host: Target,
pub opts: config::Options,
- pub host_tlib_path: SearchPath,
- /// `None` if the host and target are the same.
- pub target_tlib_path: Option<SearchPath>,
+ pub host_tlib_path: Lrc<SearchPath>,
+ pub target_tlib_path: Lrc<SearchPath>,
pub parse_sess: ParseSess,
pub sysroot: PathBuf,
/// The name of the root source file of the crate, in the local file system.
&self.sysroot,
self.opts.target_triple.triple(),
&self.opts.search_paths,
- // `target_tlib_path == None` means it's the same as `host_tlib_path`.
- self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path),
+ &self.target_tlib_path,
kind,
)
}
)
}
+ /// Returns a list of directories where target-specific tool binaries are located.
+ pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
+ let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple());
+ let p = std::array::IntoIter::new([
+ Path::new(&self.sysroot),
+ Path::new(&rustlib_path),
+ Path::new("bin"),
+ ])
+ .collect::<PathBuf>();
+ if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
+ }
+
pub fn init_incr_comp_session(
&self,
session_dir: PathBuf,
let host_triple = config::host_triple();
let target_triple = sopts.target_triple.triple();
- let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple);
+ let host_tlib_path = Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
let target_tlib_path = if host_triple == target_triple {
- None
+ // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
+ // rescanning of the target lib path and an unnecessary allocation.
+ host_tlib_path.clone()
} else {
- Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
+ Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
};
let file_path_mapping = sopts.file_path_mapping();
[package]
name = "rustc_span"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
// Span lo and hi may equal line end when last line doesn't
// end in newline, hence the inclusive upper bounds below.
- debug_assert!(span_data.lo >= lo.line.start);
- debug_assert!(span_data.lo <= lo.line.end);
- debug_assert!(span_data.hi >= hi.line.start);
- debug_assert!(span_data.hi <= hi.line.end);
- debug_assert!(lo.file.contains(span_data.lo));
- debug_assert!(lo.file.contains(span_data.hi));
- debug_assert_eq!(lo.file_index, hi.file_index);
+ assert!(span_data.lo >= lo.line.start);
+ assert!(span_data.lo <= lo.line.end);
+ assert!(span_data.hi >= hi.line.start);
+ assert!(span_data.hi <= hi.line.end);
+ assert!(lo.file.contains(span_data.lo));
+ assert!(lo.file.contains(span_data.hi));
+ assert_eq!(lo.file_index, hi.file_index);
Some((
lo.file.clone(),
mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
) -> Result<(), E> {
let all_data: Vec<_> = HygieneData::with(|data| {
- expns
- .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone()))
- .collect()
+ expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
});
for (expn, data, hash) in all_data.into_iter() {
f(expn, &data, hash)?;
pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
pub mod def_id;
-use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
+use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
pub mod lev_distance;
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
// threads within the compilation session, but is not accessible outside the
// session.
pub struct SessionGlobals {
- symbol_interner: Lock<symbol::Interner>,
+ symbol_interner: symbol::Interner,
span_interner: Lock<span_encoding::SpanInterner>,
hygiene_data: Lock<hygiene::HygieneData>,
source_map: Lock<Option<Lrc<SourceMap>>>,
impl SessionGlobals {
pub fn new(edition: Edition) -> SessionGlobals {
SessionGlobals {
- symbol_interner: Lock::new(symbol::Interner::fresh()),
+ symbol_interner: symbol::Interner::fresh(),
span_interner: Lock::new(span_encoding::SpanInterner::default()),
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
source_map: Lock::new(None),
/// Information about where the macro came from, if this piece of
/// code was created by a macro expansion.
pub ctxt: SyntaxContext,
+ pub parent: Option<LocalDefId>,
}
impl SpanData {
#[inline]
pub fn span(&self) -> Span {
- Span::new(self.lo, self.hi, self.ctxt)
+ Span::new(self.lo, self.hi, self.ctxt, self.parent)
}
#[inline]
pub fn with_lo(&self, lo: BytePos) -> Span {
- Span::new(lo, self.hi, self.ctxt)
+ Span::new(lo, self.hi, self.ctxt, self.parent)
}
#[inline]
pub fn with_hi(&self, hi: BytePos) -> Span {
- Span::new(self.lo, hi, self.ctxt)
+ Span::new(self.lo, hi, self.ctxt, self.parent)
}
#[inline]
pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
- Span::new(self.lo, self.hi, ctxt)
+ Span::new(self.lo, self.hi, ctxt, self.parent)
+ }
+ #[inline]
+ pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
+ Span::new(self.lo, self.hi, self.ctxt, parent)
+ }
+ /// Returns `true` if this is a dummy span with any hygienic context.
+ #[inline]
+ pub fn is_dummy(self) -> bool {
+ self.lo.0 == 0 && self.hi.0 == 0
+ }
+ /// Returns `true` if `self` fully encloses `other`.
+ pub fn contains(self, other: Self) -> bool {
+ self.lo <= other.lo && other.hi <= self.hi
}
}
}
#[inline]
pub fn ctxt(self) -> SyntaxContext {
- self.data().ctxt
+ self.data_untracked().ctxt
}
#[inline]
pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
- self.data().with_ctxt(ctxt)
+ self.data_untracked().with_ctxt(ctxt)
+ }
+ #[inline]
+ pub fn parent(self) -> Option<LocalDefId> {
+ self.data().parent
+ }
+ #[inline]
+ pub fn with_parent(self, ctxt: Option<LocalDefId>) -> Span {
+ self.data().with_parent(ctxt)
}
/// Returns `true` if this is a dummy span with any hygienic context.
#[inline]
pub fn is_dummy(self) -> bool {
- let span = self.data();
- span.lo.0 == 0 && span.hi.0 == 0
+ self.data_untracked().is_dummy()
}
/// Returns `true` if this span comes from a macro or desugaring.
#[inline]
pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
- Span::new(lo, hi, SyntaxContext::root())
+ Span::new(lo, hi, SyntaxContext::root(), None)
}
/// Returns a new span representing an empty span at the beginning of this span.
#[inline]
pub fn shrink_to_lo(self) -> Span {
- let span = self.data();
+ let span = self.data_untracked();
span.with_hi(span.lo)
}
/// Returns a new span representing an empty span at the end of this span.
#[inline]
pub fn shrink_to_hi(self) -> Span {
- let span = self.data();
+ let span = self.data_untracked();
span.with_lo(span.hi)
}
#[inline]
/// Returns `true` if `hi == lo`.
pub fn is_empty(&self) -> bool {
- let span = self.data();
+ let span = self.data_untracked();
span.hi == span.lo
}
pub fn contains(self, other: Span) -> bool {
let span = self.data();
let other = other.data();
- span.lo <= other.lo && other.hi <= span.hi
+ span.contains(other)
}
/// Returns `true` if `self` touches `other`.
/// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
/// if any.
- pub fn parent(self) -> Option<Span> {
+ pub fn parent_callsite(self) -> Option<Span> {
let expn_data = self.ctxt().outer_expn_data();
if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
}
/// Walk down the expansion ancestors to find a span that's contained within `outer`.
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
while !outer.contains(self) {
- self = self.parent()?;
+ self = self.parent_callsite()?;
}
Some(self)
}
cmp::min(span_data.lo, end_data.lo),
cmp::max(span_data.hi, end_data.hi),
if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
+ if span_data.parent == end_data.parent { span_data.parent } else { None },
)
}
span.hi,
end.lo,
if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+ if span.parent == end.parent { span.parent } else { None },
)
}
span.lo,
end.lo,
if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+ if span.parent == end.parent { span.parent } else { None },
)
}
span.lo + BytePos::from_usize(inner.start),
span.lo + BytePos::from_usize(inner.end),
span.ctxt,
+ span.parent,
)
}
pub fn remove_mark(&mut self) -> ExpnId {
let mut span = self.data();
let mark = span.ctxt.remove_mark();
- *self = Span::new(span.lo, span.hi, span.ctxt);
+ *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
mark
}
pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
let mut span = self.data();
let mark = span.ctxt.adjust(expn_id);
- *self = Span::new(span.lo, span.hi, span.ctxt);
+ *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
mark
}
pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
let mut span = self.data();
let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
- *self = Span::new(span.lo, span.hi, span.ctxt);
+ *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
mark
}
pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
let mut span = self.data();
let mark = span.ctxt.glob_adjust(expn_id, glob_span);
- *self = Span::new(span.lo, span.hi, span.ctxt);
+ *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
mark
}
) -> Option<Option<ExpnId>> {
let mut span = self.data();
let mark = span.ctxt.reverse_glob_adjust(expn_id, glob_span);
- *self = Span::new(span.lo, span.hi, span.ctxt);
+ *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
mark
}
let lo = d.read_struct_field("lo", Decodable::decode)?;
let hi = d.read_struct_field("hi", Decodable::decode)?;
- Ok(Span::new(lo, hi, SyntaxContext::root()))
+ Ok(Span::new(lo, hi, SyntaxContext::root(), None))
})
}
}
impl fmt::Debug for SpanData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt), f)
+ (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt, self.parent), f)
}
}
pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
// _____________________________________________________________________________
// SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
pub trait HashStableContext {
fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
fn hash_spans(&self) -> bool;
+ fn def_span(&self, def_id: LocalDefId) -> Span;
fn span_data_to_lines_and_cols(
&mut self,
span: &SpanData,
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
const TAG_VALID_SPAN: u8 = 0;
const TAG_INVALID_SPAN: u8 = 1;
+ const TAG_RELATIVE_SPAN: u8 = 2;
if !ctx.hash_spans() {
return;
}
- self.ctxt().hash_stable(ctx, hasher);
+ let span = self.data_untracked();
+ span.ctxt.hash_stable(ctx, hasher);
+ span.parent.hash_stable(ctx, hasher);
- if self.is_dummy() {
+ if span.is_dummy() {
Hash::hash(&TAG_INVALID_SPAN, hasher);
return;
}
+ if let Some(parent) = span.parent {
+ let def_span = ctx.def_span(parent).data_untracked();
+ if def_span.contains(span) {
+ // This span is enclosed in a definition: only hash the relative position.
+ Hash::hash(&TAG_RELATIVE_SPAN, hasher);
+ (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
+ (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
+ return;
+ }
+ }
+
// If this is not an empty or invalid span, we want to hash the last
// position that belongs to it, as opposed to hashing the first
// position past it.
- let span = self.data();
let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
{
Some(pos) => pos,
start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point);
let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point));
- Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt())
+ Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
}
/// Finds the width of the character, either before or after the end of provided span,
// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
+use crate::def_id::LocalDefId;
use crate::hygiene::SyntaxContext;
+use crate::SPAN_TRACK;
use crate::{BytePos, SpanData};
use rustc_data_structures::fx::FxIndexSet;
/// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
/// but larger crates might need more than 16 bits.
///
+/// In order to reliably use parented spans in incremental compilation,
+/// the dependency to the parent definition's span. This is performed
+/// using the callback `SPAN_TRACK` to access the query engine.
+///
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
pub struct Span {
base_or_index: u32,
impl Span {
#[inline]
- pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self {
+ pub fn new(
+ mut lo: BytePos,
+ mut hi: BytePos,
+ ctxt: SyntaxContext,
+ parent: Option<LocalDefId>,
+ ) -> Self {
if lo > hi {
std::mem::swap(&mut lo, &mut hi);
}
let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32());
- if len <= MAX_LEN && ctxt2 <= MAX_CTXT {
+ if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() {
// Inline format.
Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 }
} else {
// Interned format.
- let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt }));
+ let index =
+ with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }));
Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 }
}
}
#[inline]
pub fn data(self) -> SpanData {
+ let data = self.data_untracked();
+ if let Some(parent) = data.parent {
+ (*SPAN_TRACK)(parent);
+ }
+ data
+ }
+
+ /// Internal function to translate between an encoded span and the expanded representation.
+ /// This function must not be used outside the incremental engine.
+ #[inline]
+ pub fn data_untracked(self) -> SpanData {
if self.len_or_tag != LEN_TAG {
// Inline format.
debug_assert!(self.len_or_tag as u32 <= MAX_LEN);
lo: BytePos(self.base_or_index),
hi: BytePos(self.base_or_index + self.len_or_tag as u32),
ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32),
+ parent: None,
}
} else {
// Interned format.
use rustc_arena::DroplessArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::sync::Lock;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
panic_2021,
panic_abort,
panic_bounds_check,
+ panic_display,
panic_fmt,
panic_handler,
panic_impl,
panic_unwind,
panicking,
param_attrs,
- parent_trait,
partial_cmp,
partial_ord,
passes,
rustc_synthetic,
rustc_test_marker,
rustc_then_this_would_need,
+ rustc_trivial_field_reads,
rustc_unsafe_specialization_marker,
rustc_variance,
rustdoc,
simd_select_bitmask,
simd_shl,
simd_shr,
+ simd_shuffle,
simd_sub,
simd_trunc,
simd_xor,
unix,
unlikely,
unmarked_api,
- unnamed_fields,
unpin,
unreachable,
unreachable_code,
wrapping_sub,
wreg,
write_bytes,
+ write_str,
x87_reg,
xer,
xmm_reg,
/// Maps a string to its interned representation.
pub fn intern(string: &str) -> Self {
- with_interner(|interner| interner.intern(string))
+ with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
}
/// Convert to a `SymbolStr`. This is a slowish operation because it
/// requires locking the symbol interner.
pub fn as_str(self) -> SymbolStr {
- with_interner(|interner| unsafe {
- SymbolStr { string: std::mem::transmute::<&str, &str>(interner.get(self)) }
+ with_session_globals(|session_globals| {
+ let symbol_str = session_globals.symbol_interner.get(self);
+ unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } }
})
}
}
pub fn len(self) -> usize {
- with_interner(|interner| interner.get(self).len())
+ with_session_globals(|session_globals| session_globals.symbol_interner.get(self).len())
}
pub fn is_empty(self) -> bool {
}
}
+#[derive(Default)]
+pub(crate) struct Interner(Lock<InternerInner>);
+
// The `&'static str`s in this type actually point into the arena.
//
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
// found that to regress performance up to 2% in some cases. This might be
// revisited after further improvements to `indexmap`.
+//
+// This type is private to prevent accidentally constructing more than one `Interner` on the same
+// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
#[derive(Default)]
-pub struct Interner {
+struct InternerInner {
arena: DroplessArena,
names: FxHashMap<&'static str, Symbol>,
strings: Vec<&'static str>,
impl Interner {
fn prefill(init: &[&'static str]) -> Self {
- Interner {
+ Interner(Lock::new(InternerInner {
strings: init.into(),
names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
..Default::default()
- }
+ }))
}
#[inline]
- pub fn intern(&mut self, string: &str) -> Symbol {
- if let Some(&name) = self.names.get(string) {
+ fn intern(&self, string: &str) -> Symbol {
+ let mut inner = self.0.lock();
+ if let Some(&name) = inner.names.get(string) {
return name;
}
- let name = Symbol::new(self.strings.len() as u32);
+ let name = Symbol::new(inner.strings.len() as u32);
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
// UTF-8.
let string: &str =
- unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
+ unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
// It is safe to extend the arena allocation to `'static` because we only access
// these while the arena is still alive.
let string: &'static str = unsafe { &*(string as *const str) };
- self.strings.push(string);
- self.names.insert(string, name);
+ inner.strings.push(string);
+ inner.names.insert(string, name);
name
}
// Get the symbol as a string. `Symbol::as_str()` should be used in
// preference to this function.
- pub fn get(&self, symbol: Symbol) -> &str {
- self.strings[symbol.0.as_usize()]
+ fn get(&self, symbol: Symbol) -> &str {
+ self.0.lock().strings[symbol.0.as_usize()]
}
}
}
}
-#[inline]
-fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
- with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
-}
-
/// An alternative to [`Symbol`], useful when the chars within the symbol need to
/// be accessed. It deliberately has limited functionality and should only be
/// used for temporary values.
#[test]
fn interner_tests() {
- let mut i: Interner = Interner::default();
+ let i = Interner::default();
// first one is zero:
assert_eq!(i.intern("dog"), Symbol::new(0));
// re-use gets the same entry:
[package]
name = "rustc_symbol_mangling"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_target"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
bitflags = "1.2.1"
--- /dev/null
+use crate::abi::call::{ArgAbi, FnAbi};
+
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
+ if ret.layout.is_aggregate() {
+ ret.make_indirect();
+ } else {
+ ret.extend_integer_width_to(32);
+ }
+}
+
+fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
+ if arg.layout.is_aggregate() {
+ arg.make_indirect_byval();
+ } else {
+ arg.extend_integer_width_to(32);
+ }
+}
+
+pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
+ if !fn_abi.ret.is_ignore() {
+ classify_ret(&mut fn_abi.ret);
+ }
+
+ for arg in &mut fn_abi.args {
+ if arg.is_ignore() {
+ continue;
+ }
+ classify_arg(arg);
+ }
+}
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
// Always sign extend u32 values on 64-bit mips
- if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+ if let abi::Abi::Scalar(scalar) = arg.layout.abi {
if let abi::Int(i, signed) = scalar.value {
if !signed && i.size().bits() == 32 {
if let PassMode::Direct(ref mut attrs) = arg.mode {
C: HasDataLayout,
{
match ret.layout.field(cx, i).abi {
- abi::Abi::Scalar(ref scalar) => match scalar.value {
+ abi::Abi::Scalar(scalar) => match scalar.value {
abi::F32 => Some(Reg::f32()),
abi::F64 => Some(Reg::f64()),
_ => None,
let offset = arg.layout.fields.offset(i);
// We only care about aligned doubles
- if let abi::Abi::Scalar(ref scalar) = field.abi {
+ if let abi::Abi::Scalar(scalar) = field.abi {
if let abi::F64 = scalar.value {
if offset.is_aligned(dl.f64_align.abi) {
// Insert enough integers to cover [last_offset, offset)
use crate::abi::{self, Abi, Align, FieldsShape, Size};
use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
use crate::spec::{self, HasTargetSpec};
+use std::fmt;
mod aarch64;
mod amdgpu;
mod avr;
mod bpf;
mod hexagon;
+mod m68k;
mod mips;
mod mips64;
mod msp430;
mod x86_64;
mod x86_win64;
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum PassMode {
/// Ignore the argument.
///
mod attr_impl {
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
bitflags::bitflags! {
- #[derive(Default)]
+ #[derive(Default, HashStable_Generic)]
pub struct ArgAttribute: u16 {
const NoAlias = 1 << 1;
const NoCapture = 1 << 2;
/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
/// defines if this extension should be zero-extension or sign-extension when necessary. When it is
/// not necessary to extend the argument, this enum is ignored.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum ArgExtension {
None,
Zext,
/// A compact representation of LLVM attributes (at least those relevant for this module)
/// that can be manipulated without interacting with LLVM's Attribute machinery.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct ArgAttributes {
pub regular: ArgAttribute,
pub arg_ext: ArgExtension,
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum RegKind {
Integer,
Float,
Vector,
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct Reg {
pub kind: RegKind,
pub size: Size,
/// An argument passed entirely registers with the
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct Uniform {
pub unit: Reg,
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct CastTarget {
pub prefix: [Option<RegKind>; 8],
pub prefix_chunk_size: Size,
Abi::Uninhabited => Err(Heterogeneous),
// The primitive for this algorithm.
- Abi::Scalar(ref scalar) => {
+ Abi::Scalar(scalar) => {
let kind = match scalar.value {
abi::Int(..) | abi::Pointer => RegKind::Integer,
abi::F32 | abi::F64 => RegKind::Float,
/// Information about how to pass an argument to,
/// or return a value from, a function, under some ABI.
-#[derive(Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct ArgAbi<'a, Ty> {
pub layout: TyAndLayout<'a, Ty>,
pub fn new(
cx: &impl HasDataLayout,
layout: TyAndLayout<'a, Ty>,
- scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes,
+ scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes,
) -> Self {
- let mode = match &layout.abi {
+ let mode = match layout.abi {
Abi::Uninhabited => PassMode::Ignore,
Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
Abi::ScalarPair(a, b) => PassMode::Pair(
pub fn extend_integer_width_to(&mut self, bits: u64) {
// Only integers have signedness
- if let Abi::Scalar(ref scalar) = self.layout.abi {
+ if let Abi::Scalar(scalar) = self.layout.abi {
if let abi::Int(i, signed) = scalar.value {
if i.size().bits() < bits {
if let PassMode::Direct(ref mut attrs) = self.mode {
}
}
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum Conv {
// General language calling conventions, for which every target
// should have its own backend (e.g. LLVM) support.
///
/// I will do my best to describe this structure, but these
/// comments are reverse-engineered and may be inaccurate. -NDM
-#[derive(Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct FnAbi<'a, Ty> {
/// The LLVM types of each argument.
pub args: Vec<ArgAbi<'a, Ty>>,
pub can_unwind: bool,
}
+/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
+#[derive(Clone, Debug, HashStable_Generic)]
+pub enum AdjustForForeignAbiError {
+ /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs.
+ Unsupported { arch: String, abi: spec::abi::Abi },
+}
+
+impl fmt::Display for AdjustForForeignAbiError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Unsupported { arch, abi } => {
+ write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi)
+ }
+ }
+ }
+}
+
impl<'a, Ty> FnAbi<'a, Ty> {
- pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
+ pub fn adjust_for_foreign_abi<C>(
+ &mut self,
+ cx: &C,
+ abi: spec::abi::Abi,
+ ) -> Result<(), AdjustForForeignAbiError>
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec,
"amdgpu" => amdgpu::compute_abi_info(cx, self),
"arm" => arm::compute_abi_info(cx, self),
"avr" => avr::compute_abi_info(self),
+ "m68k" => m68k::compute_abi_info(self),
"mips" => mips::compute_abi_info(cx, self),
"mips64" => mips64::compute_abi_info(cx, self),
"powerpc" => powerpc::compute_abi_info(self),
}
"asmjs" => wasm::compute_c_abi_info(cx, self),
"bpf" => bpf::compute_abi_info(self),
- a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
+ arch => {
+ return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi });
+ }
}
Ok(())
Ty: TyAbiInterface<'a, C> + Copy,
{
match arg_layout.abi {
- Abi::Scalar(ref scalar) => match scalar.value {
+ Abi::Scalar(scalar) => match scalar.value {
abi::Int(..) | abi::Pointer => {
if arg_layout.size.bits() > xlen {
return Err(CannotUseFpConv);
}
fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
- if let Abi::Scalar(ref scalar) = arg.layout.abi {
+ if let Abi::Scalar(scalar) = arg.layout.abi {
if let abi::Int(i, _) = scalar.value {
// 32-bit integers are always sign-extended
if i.size().bits() == 32 && xlen > 32 {
C: HasDataLayout,
{
match layout.abi {
- abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+ abi::Abi::Scalar(scalar) => scalar.value.is_float(),
abi::Abi::Aggregate { .. } => {
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
is_single_fp_element(cx, layout.field(cx, 0))
C: HasDataLayout,
{
match layout.abi {
- abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+ abi::Abi::Scalar(scalar) => scalar.value.is_float(),
abi::Abi::Aggregate { .. } => {
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
is_single_fp_element(cx, layout.field(cx, 0))
let mut c = match layout.abi {
Abi::Uninhabited => return Ok(()),
- Abi::Scalar(ref scalar) => match scalar.value {
+ Abi::Scalar(scalar) => match scalar.value {
abi::Int(..) | abi::Pointer => Class::Int,
abi::F32 | abi::F64 => Class::Sse,
},
use std::fmt;
use std::iter::Step;
use std::num::NonZeroUsize;
-use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
use std::str::FromStr;
use rustc_index::vec::{Idx, IndexVec};
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
(value << shift) >> shift
}
+
+ #[inline]
+ pub fn signed_int_min(&self) -> i128 {
+ self.sign_extend(1_u128 << (self.bits() - 1)) as i128
+ }
+
+ #[inline]
+ pub fn signed_int_max(&self) -> i128 {
+ i128::MAX >> (128 - self.bits())
+ }
+
+ #[inline]
+ pub fn unsigned_int_max(&self) -> u128 {
+ u128::MAX >> (128 - self.bits())
+ }
}
// Panicking addition, subtraction and multiplication for convenience.
///
/// 254 (-2), 255 (-1), 0, 1, 2
///
-/// This is intended specifically to mirror LLVM’s `!range` metadata,
-/// semantics.
-#[derive(Clone, PartialEq, Eq, Hash)]
+/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct WrappingRange {
pub start: u128,
}
}
- /// Returns `true` if zero is contained in the range.
- /// Equal to `range.contains(0)` but should be faster.
- #[inline(always)]
- pub fn contains_zero(&self) -> bool {
- self.start > self.end || self.start == 0
- }
-
/// Returns `self` with replaced `start`
#[inline(always)]
pub fn with_start(mut self, start: u128) -> Self {
self.end = end;
self
}
+
+ /// Returns `true` if `size` completely fills the range.
+ #[inline]
+ pub fn is_full_for(&self, size: Size) -> bool {
+ let max_value = size.unsigned_int_max();
+ debug_assert!(self.start <= max_value && self.end <= max_value);
+ self.start == (self.end.wrapping_add(1) & max_value)
+ }
}
impl fmt::Debug for WrappingRange {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(fmt, "{}..={}", self.start, self.end)?;
+ if self.start > self.end {
+ write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
+ } else {
+ write!(fmt, "{}..={}", self.start, self.end)?;
+ }
Ok(())
}
}
/// Information about one scalar component of a Rust type.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(HashStable_Generic)]
pub struct Scalar {
pub value: Primitive,
impl Scalar {
#[inline]
pub fn is_bool(&self) -> bool {
- matches!(self.value, Int(I8, false))
- && matches!(self.valid_range, WrappingRange { start: 0, end: 1 })
+ matches!(
+ self,
+ Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }
+ )
}
- /// Returns the valid range as a `x..y` range.
- ///
- /// If `x` and `y` are equal, the range is full, not empty.
- pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
- // For a (max) value of -1, max will be `-1 as usize`, which overflows.
- // However, that is fine here (it would still represent the full range),
- // i.e., if the range is everything.
- let bits = self.value.size(cx).bits();
- assert!(bits <= 128);
- let mask = !0u128 >> (128 - bits);
- let start = self.valid_range.start;
- let end = self.valid_range.end;
- assert_eq!(start, start & mask);
- assert_eq!(end, end & mask);
- start..(end.wrapping_add(1) & mask)
+ /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
+ #[inline]
+ pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
+ self.valid_range.is_full_for(self.value.size(cx))
}
}
/// Describes how values of the type are passed by target ABIs,
/// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum Abi {
Uninhabited,
Scalar(Scalar),
/// Returns `true` if this is a single signed integer scalar
#[inline]
pub fn is_signed(&self) -> bool {
- match *self {
- Abi::Scalar(ref scal) => match scal.value {
+ match self {
+ Abi::Scalar(scal) => match scal.value {
Primitive::Int(_, signed) => signed,
_ => false,
},
},
}
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct Niche {
pub offset: Size,
pub scalar: Scalar,
}
pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
- let Scalar { value, valid_range: ref v } = self.scalar;
- let bits = value.size(cx).bits();
- assert!(bits <= 128);
- let max_value = !0u128 >> (128 - bits);
+ let Scalar { value, valid_range: v } = self.scalar;
+ let size = value.size(cx);
+ assert!(size.bits() <= 128);
+ let max_value = size.unsigned_int_max();
// Find out how many values are outside the valid range.
let niche = v.end.wrapping_add(1)..v.start;
pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
assert!(count > 0);
- let Scalar { value, valid_range: v } = self.scalar.clone();
- let bits = value.size(cx).bits();
- assert!(bits <= 128);
- let max_value = !0u128 >> (128 - bits);
+ let Scalar { value, valid_range: v } = self.scalar;
+ let size = value.size(cx);
+ assert!(size.bits() <= 128);
+ let max_value = size.unsigned_int_max();
- if count > max_value {
+ let niche = v.end.wrapping_add(1)..v.start;
+ let available = niche.end.wrapping_sub(niche.start) & max_value;
+ if count > available {
return None;
}
- // Compute the range of invalid values being reserved.
- let start = v.end.wrapping_add(1) & max_value;
- let end = v.end.wrapping_add(count) & max_value;
-
- if v.contains(end) {
- return None;
+ // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
+ // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
+ // This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
+ // Having `None` in niche zero can enable some special optimizations.
+ //
+ // Bound selection criteria:
+ // 1. Select closest to zero given wrapping semantics.
+ // 2. Avoid moving past zero if possible.
+ //
+ // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
+ // If niche zero is already reserved, the selection of bounds are of little interest.
+ let move_start = |v: WrappingRange| {
+ let start = v.start.wrapping_sub(1) & max_value;
+ Some((start, Scalar { value, valid_range: v.with_start(start) }))
+ };
+ let move_end = |v: WrappingRange| {
+ let start = v.end.wrapping_add(1) & max_value;
+ let end = v.end.wrapping_add(count) & max_value;
+ Some((start, Scalar { value, valid_range: v.with_end(end) }))
+ };
+ let distance_end_zero = max_value - v.end;
+ if v.start > v.end {
+ // zero is unavailable because wrapping occurs
+ move_end(v)
+ } else if v.start <= distance_end_zero {
+ if count <= v.start {
+ move_start(v)
+ } else {
+ // moved past zero, use other bound
+ move_end(v)
+ }
+ } else {
+ let end = v.end.wrapping_add(count) & max_value;
+ let overshot_zero = (1..=v.end).contains(&end);
+ if overshot_zero {
+ // moved past zero, use other bound
+ move_start(v)
+ } else {
+ move_end(v)
+ }
}
-
- Some((start, Scalar { value, valid_range: v.with_end(end) }))
}
}
impl Layout {
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
- let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone());
+ let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.value.size(cx);
let align = scalar.value.align(cx);
Layout {
Ty: TyAbiInterface<'a, C>,
C: HasDataLayout,
{
- let scalar_allows_raw_init = move |s: &Scalar| -> bool {
+ let scalar_allows_raw_init = move |s: Scalar| -> bool {
if zero {
// The range must contain 0.
- s.valid_range.contains_zero()
+ s.valid_range.contains(0)
} else {
- // The range must include all values. `valid_range_exclusive` handles
- // the wrap-around using target arithmetic; with wrap-around then the full
- // range is one where `start == end`.
- let range = s.valid_range_exclusive(cx);
- range.start == range.end
+ // The range must include all values.
+ s.is_always_valid(cx)
}
};
// Check the ABI.
- let valid = match &self.abi {
+ let valid = match self.abi {
Abi::Uninhabited => false, // definitely UB
Abi::Scalar(s) => scalar_allows_raw_init(s),
Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
- Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
+ Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
Abi::Aggregate { .. } => true, // Fields are checked below.
};
if !valid {
--- /dev/null
+use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+/// A base target for Nintendo 3DS devices using the devkitARM toolchain.
+///
+/// Requires the devkitARM toolchain for 3DS targets on the host system.
+
+pub fn target() -> Target {
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(
+ LinkerFlavor::Gcc,
+ vec![
+ "-specs=3dsx.specs".to_string(),
+ "-mtune=mpcore".to_string(),
+ "-mfloat-abi=hard".to_string(),
+ "-mtp=soft".to_string(),
+ ],
+ );
+
+ Target {
+ llvm_target: "armv6k-none-eabihf".to_string(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+ arch: "arm".to_string(),
+
+ options: TargetOptions {
+ os: "horizon".to_string(),
+ env: "newlib".to_string(),
+ vendor: "nintendo".to_string(),
+ abi: "eabihf".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
+ cpu: "mpcore".to_string(),
+ executables: true,
+ families: vec!["unix".to_string()],
+ linker: Some("arm-none-eabi-gcc".to_string()),
+ relocation_model: RelocModel::Static,
+ features: "+vfp2".to_string(),
+ pre_link_args,
+ exe_suffix: ".elf".to_string(),
+ panic_strategy: PanicStrategy::Abort,
+ ..Default::default()
+ },
+ }
+}
--- /dev/null
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ let mut base = super::linux_base::opts();
+ base.max_atomic_width = Some(32);
+
+ Target {
+ llvm_target: "m68k-unknown-linux-gnu".to_string(),
+ pointer_width: 32,
+ data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".to_string(),
+ arch: "m68k".to_string(),
+ options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+ }
+}
("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
+ ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
("bpfeb-unknown-none", bpfeb_unknown_none),
("bpfel-unknown-none", bpfel_unknown_none),
+
+ ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
}
/// Warnings encountered when parsing the target `json`.
[package]
name = "rustc_trait_selection"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt};
+use rustc_data_structures::stable_set::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
- fn_sig_tys: &[Ty<'tcx>],
+ fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
);
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
- fn_sig_tys: &[Ty<'tcx>],
+ fn_sig_tys: FxHashSet<Ty<'tcx>>,
body_id: hir::HirId,
span: Span,
) {
debug!("add_implied_bounds()");
- for &ty in fn_sig_tys {
+ for ty in fn_sig_tys {
let ty = infcx.resolve_vars_if_possible(ty);
debug!("add_implied_bounds: ty = {}", ty);
let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
-use crate::infer::InferCtxtExt as _;
use crate::traits::{self, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
/// - `substs`, the substs used to instantiate this opaque type
/// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
/// `opaque_defn.concrete_ty`
- #[instrument(skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn infer_opaque_definition_from_instantiation(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
}
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
- #[instrument(skip(self))]
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder {
})
}
+ #[instrument(skip(self), level = "debug")]
fn fold_opaque_ty(
&mut self,
ty: Ty<'tcx>,
let tcx = infcx.tcx;
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
- debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
-
// Use the same type variable if the exact same opaque type appears more
// than once in the return type (e.g., if it's passed to a type alias).
if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
- debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
+ debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
return opaque_defn.concrete_ty;
}
+
let ty_var = infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: self.value_span,
});
- // Make sure that we are in fact defining the *entire* type
- // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
- // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
- debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
- debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
-
// Ideally, we'd get the span where *this specific `ty` came
// from*, but right now we just use the span from the overall
// value being folded. In simple cases like `-> impl Foo`,
infcx.opaque_types_vars.insert(ty_var, ty);
}
- debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
- self.compute_opaque_type_obligations(opaque_type_key);
-
- ty_var
- }
-
- fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) {
- let infcx = self.infcx;
- let tcx = infcx.tcx;
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+ debug!("generated new type inference var {:?}", ty_var.kind());
let item_bounds = tcx.explicit_item_bounds(def_id);
- debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
- let bounds: Vec<_> =
- item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
-
- let param_env = tcx.param_env(def_id);
- let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
- ObligationCause::misc(self.value_span, self.body_id),
- param_env,
- bounds,
- );
- self.obligations.extend(obligations);
- debug!("instantiate_opaque_types: bounds={:?}", bounds);
+ self.obligations.reserve(item_bounds.len());
+ for (predicate, _) in item_bounds {
+ debug!(?predicate);
+ let predicate = predicate.subst(tcx, substs);
+ debug!(?predicate);
+
+ // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
+ let predicate = predicate.fold_with(&mut BottomUpFolder {
+ tcx,
+ ty_op: |ty| match ty.kind() {
+ ty::Projection(projection_ty) => infcx.infer_projection(
+ self.param_env,
+ *projection_ty,
+ ObligationCause::misc(self.value_span, self.body_id),
+ 0,
+ &mut self.obligations,
+ ),
+ _ => ty,
+ },
+ lt_op: |lt| lt,
+ ct_op: |ct| ct,
+ });
+ debug!(?predicate);
- for predicate in &bounds {
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
if projection.ty.references_error() {
// No point on adding these obligations since there's a type error involved.
- return;
+ return tcx.ty_error();
}
}
- }
-
- self.obligations.reserve(bounds.len());
- for predicate in bounds {
// Change the predicate to refer to the type variable,
// which will be the concrete type instead of the opaque type.
// This also instantiates nested instances of `impl Trait`.
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
// Require that the predicate holds for the concrete type.
- debug!("instantiate_opaque_types: predicate={:?}", predicate);
+ debug!(?predicate);
self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
}
+
+ ty_var
}
}
.map(|obligation| FulfillmentError {
obligation: obligation.clone(),
code: FulfillmentErrorCode::CodeAmbiguity,
- points_at_arg_span: false,
// FIXME - does Chalk have a notation of 'root obligation'?
// This is just for diagnostics, so it's okay if this is wrong
root_obligation: obligation.clone(),
code: FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,
),
- points_at_arg_span: false,
// FIXME - does Chalk have a notation of 'root obligation'?
// This is just for diagnostics, so it's okay if this is wrong
root_obligation: obligation,
code: FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,
),
- points_at_arg_span: false,
// FIXME - does Chalk have a notation of 'root obligation'?
// This is just for diagnostics, so it's okay if this is wrong
root_obligation: obligation,
//! this is not as easy.
//!
//! In this case we try to build an abstract representation of this constant using
-//! `mir_abstract_const` which can then be checked for structural equality with other
+//! `thir_abstract_const` which can then be checked for structural equality with other
//! generic constants mentioned in the `caller_bounds` of the current environment.
use rustc_errors::ErrorReported;
use rustc_hir::def::DefKind;
-use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
-use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable};
+use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
+use rustc_middle::thir;
+use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_session::lint;
tcx: TyCtxt<'tcx>,
uv: ty::Unevaluated<'tcx, ()>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
- let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?;
+ let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) }))
}
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-struct WorkNode<'tcx> {
- node: Node<'tcx>,
- span: Span,
- used: bool,
-}
-
struct AbstractConstBuilder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'a mir::Body<'tcx>,
+ body_id: thir::ExprId,
+ body: &'a thir::Thir<'tcx>,
/// The current WIP node tree.
- ///
- /// We require all nodes to be used in the final abstract const,
- /// so we store this here. Note that we also consider nodes as used
- /// if they are mentioned in an assert, so some used nodes are never
- /// actually reachable by walking the [`AbstractConst`].
- nodes: IndexVec<NodeId, WorkNode<'tcx>>,
- locals: IndexVec<mir::Local, NodeId>,
- /// We only allow field accesses if they access
- /// the result of a checked operation.
- checked_op_locals: BitSet<mir::Local>,
+ nodes: IndexVec<NodeId, Node<'tcx>>,
}
impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
+ fn root_span(&self) -> Span {
+ self.body.exprs[self.body_id].span
+ }
+
fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
self.tcx
.sess
- .struct_span_err(self.body.span, "overly complex generic constant")
- .span_label(span.unwrap_or(self.body.span), msg)
+ .struct_span_err(self.root_span(), "overly complex generic constant")
+ .span_label(span.unwrap_or(self.root_span()), msg)
.help("consider moving this anonymous constant into a `const` function")
.emit();
fn new(
tcx: TyCtxt<'tcx>,
- body: &'a mir::Body<'tcx>,
+ (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId),
) -> Result<Option<AbstractConstBuilder<'a, 'tcx>>, ErrorReported> {
- let mut builder = AbstractConstBuilder {
- tcx,
- body,
- nodes: IndexVec::new(),
- locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls),
- checked_op_locals: BitSet::new_empty(body.local_decls.len()),
- };
-
- // We don't have to look at concrete constants, as we
- // can just evaluate them.
- if !body.is_polymorphic {
- return Ok(None);
- }
+ let builder = AbstractConstBuilder { tcx, body_id, body, nodes: IndexVec::new() };
- // We only allow consts without control flow, so
- // we check for cycles here which simplifies the
- // rest of this implementation.
- if body.is_cfg_cyclic() {
- builder.error(None, "cyclic anonymous constants are forbidden")?;
+ struct IsThirPolymorphic<'a, 'tcx> {
+ is_poly: bool,
+ thir: &'a thir::Thir<'tcx>,
+ tcx: TyCtxt<'tcx>,
}
- Ok(Some(builder))
- }
-
- fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId {
- // Mark used nodes.
- match node {
- Node::Leaf(_) => (),
- Node::Binop(_, lhs, rhs) => {
- self.nodes[lhs].used = true;
- self.nodes[rhs].used = true;
- }
- Node::UnaryOp(_, input) => {
- self.nodes[input].used = true;
- }
- Node::FunctionCall(func, nodes) => {
- self.nodes[func].used = true;
- nodes.iter().for_each(|&n| self.nodes[n].used = true);
+ use thir::visit;
+ impl<'a, 'tcx: 'a> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
+ fn thir(&self) -> &'a thir::Thir<'tcx> {
+ &self.thir
}
- Node::Cast(_, operand, _) => {
- self.nodes[operand].used = true;
+
+ fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) {
+ self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx);
+ if self.is_poly == false {
+ visit::walk_expr(self, expr)
+ }
}
- }
- // Nodes start as unused.
- self.nodes.push(WorkNode { node, span, used: false })
- }
+ fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
+ self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx);
+ if self.is_poly == false {
+ visit::walk_pat(self, pat);
+ }
+ }
- fn place_to_local(
- &mut self,
- span: Span,
- p: &mir::Place<'tcx>,
- ) -> Result<mir::Local, ErrorReported> {
- const ZERO_FIELD: mir::Field = mir::Field::from_usize(0);
- // Do not allow any projections.
- //
- // One exception are field accesses on the result of checked operations,
- // which are required to support things like `1 + 2`.
- if let Some(p) = p.as_local() {
- debug_assert!(!self.checked_op_locals.contains(p));
- Ok(p)
- } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
- // Only allow field accesses if the given local
- // contains the result of a checked operation.
- if self.checked_op_locals.contains(p.local) {
- Ok(p.local)
- } else {
- self.error(Some(span), "unsupported projection")?;
+ fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) {
+ self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx);
}
- } else {
- self.error(Some(span), "unsupported projection")?;
}
- }
- fn operand_to_node(
- &mut self,
- span: Span,
- op: &mir::Operand<'tcx>,
- ) -> Result<NodeId, ErrorReported> {
- debug!("operand_to_node: op={:?}", op);
- match op {
- mir::Operand::Copy(p) | mir::Operand::Move(p) => {
- let local = self.place_to_local(span, p)?;
- Ok(self.locals[local])
- }
- mir::Operand::Constant(ct) => match ct.literal {
- mir::ConstantKind::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)),
- mir::ConstantKind::Val(..) => self.error(Some(span), "unsupported constant")?,
- },
+ let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx };
+ visit::walk_expr(&mut is_poly_vis, &body[body_id]);
+ debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly);
+ if is_poly_vis.is_poly == false {
+ return Ok(None);
}
+
+ Ok(Some(builder))
}
/// We do not allow all binary operations in abstract consts, so filter disallowed ones.
}
}
- fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> {
- debug!("AbstractConstBuilder: stmt={:?}", stmt);
- let span = stmt.source_info.span;
- match stmt.kind {
- StatementKind::Assign(box (ref place, ref rvalue)) => {
- let local = self.place_to_local(span, place)?;
- match *rvalue {
- Rvalue::Use(ref operand) => {
- self.locals[local] = self.operand_to_node(span, operand)?;
- Ok(())
- }
- Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) if Self::check_binop(op) => {
- let lhs = self.operand_to_node(span, lhs)?;
- let rhs = self.operand_to_node(span, rhs)?;
- self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
- if op.is_checkable() {
- bug!("unexpected unchecked checkable binary operation");
- } else {
- Ok(())
- }
- }
- Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs))
- if Self::check_binop(op) =>
- {
- let lhs = self.operand_to_node(span, lhs)?;
- let rhs = self.operand_to_node(span, rhs)?;
- self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
- self.checked_op_locals.insert(local);
- Ok(())
- }
- Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
- let operand = self.operand_to_node(span, operand)?;
- self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
- Ok(())
- }
- Rvalue::Cast(cast_kind, ref operand, ty) => {
- let operand = self.operand_to_node(span, operand)?;
- self.locals[local] =
- self.add_node(Node::Cast(cast_kind, operand, ty), span);
- Ok(())
- }
- _ => self.error(Some(span), "unsupported rvalue")?,
- }
- }
- // These are not actually relevant for us here, so we can ignore them.
- StatementKind::AscribeUserType(..)
- | StatementKind::StorageLive(_)
- | StatementKind::StorageDead(_) => Ok(()),
- _ => self.error(Some(stmt.source_info.span), "unsupported statement")?,
- }
- }
-
- /// Possible return values:
- ///
- /// - `None`: unsupported terminator, stop building
- /// - `Some(None)`: supported terminator, finish building
- /// - `Some(Some(block))`: support terminator, build `block` next
- fn build_terminator(
- &mut self,
- terminator: &mir::Terminator<'tcx>,
- ) -> Result<Option<mir::BasicBlock>, ErrorReported> {
- debug!("AbstractConstBuilder: terminator={:?}", terminator);
- match terminator.kind {
- TerminatorKind::Goto { target } => Ok(Some(target)),
- TerminatorKind::Return => Ok(None),
- TerminatorKind::Call {
- ref func,
- ref args,
- destination: Some((ref place, target)),
- // We do not care about `cleanup` here. Any branch which
- // uses `cleanup` will fail const-eval and they therefore
- // do not matter when checking for const evaluatability.
- //
- // Do note that even if `panic::catch_unwind` is made const,
- // we still do not have to care about this, as we do not look
- // into functions.
- cleanup: _,
- // Do not allow overloaded operators for now,
- // we probably do want to allow this in the future.
- //
- // This is currently fairly irrelevant as it requires `const Trait`s.
- from_hir_call: true,
- fn_span,
- } => {
- let local = self.place_to_local(fn_span, place)?;
- let func = self.operand_to_node(fn_span, func)?;
- let args = self.tcx.arena.alloc_from_iter(
- args.iter()
- .map(|arg| self.operand_to_node(terminator.source_info.span, arg))
- .collect::<Result<Vec<NodeId>, _>>()?,
- );
- self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span);
- Ok(Some(target))
- }
- TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
- let p = match cond {
- mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
- mir::Operand::Constant(_) => bug!("unexpected assert"),
- };
-
- const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
- debug!("proj: {:?}", p.projection);
- if let Some(p) = p.as_local() {
- debug_assert!(!self.checked_op_locals.contains(p));
- // Mark locals directly used in asserts as used.
- //
- // This is needed because division does not use `CheckedBinop` but instead
- // adds an explicit assert for `divisor != 0`.
- self.nodes[self.locals[p]].used = true;
- return Ok(Some(target));
- } else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
- // Only allow asserts checking the result of a checked operation.
- if self.checked_op_locals.contains(p.local) {
- return Ok(Some(target));
- }
- }
-
- self.error(Some(terminator.source_info.span), "unsupported assertion")?;
- }
- _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?,
- }
- }
-
- /// Builds the abstract const by walking the mir from start to finish
- /// and bailing out when encountering an unsupported operation.
+ /// Builds the abstract const by walking the thir and bailing out when
+ /// encountering an unspported operation.
fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> {
- let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
- // We checked for a cyclic cfg above, so this should terminate.
- loop {
- debug!("AbstractConstBuilder: block={:?}", block);
- for stmt in block.statements.iter() {
- self.build_statement(stmt)?;
- }
+ debug!("Abstractconstbuilder::build: body={:?}", &*self.body);
+ self.recurse_build(self.body_id)?;
- if let Some(next) = self.build_terminator(block.terminator())? {
- block = &self.body.basic_blocks()[next];
- } else {
- break;
- }
- }
-
- assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
for n in self.nodes.iter() {
- if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node {
+ if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n {
// `AbstractConst`s should not contain any promoteds as they require references which
// are not allowed.
assert_eq!(ct.promoted, None);
}
}
- self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
- if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
- self.error(Some(unused.span), "dead code")?;
- }
+ Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter()))
+ }
- Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)))
+ fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorReported> {
+ use thir::ExprKind;
+ let node = &self.body.exprs[node];
+ debug!("recurse_build: node={:?}", node);
+ Ok(match &node.kind {
+ // I dont know if handling of these 3 is correct
+ &ExprKind::Scope { value, .. } => self.recurse_build(value)?,
+ &ExprKind::PlaceTypeAscription { source, .. } |
+ &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
+
+ // subtle: associated consts are literals this arm handles
+ // `<T as Trait>::ASSOC` as well as `12`
+ &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
+
+ ExprKind::Call { fun, args, .. } => {
+ let fun = self.recurse_build(*fun)?;
+
+ let mut new_args = Vec::<NodeId>::with_capacity(args.len());
+ for &id in args.iter() {
+ new_args.push(self.recurse_build(id)?);
+ }
+ let new_args = self.tcx.arena.alloc_slice(&new_args);
+ self.nodes.push(Node::FunctionCall(fun, new_args))
+ },
+ &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
+ let lhs = self.recurse_build(lhs)?;
+ let rhs = self.recurse_build(rhs)?;
+ self.nodes.push(Node::Binop(op, lhs, rhs))
+ }
+ &ExprKind::Unary { op, arg } if Self::check_unop(op) => {
+ let arg = self.recurse_build(arg)?;
+ self.nodes.push(Node::UnaryOp(op, arg))
+ },
+ // This is necessary so that the following compiles:
+ //
+ // ```
+ // fn foo<const N: usize>(a: [(); N + 1]) {
+ // bar::<{ N + 1 }>();
+ // }
+ // ```
+ ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
+ // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
+ // "coercion cast" i.e. using a coercion or is a no-op.
+ // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
+ &ExprKind::Use { source } => {
+ let arg = self.recurse_build(source)?;
+ self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
+ },
+ &ExprKind::Cast { source } => {
+ let arg = self.recurse_build(source)?;
+ self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
+ },
+
+ // FIXME(generic_const_exprs): We may want to support these.
+ ExprKind::AddressOf { .. }
+ | ExprKind::Borrow { .. }
+ | ExprKind::Deref { .. }
+ | ExprKind::Repeat { .. }
+ | ExprKind::Array { .. }
+ | ExprKind::Block { .. }
+ | ExprKind::NeverToAny { .. }
+ | ExprKind::Tuple { .. }
+ | ExprKind::Index { .. }
+ | ExprKind::Field { .. }
+ | ExprKind::ConstBlock { .. }
+ | ExprKind::Adt(_) => self.error(
+ Some(node.span),
+ "unsupported operation in generic constant, this may be supported in the future",
+ )?,
+
+ ExprKind::Match { .. }
+ // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
+ | ExprKind::VarRef { .. }
+ | ExprKind::UpvarRef { .. }
+ | ExprKind::Closure { .. }
+ | ExprKind::Let { .. } // let expressions imply control flow
+ | ExprKind::Loop { .. }
+ | ExprKind::Assign { .. }
+ | ExprKind::StaticRef { .. }
+ | ExprKind::LogicalOp { .. }
+ // we handle valid unary/binary ops above
+ | ExprKind::Unary { .. }
+ | ExprKind::Binary { .. }
+ | ExprKind::Break { .. }
+ | ExprKind::Continue { .. }
+ | ExprKind::If { .. }
+ | ExprKind::Pointer { .. } // dont know if this is correct
+ | ExprKind::ThreadLocalRef(_)
+ | ExprKind::LlvmInlineAsm { .. }
+ | ExprKind::Return { .. }
+ | ExprKind::Box { .. } // allocations not allowed in constants
+ | ExprKind::AssignOp { .. }
+ | ExprKind::InlineAsm { .. }
+ | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
+ })
}
}
/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
-pub(super) fn mir_abstract_const<'tcx>(
+pub(super) fn thir_abstract_const<'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
if tcx.features().generic_const_exprs {
match tcx.def_kind(def.did) {
// FIXME(generic_const_exprs): We currently only do this for anonymous constants,
DefKind::AnonConst => (),
_ => return Ok(None),
}
- let body = tcx.mir_const(def).borrow();
- AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose()
+
+ let body = tcx.thir_body(def);
+ if body.0.borrow().exprs.is_empty() {
+ // type error in constant, there is no thir
+ return Err(ErrorReported);
+ }
+
+ AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
+ .map(AbstractConstBuilder::build)
+ .transpose()
} else {
Ok(None)
}
&& iter::zip(a_args, b_args)
.all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
}
- (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
- if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
+ (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty))
+ if (a_ty == b_ty) && (a_kind == b_kind) =>
{
try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
}
- _ => false,
+ // use this over `_ => false` to make adding variants to `Node` less error prone
+ (Node::Cast(..), _)
+ | (Node::FunctionCall(..), _)
+ | (Node::UnaryOp(..), _)
+ | (Node::Binop(..), _)
+ | (Node::Leaf(..), _) => false,
}
}
use rustc_hir::GenericParam;
use rustc_hir::Item;
use rustc_hir::Node;
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::{
root_obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>,
fallback_has_occurred: bool,
- points_at_arg: bool,
);
/// Given some node representing a fn-like thing in the HIR map,
root_obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>,
fallback_has_occurred: bool,
- points_at_arg: bool,
) {
let tcx = self.tcx;
let mut span = obligation.cause.span;
if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
root_obligation.cause.code.peel_derives()
{
- if let Some(cause) = self.tcx.diagnostic_hir_wf_check((
- tcx.erase_regions(obligation.predicate),
- wf_loc.clone(),
- )) {
+ if let Some(cause) = self
+ .tcx
+ .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
+ {
obligation.cause = cause;
span = obligation.cause.span;
}
&obligation,
&mut err,
&trait_ref,
- points_at_arg,
have_alt_message,
) {
self.note_obligation_cause(&mut err, &obligation);
err.span_label(enclosing_scope_span, s.as_str());
}
- self.suggest_dereferences(&obligation, &mut err, trait_ref, points_at_arg);
- self.suggest_fn_call(&obligation, &mut err, trait_ref, points_at_arg);
+ self.suggest_dereferences(&obligation, &mut err, trait_ref);
+ self.suggest_fn_call(&obligation, &mut err, trait_ref);
self.suggest_remove_reference(&obligation, &mut err, trait_ref);
self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref);
self.note_version_mismatch(&mut err, &trait_ref);
// Changing mutability doesn't make a difference to whether we have
// an `Unsize` impl (Fixes ICE in #71036)
if !is_unsize {
- self.suggest_change_mut(
- &obligation,
- &mut err,
- trait_ref,
- points_at_arg,
- );
+ self.suggest_change_mut(&obligation, &mut err, trait_ref);
}
// If this error is due to `!: Trait` not implemented but `(): Trait` is
};
let found_did = match *found_trait_ty.kind() {
- ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+ ty::Closure(did, _)
+ | ty::Foreign(did)
+ | ty::FnDef(did, _)
+ | ty::Generator(did, ..) => Some(did),
ty::Adt(def, _) => Some(def.did),
_ => None,
};
&error.root_obligation,
selection_error,
fallback_has_occurred,
- error.points_at_arg_span,
);
}
FulfillmentErrorCode::CodeProjectionError(ref e) => {
flags.push((sym::from_method, Some(method.to_string())));
}
}
- if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
- flags.push((sym::parent_trait, Some(t)));
- }
if let Some(k) = obligation.cause.span.desugaring_kind() {
flags.push((sym::from_desugaring, None));
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_data_structures::sync::Lrc;
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::{TypeAndMut, TypeckResults};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP};
use rustc_target::spec::abi;
use std::fmt;
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
- points_at_arg: bool,
);
fn get_closure_name(
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
);
fn suggest_add_reference_to_arg(
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
has_custom_message: bool,
) -> bool;
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
);
fn suggest_semicolon_removal(
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
- points_at_arg: bool,
) {
// It only make sense when suggesting dereferences for arguments
- if !points_at_arg {
+ let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+ &obligation.cause.code
+ {
+ parent_code.clone()
+ } else {
return;
- }
+ };
let param_env = obligation.param_env;
let body_id = obligation.cause.body_id;
let span = obligation.cause.span;
- let real_trait_ref = match &obligation.cause.code {
+ let real_trait_ref = match &*code {
ObligationCauseCode::ImplDerivedObligation(cause)
| ObligationCauseCode::DerivedObligation(cause)
| ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
) {
let self_ty = match trait_ref.self_ty().no_bound_vars() {
None => return,
}
_ => return,
};
- if points_at_arg {
+ if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) {
// When the obligation error has been ensured to have been caused by
// an argument, the `obligation.cause.span` points at the expression
- // of the argument, so we can provide a suggestion. This is signaled
- // by `points_at_arg`. Otherwise, we give a more general note.
+ // of the argument, so we can provide a suggestion. Otherwise, we give
+ // a more general note.
err.span_suggestion_verbose(
obligation.cause.span.shrink_to_hi(),
&msg,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
has_custom_message: bool,
) -> bool {
- if !points_at_arg {
+ let span = obligation.cause.span;
+
+ let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+ &obligation.cause.code
+ {
+ parent_code.clone()
+ } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) =
+ span.ctxt().outer_expn_data().kind
+ {
+ Lrc::new(obligation.cause.code.clone())
+ } else {
return false;
- }
+ };
// List of traits for which it would be nonsensical to suggest borrowing.
// For instance, immutable references are always Copy, so suggesting to
never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
- let span = obligation.cause.span;
let param_env = obligation.param_env;
let trait_ref = trait_ref.skip_binder();
);
// This if is to prevent a special edge-case
- if !span.from_expansion() {
+ if matches!(
+ span.ctxt().outer_expn_data().kind,
+ ExpnKind::Root
+ | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
+ ) {
// We don't want a borrowing suggestion on the fields in structs,
// ```
// struct Foo {
return false;
};
- if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+ if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
let expected_trait_ref = obligation.parent_trait_ref.skip_binder();
let new_imm_trait_ref =
ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]);
}
} else if let ObligationCauseCode::BindingObligation(_, _)
- | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code
+ | ObligationCauseCode::ItemObligation(_) = &*code
{
if try_borrowing(
ty::TraitRef::new(trait_ref.def_id, imm_substs),
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
- points_at_arg: bool,
) {
+ let points_at_arg = matches!(
+ obligation.cause.code,
+ ObligationCauseCode::FunctionArgumentObligation { .. },
+ );
+
let span = obligation.cause.span;
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let refs_number =
trait_ref: ty::PolyTraitRef<'tcx>,
) -> String {
let inputs = trait_ref.skip_binder().substs.type_at(1);
- 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::from_u32(0))),
- false,
- hir::Unsafety::Normal,
- abi::Abi::Rust,
- )
- } else {
- tcx.mk_fn_sig(
+ let sig = match inputs.kind() {
+ ty::Tuple(inputs)
+ if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() =>
+ {
+ tcx.mk_fn_sig(
+ inputs.iter().map(|k| k.expect_ty()),
+ tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
+ false,
+ hir::Unsafety::Normal,
+ abi::Abi::Rust,
+ )
+ }
+ _ => tcx.mk_fn_sig(
std::iter::once(inputs),
tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
false,
hir::Unsafety::Normal,
abi::Abi::Rust,
- )
+ ),
};
trait_ref.rebind(sig).to_string()
}
- let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+ let argument_kind = match expected_ref.skip_binder().substs.type_at(0) {
+ t if t.is_closure() => "closure",
+ t if t.is_generator() => "generator",
+ _ => "function",
+ };
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0631,
"type mismatch in {} arguments",
- if argument_is_closure { "closure" } else { "function" }
+ argument_kind
);
let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found));
)
});
}
+ ObligationCauseCode::FunctionArgumentObligation {
+ arg_hir_id,
+ call_hir_id,
+ ref parent_code,
+ } => {
+ let hir = self.tcx.hir();
+ if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
+ hir.find(arg_hir_id)
+ {
+ let in_progress_typeck_results =
+ self.in_progress_typeck_results.map(|t| t.borrow());
+ let parent_id = hir.local_def_id(hir.get_parent_item(arg_hir_id));
+ let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results {
+ Some(t) if t.hir_owner == parent_id => t,
+ _ => self.tcx.typeck(parent_id),
+ };
+ let ty = typeck_results.expr_ty_adjusted(expr);
+ let span = expr.peel_blocks().span;
+ if Some(span) != err.span.primary_span() {
+ err.span_label(
+ span,
+ &if ty.references_error() {
+ String::new()
+ } else {
+ format!("this tail expression is of type `{:?}`", ty)
+ },
+ );
+ }
+ }
+ if let Some(Node::Expr(hir::Expr {
+ kind:
+ hir::ExprKind::Call(hir::Expr { span, .. }, _)
+ | hir::ExprKind::MethodCall(_, span, ..),
+ ..
+ })) = hir.find(call_hir_id)
+ {
+ if Some(*span) != err.span.primary_span() {
+ err.span_label(*span, "required by a bound introduced by this call");
+ }
+ }
+ ensure_sufficient_stack(|| {
+ self.note_obligation_cause_code(
+ err,
+ predicate,
+ &parent_code,
+ obligated_types,
+ seen_requirements,
+ )
+ });
+ }
ObligationCauseCode::CompareImplMethodObligation {
item_name,
trait_item_def_id,
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::ToPredicate;
vtable_entries,
vtable_trait_upcasting_coercion_new_vptr_slot,
subst_and_check_impossible_predicates,
- mir_abstract_const: |tcx, def_id| {
+ thir_abstract_const: |tcx, def_id| {
let def_id = def_id.expect_local();
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.mir_abstract_const_of_const_arg(def)
+ tcx.thir_abstract_const_of_const_arg(def)
} else {
- const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
+ const_evaluatable::thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
}
},
- mir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
- const_evaluatable::mir_abstract_const(
+ thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
+ const_evaluatable::thir_abstract_const(
tcx,
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
)
let param_env = tcx.param_env(method.def_id);
- let abi_of_ty = |ty: Ty<'tcx>| -> Option<&Abi> {
+ let abi_of_ty = |ty: Ty<'tcx>| -> Option<Abi> {
match tcx.layout_of(param_env.and(ty)) {
- Ok(layout) => Some(&layout.abi),
+ Ok(layout) => Some(layout.abi),
Err(err) => {
// #78372
tcx.sess.delay_span_bug(
//
// This shouldn't really matter though as we can't really use any
// constants which are not considered const evaluatable.
- use rustc_middle::mir::abstract_const::Node;
+ use rustc_middle::thir::abstract_const::Node;
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
Node::Leaf(leaf) => {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderRegion { universe, name: br.kind };
- self.mapped_regions.insert(p.clone(), br);
+ self.mapped_regions.insert(p, br);
self.infcx.tcx.mk_region(ty::RePlaceholder(p))
}
_ => r,
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderType { universe, name: bound_ty.var };
- self.mapped_types.insert(p.clone(), bound_ty);
+ self.mapped_types.insert(p, bound_ty);
self.infcx.tcx.mk_ty(ty::Placeholder(p))
}
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
universe,
name: ty::BoundConst { var: bound_const, ty },
};
- self.mapped_consts.insert(p.clone(), bound_const);
+ self.mapped_consts.insert(p, bound_const);
self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
}
_ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
// and a deferred predicate to resolve this when more type
// information is available.
- let tcx = selcx.infcx().tcx;
- let def_id = projection_ty.item_def_id;
- let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::NormalizeProjectionType,
- span: tcx.def_span(def_id),
- });
- let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
- let obligation =
- Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx));
- obligations.push(obligation);
- ty_var
+ selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations)
})
}
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Result<Option<Ty<'tcx>>, InProgress> {
let infcx = selcx.infcx();
+ // Don't use the projection cache in intercrate mode -
+ // the `infcx` may be re-used between intercrate in non-intercrate
+ // mode, which could lead to using incorrect cache results.
+ let use_cache = !selcx.is_intercrate();
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
let cache_key = ProjectionCacheKey::new(projection_ty);
// bounds. It might be the case that we want two distinct caches,
// or else another kind of cache entry.
- let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
+ let cache_result = if use_cache {
+ infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
+ } else {
+ Ok(())
+ };
match cache_result {
Ok(()) => debug!("no cache"),
Err(ProjectionCacheEntry::Ambiguous) => {
// should ensure that, unless this happens within a snapshot that's
// rolled back, fulfillment or evaluation will notice the cycle.
- infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+ }
return Err(InProgress);
}
Err(ProjectionCacheEntry::Recur) => {
.map_or(false, |res| res.must_apply_considering_regions())
});
- infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ }
obligations.extend(result.obligations);
Ok(Some(result.value))
}
Ok(ProjectedTy::NoProgress(projected_ty)) => {
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
let result = Normalized { value: projected_ty, obligations: vec![] };
- infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ }
// No need to extend `obligations`.
Ok(Some(result.value))
}
Err(ProjectionTyError::TooManyCandidates) => {
debug!("opt_normalize_projection_type: too many candidates");
- infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+ }
Ok(None)
}
Err(ProjectionTyError::TraitSelectionError(_)) => {
// Trait`, which when processed will cause the error to be
// reported later
- infcx.inner.borrow_mut().projection_cache().error(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().error(cache_key);
+ }
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
obligations.extend(result.obligations);
Ok(Some(result.value))
}
super::ImplSource::AutoImpl(..)
| super::ImplSource::Builtin(..)
- | super::ImplSource::TraitUpcasting(_) => {
+ | super::ImplSource::TraitUpcasting(_)
+ | super::ImplSource::ConstDrop(_) => {
// These traits have no associated types.
selcx.tcx().sess.delay_span_bug(
obligation.cause.span,
| super::ImplSource::Param(..)
| super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_)
- | super::ImplSource::TraitAlias(..) => {
+ | super::ImplSource::TraitAlias(..)
+ | super::ImplSource::ConstDrop(_) => {
// we don't create Select candidates with this kind of resolution
span_bug!(
obligation.cause.span,
use rustc_hir as hir;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_target::spec::abi::Abi;
use crate::traits::coherence::Conflict;
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
} else if lang_items.unsize_trait() == Some(def_id) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+ } else if lang_items.drop_trait() == Some(def_id)
+ && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
+ {
+ if self.is_in_const_context {
+ self.assemble_const_drop_candidates(obligation, &mut candidates)?;
+ } else {
+ debug!("passing ~const Drop bound; in non-const context");
+ // `~const Drop` when we are not in a const context has no effect.
+ candidates.vec.push(ConstDropCandidate)
+ }
} else {
if lang_items.clone_trait() == Some(def_id) {
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
}
}
}
+
+ fn assemble_const_drop_candidates(
+ &mut self,
+ obligation: &TraitObligation<'tcx>,
+ candidates: &mut SelectionCandidateSet<'tcx>,
+ ) -> Result<(), SelectionError<'tcx>> {
+ let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
+
+ while let Some((ty, depth)) = stack.pop() {
+ let mut noreturn = false;
+
+ self.check_recursion_depth(depth, obligation)?;
+ let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+ let mut copy_obligation =
+ obligation.with(obligation.predicate.rebind(ty::TraitPredicate {
+ trait_ref: ty::TraitRef {
+ def_id: self.tcx().require_lang_item(hir::LangItem::Copy, None),
+ substs: self.tcx().mk_substs_trait(ty, &[]),
+ },
+ constness: ty::BoundConstness::NotConst,
+ }));
+ copy_obligation.recursion_depth = depth + 1;
+ self.assemble_candidates_from_impls(©_obligation, &mut copy_candidates);
+ let copy_conditions = self.copy_clone_conditions(©_obligation);
+ self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
+ if !copy_candidates.vec.is_empty() {
+ noreturn = true;
+ }
+ debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
+
+ match ty.kind() {
+ ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Infer(ty::IntVar(_))
+ | ty::Infer(ty::FloatVar(_))
+ | ty::FnPtr(_)
+ | ty::Never
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::RawPtr(_)
+ | ty::Bool
+ | ty::Char
+ | ty::Str
+ | ty::Foreign(_) => {} // Do nothing. These types satisfy `const Drop`.
+
+ ty::Adt(def, subst) => {
+ let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+ self.assemble_candidates_from_impls(
+ &obligation.with(obligation.predicate.map_bound(|mut pred| {
+ pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]);
+ pred
+ })),
+ &mut set,
+ );
+ stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
+
+ debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt");
+ if set.vec.into_iter().any(|candidate| {
+ if let SelectionCandidate::ImplCandidate(did) = candidate {
+ matches!(self.tcx().impl_constness(did), hir::Constness::NotConst)
+ } else {
+ false
+ }
+ }) {
+ if !noreturn {
+ // has non-const Drop
+ return Ok(());
+ }
+ debug!("not returning");
+ }
+ }
+
+ ty::Array(ty, _) => stack.push((ty, depth + 1)),
+
+ ty::Tuple(_) => stack.extend(ty.tuple_fields().map(|t| (t, depth + 1))),
+
+ ty::Closure(_, substs) => {
+ stack.extend(substs.as_closure().upvar_tys().map(|t| (t, depth + 1)))
+ }
+
+ ty::Generator(_, substs, _) => {
+ let substs = substs.as_generator();
+ stack.extend(substs.upvar_tys().map(|t| (t, depth + 1)));
+ stack.push((substs.witness(), depth + 1));
+ }
+
+ ty::GeneratorWitness(tys) => stack.extend(
+ self.tcx().erase_late_bound_regions(*tys).iter().map(|t| (t, depth + 1)),
+ ),
+
+ ty::Slice(ty) => stack.push((ty, depth + 1)),
+
+ ty::Opaque(..)
+ | ty::Dynamic(..)
+ | ty::Error(_)
+ | ty::Bound(..)
+ | ty::Infer(_)
+ | ty::Placeholder(_)
+ | ty::Projection(..)
+ | ty::Param(..) => {
+ if !noreturn {
+ return Ok(());
+ }
+ debug!("not returning");
+ }
+ }
+ debug!(?stack, "assemble_const_drop_candidates - in loop");
+ }
+ // all types have passed.
+ candidates.vec.push(ConstDropCandidate);
+
+ Ok(())
+ }
}
use crate::traits::VtblSegment;
use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
use crate::traits::{
- ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
+ ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData,
ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
Ok(ImplSource::TraitUpcasting(data))
}
+
+ ConstDropCandidate => Ok(ImplSource::ConstDrop(ImplSourceConstDropData)),
}
}
use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
use super::wf;
use super::DerivedObligationCause;
+use super::Normalized;
use super::Obligation;
use super::ObligationCauseCode;
use super::Selection;
use super::SelectionResult;
use super::TraitQueryMode;
-use super::{Normalized, ProjectionCacheKey};
use super::{ObligationCause, PredicateObligation, TraitObligation};
use super::{Overflow, SelectionError, Unimplemented};
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
use crate::traits::error_reporting::InferCtxtExt;
-use crate::traits::project::ProjectionCacheKeyExt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::TypeRelation;
self.infcx.tcx
}
+ pub fn is_intercrate(&self) -> bool {
+ self.intercrate
+ }
+
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
match pred.constness {
match project::poly_project_and_unify_type(self, &project_obligation) {
Ok(Ok(Some(mut subobligations))) => {
self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
- let result = self
- .evaluate_predicates_recursively(previous_stack, subobligations);
- if let Some(key) =
- ProjectionCacheKey::from_poly_projection_predicate(self, data)
- {
- self.infcx.inner.borrow_mut().projection_cache().complete(key);
- }
- result
+ self.evaluate_predicates_recursively(previous_stack, subobligations)
}
Ok(Ok(None)) => Ok(EvaluatedToAmbig),
Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur),
param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
) -> Option<EvaluationResult> {
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return None;
+ }
+
let tcx = self.tcx();
if self.can_use_global_caches(param_env) {
if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_ref), tcx) {
return;
}
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return;
+ }
+
if self.can_use_global_caches(param_env) {
if !trait_ref.needs_infer() {
debug!(?trait_ref, ?result, "insert_evaluation_cache global");
it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
}
- /// Checks that the recursion limit has not been exceeded.
- ///
- /// The weird return type of this function allows it to be used with the `try` (`?`)
- /// operator within certain functions.
- fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+ fn check_recursion_depth<T: Display + TypeFoldable<'tcx>>(
&self,
- obligation: &Obligation<'tcx, T>,
- error_obligation: &Obligation<'tcx, V>,
+ depth: usize,
+ error_obligation: &Obligation<'tcx, T>,
) -> Result<(), OverflowError> {
- if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
+ if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
match self.query_mode {
TraitQueryMode::Standard => {
- self.infcx().report_overflow_error(error_obligation, true);
+ self.infcx.report_overflow_error(error_obligation, true);
}
TraitQueryMode::Canonical => {
return Err(OverflowError);
Ok(())
}
+ /// Checks that the recursion limit has not been exceeded.
+ ///
+ /// The weird return type of this function allows it to be used with the `try` (`?`)
+ /// operator within certain functions.
+ #[inline(always)]
+ fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+ &self,
+ obligation: &Obligation<'tcx, T>,
+ error_obligation: &Obligation<'tcx, V>,
+ ) -> Result<(), OverflowError> {
+ self.check_recursion_depth(obligation.recursion_depth, error_obligation)
+ }
+
fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
where
OP: FnOnce(&mut Self) -> R,
let tcx = self.tcx();
// Respect const trait obligations
if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
- if Some(obligation.predicate.skip_binder().trait_ref.def_id)
- != tcx.lang_items().sized_trait()
- // const Sized bounds are skipped
- {
- match candidate {
- // const impl
- ImplCandidate(def_id)
- if tcx.impl_constness(def_id) == hir::Constness::Const => {}
- // const param
- ParamCandidate(ty::ConstnessAnd {
- constness: ty::BoundConstness::ConstIfConst,
- ..
- }) => {}
- // auto trait impl
- AutoImplCandidate(..) => {}
- // generator, this will raise error in other places
- // or ignore error with const_async_blocks feature
- GeneratorCandidate => {}
- _ => {
- // reject all other types of candidates
- return Err(Unimplemented);
- }
+ match candidate {
+ // const impl
+ ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {}
+ // const param
+ ParamCandidate(ty::ConstnessAnd {
+ constness: ty::BoundConstness::ConstIfConst,
+ ..
+ }) => {}
+ // auto trait impl
+ AutoImplCandidate(..) => {}
+ // generator, this will raise error in other places
+ // or ignore error with const_async_blocks feature
+ GeneratorCandidate => {}
+ ConstDropCandidate => {}
+ _ => {
+ // reject all other types of candidates
+ return Err(Unimplemented);
}
}
}
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return None;
+ }
let tcx = self.tcx();
let pred = &cache_fresh_trait_pred.skip_binder();
let trait_ref = pred.trait_ref;
&self,
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) -> bool {
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return false;
+ }
match result {
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
_ => true,
(
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
- | PointeeCandidate,
+ | PointeeCandidate
+ | ConstDropCandidate,
_,
) => true,
(
_,
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
- | PointeeCandidate,
+ | PointeeCandidate
+ | ConstDropCandidate,
) => false,
(ParamCandidate(other), ParamCandidate(victim)) => {
- let value_same_except_bound_vars = other.value.skip_binder()
+ let same_except_bound_vars = other.value.skip_binder()
== victim.value.skip_binder()
+ && other.constness == victim.constness
&& !other.value.skip_binder().has_escaping_bound_vars();
- if value_same_except_bound_vars {
+ if same_except_bound_vars {
// See issue #84398. In short, we can generate multiple ParamCandidates which are
// the same except for unused bound vars. Just pick the one with the fewest bound vars
// or the current one if tied (they should both evaluate to the same answer). This is
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id),
+ ObligationCauseCode::MatchImpl(obligation.cause.clone(), impl_def_id),
);
let InferOk { obligations, .. } = self
"get_provisional = {:#?}",
self.map.borrow().get(&fresh_trait_ref),
);
- Some(self.map.borrow().get(&fresh_trait_ref)?.clone())
+ Some(*self.map.borrow().get(&fresh_trait_ref)?)
}
/// Insert a provisional result into the cache. The result came
let self_ty = trait_ref.self_ty();
// FIXME: should postpone string formatting until we decide to actually emit.
- with_no_trimmed_paths(|| OverlapError {
- with_impl: possible_sibling,
- trait_desc: trait_ref.print_only_trait_path().to_string(),
- // Only report the `Self` type if it has at least
- // some outer concrete shell; otherwise, it's
- // not adding much information.
- self_desc: if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- },
- intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
- involves_placeholder: overlap.involves_placeholder,
+ with_no_trimmed_paths(|| {
+ OverlapError {
+ with_impl: possible_sibling,
+ trait_desc: trait_ref.print_only_trait_path().to_string(),
+ // Only report the `Self` type if it has at least
+ // some outer concrete shell; otherwise, it's
+ // not adding much information.
+ self_desc: if self_ty.has_concrete_skeleton() {
+ Some(self_ty.to_string())
+ } else {
+ None
+ },
+ intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
+ involves_placeholder: overlap.involves_placeholder,
+ }
})
};
_ => return,
};
let fix_span =
- |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind {
+ |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
_ => impl_item_ref.span,
};
[package]
name = "rustc_traits"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
[package]
name = "rustc_ty_utils"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
| traits::ImplSource::TraitAlias(..)
| traits::ImplSource::DiscriminantKind(..)
| traits::ImplSource::Pointee(..)
- | traits::ImplSource::TraitUpcasting(_) => None,
+ | traits::ImplSource::TraitUpcasting(_)
+ | traits::ImplSource::ConstDrop(_) => None,
})
}
type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
- let adt_fields =
+ let adt_components =
move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
+
// If we don't know a type doesn't need drop, for example if it's a type
// parameter without a `Copy` bound, then we conservatively return that it
// needs drop.
- let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
+ let res =
+ NeedsDropTypes::new(tcx, query.param_env, query.value, adt_components).next().is_some();
+
debug!("needs_drop_raw({:?}) = {:?}", query, res);
res
}
fn associated_item_from_impl_item_ref(
tcx: TyCtxt<'_>,
parent_def_id: LocalDefId,
- impl_item_ref: &hir::ImplItemRef<'_>,
+ impl_item_ref: &hir::ImplItemRef,
) -> ty::AssocItem {
let def_id = impl_item_ref.id.def_id;
let (kind, has_self) = match impl_item_ref.kind {
[package]
name = "rustc_type_ir"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_typeck"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
constraint=constraint,
));
} else {
- err.span_suggestion(
- span,
+ err.span_suggestion_verbose(
+ span.with_hi(assoc_name.span.lo()),
"use fully qualified syntax to disambiguate",
format!(
- "<{} as {}>::{}",
+ "<{} as {}>::",
ty_param_name(),
bound.print_only_trait_path(),
- assoc_name,
),
Applicability::MaybeIncorrect,
);
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
// Our own parameters are the resolved lifetimes.
- match param.kind {
- GenericParamDefKind::Lifetime
- if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] =>
- {
+ if let GenericParamDefKind::Lifetime = param.kind {
+ if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
self.ast_region_to_region(lifetime, None).into()
+ } else {
+ bug!()
}
- _ => bug!(),
+ } else {
+ bug!()
}
} else {
match param.kind {
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
- let original_callee_ty = self.check_expr(callee_expr);
+ let original_callee_ty = match &callee_expr.kind {
+ hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
+ .check_expr_with_expectation_and_args(
+ callee_expr,
+ Expectation::NoExpectation,
+ arg_exprs,
+ ),
+ _ => self.check_expr(callee_expr),
+ };
+
let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
),
self.cast_ty,
AllowTwoPhase::No,
+ None,
)
.is_ok()
{
),
self.cast_ty,
AllowTwoPhase::No,
+ None,
)
.is_ok()
{
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
self.cast_ty,
AllowTwoPhase::No,
+ None,
)
.is_ok()
{
),
self.cast_ty,
AllowTwoPhase::No,
+ None,
)
.is_ok()
{
self.expr_ty,
fcx.tcx.mk_fn_ptr(f),
AllowTwoPhase::No,
+ None,
);
if let Err(TypeError::IntrinsicCast) = res {
return Err(CastError::IllegalCast);
// Coerce to a raw pointer so that we generate AddressOf in MIR.
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
- fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
+ fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
.unwrap_or_else(|_| {
bug!(
"could not cast from reference to array to pointer to array ({:?} to {:?})",
}
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> {
- match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
+ match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
Ok(_) => Ok(()),
Err(err) => Err(err),
}
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
} else {
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
- fcx.check_return_expr(&body.value);
+ fcx.check_return_expr(&body.value, false);
}
fcx.in_tail_expr = false;
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, hir_id);
- fcx.regionck_item(hir_id, span, &[]);
+ fcx.regionck_item(hir_id, span, FxHashSet::default());
});
}
full_impl_span: Span,
impl_id: LocalDefId,
impl_trait_ref: ty::TraitRef<'tcx>,
- impl_item_refs: &[hir::ImplItemRef<'_>],
+ impl_item_refs: &[hir::ImplItemRef],
) {
// If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
// Object safety violations or miscellaneous.
Err(err) => {
- self.report_selection_error(
- obligation.clone(),
- &obligation,
- &err,
- false,
- false,
- );
+ self.report_selection_error(obligation.clone(), &obligation, &err, false);
// Treat this like an obligation and follow through
// with the unsizing - the lack of a coercion should
// be silent, as it causes a type mismatch later.
expr_ty: Ty<'tcx>,
target: Ty<'tcx>,
allow_two_phase: AllowTwoPhase,
+ cause: Option<ObligationCause<'tcx>>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
- let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
+ let cause =
+ cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
let coerce = Coerce::new(self, cause, allow_two_phase);
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
exprs.len()
);
+ // The following check fixes #88097, where the compiler erroneously
+ // attempted to coerce a closure type to itself via a function pointer.
+ if prev_ty == new_ty {
+ return Ok(prev_ty);
+ }
+
// Special-case that coercion alone cannot handle:
// Function items or non-capturing closures of differing IDs or InternalSubsts.
let (a_sig, b_sig) = {
// Special-case the first expression we are coercing.
// To be honest, I'm not entirely sure why we do this.
// We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
- fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No)
+ fcx.try_coerce(
+ expression,
+ expression_ty,
+ self.expected_ty,
+ AllowTwoPhase::No,
+ Some(cause.clone()),
+ )
} else {
match self.expressions {
Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub(
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
// Compute placeholder form of impl and trait method tys.
let tcx = infcx.tcx;
- let mut wf_tys = vec![];
+ let mut wf_tys = FxHashSet::default();
let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
impl_m_span,
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
- fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys);
+ fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys);
Ok(())
})
}
let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
- fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
+ fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default());
});
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
- fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+ fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default());
Ok(())
})
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
let implied_bounds = match impl_ty.container {
- ty::TraitContainer(_) => vec![],
+ ty::TraitContainer(_) => FxHashSet::default(),
ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
};
- fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
+ fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds);
Ok(())
})
use super::method::probe;
-use std::fmt;
use std::iter;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
let expected = self.resolve_vars_with_obligations(expected);
- let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) {
+ let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return (ty, None),
Err(e) => e,
};
// E.g. for `&format!("")`, where we want the span to the
// `format!()` invocation instead of its expansion.
if let Some(call_span) =
- iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s))
+ iter::successors(Some(expr.span), |s| s.parent_callsite())
+ .find(|&s| sp.contains(s))
{
if sm.span_to_snippet(call_span).is_ok() {
return Some((
// For now, don't suggest casting with `as`.
let can_cast = false;
- let prefix = if let Some(hir::Node::Expr(hir::Expr {
- kind: hir::ExprKind::Struct(_, fields, _),
- ..
+ let mut sugg = vec![];
+
+ if let Some(hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Struct(_, fields, _), ..
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
{
// `expr` is a literal field for a struct, only suggest if appropriate
.find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand)
{
// This is a field literal
- Some(field) => format!("{}: ", field.ident),
+ Some(field) => {
+ sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
+ }
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
None => return false,
}
- } else {
- String::new()
};
if let hir::ExprKind::Call(path, args) = &expr.kind {
checked_ty, expected_ty,
);
- let with_opt_paren: fn(&dyn fmt::Display) -> String =
- if expr.precedence().order() < PREC_POSTFIX {
- |s| format!("({})", s)
- } else {
- |s| s.to_string()
- };
+ let close_paren = if expr.precedence().order() < PREC_POSTFIX {
+ sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
+ ")"
+ } else {
+ ""
+ };
- let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty);
- let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src));
- let suffix_suggestion = with_opt_paren(&format_args!(
- "{}{}",
+ let mut cast_suggestion = sugg.clone();
+ cast_suggestion
+ .push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty)));
+ let mut into_suggestion = sugg.clone();
+ into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren)));
+ let mut suffix_suggestion = sugg.clone();
+ suffix_suggestion.push((
if matches!(
(&expected_ty.kind(), &checked_ty.kind()),
(ty::Int(_) | ty::Uint(_), ty::Float(_))
) {
// Remove fractional part from literal, for example `42.0f32` into `42`
let src = src.trim_end_matches(&checked_ty.to_string());
- src.split('.').next().unwrap()
+ let len = src.split('.').next().unwrap().len();
+ expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
} else {
- src.trim_end_matches(&checked_ty.to_string())
+ let len = src.trim_end_matches(&checked_ty.to_string()).len();
+ expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
+ },
+ if expr.precedence().order() < PREC_POSTFIX {
+ // Readd `)`
+ format!("{})", expected_ty)
+ } else {
+ expected_ty.to_string()
},
- expected_ty,
));
let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false }
.ok()
.map(|src| (expr, src))
});
- let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
+ let (msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
(lhs_expr_and_src, exp_to_found_is_fallible)
{
let msg = format!(
"you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
lhs_src, expected_ty, checked_ty, src
);
- let suggestion = format!("{}::from({})", checked_ty, lhs_src);
- (lhs_expr.span, msg, suggestion)
+ let suggestion = vec![
+ (lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)),
+ (lhs_expr.span.shrink_to_hi(), ")".to_string()),
+ ];
+ (msg, suggestion)
} else {
let msg = format!("{} and panic if the converted value doesn't fit", msg);
- let suggestion =
- format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
- (expr.span, msg, suggestion)
+ let mut suggestion = sugg.clone();
+ suggestion.push((
+ expr.span.shrink_to_hi(),
+ format!("{}.try_into().unwrap()", close_paren),
+ ));
+ (msg, suggestion)
};
- err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable);
+ err.multipart_suggestion_verbose(
+ &msg,
+ suggestion,
+ Applicability::MachineApplicable,
+ );
};
let suggest_to_change_suffix_or_into =
} else {
into_suggestion.clone()
};
- err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable);
+ err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable);
};
match (&expected_ty.kind(), &checked_ty.kind()) {
if found.bit_width() < exp.bit_width() {
suggest_to_change_suffix_or_into(err, false, true);
} else if literal_is_ty_suffixed(expr) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&lit_msg,
suffix_suggestion,
Applicability::MachineApplicable,
);
} else if can_cast {
// Missing try_into implementation for `f64` to `f32`
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!("{}, producing the closest possible value", cast_msg),
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
}
(&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => {
if literal_is_ty_suffixed(expr) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&lit_msg,
suffix_suggestion,
Applicability::MachineApplicable,
);
} else if can_cast {
// Missing try_into implementation for `{float}` to `{integer}`
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!("{}, rounding the float towards zero", msg),
cast_suggestion,
Applicability::MaybeIncorrect, // lossy conversion
(&ty::Float(ref exp), &ty::Uint(ref found)) => {
// if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer",
msg,
Applicability::MachineApplicable,
);
} else if literal_is_ty_suffixed(expr) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&lit_msg,
suffix_suggestion,
Applicability::MachineApplicable,
);
} else {
// Missing try_into implementation for `{integer}` to `{float}`
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer,
rounded if necessary",
(&ty::Float(ref exp), &ty::Int(ref found)) => {
// if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer",
&msg,
Applicability::MachineApplicable,
);
} else if literal_is_ty_suffixed(expr) {
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&lit_msg,
suffix_suggestion,
Applicability::MachineApplicable,
);
} else {
// Missing try_into implementation for `{integer}` to `{float}`
- err.span_suggestion(
- expr.span,
+ err.multipart_suggestion_verbose(
&format!(
"{}, producing the floating point representation of the integer, \
rounded if necessary",
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
+ ) -> Ty<'tcx> {
+ self.check_expr_with_expectation_and_args(expr, expected, &[])
+ }
+
+ /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
+ /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
+ pub(super) fn check_expr_with_expectation_and_args(
+ &self,
+ expr: &'tcx hir::Expr<'tcx>,
+ expected: Expectation<'tcx>,
+ args: &'tcx [hir::Expr<'tcx>],
) -> Ty<'tcx> {
if self.tcx().sess.verbose() {
// make this code only run with -Zverbose because it is probably slow
let old_diverges = self.diverges.replace(Diverges::Maybe);
let old_has_errors = self.has_errors.replace(false);
- let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected));
+ let ty = ensure_sufficient_stack(|| match &expr.kind {
+ hir::ExprKind::Path(
+ qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..),
+ ) => self.check_expr_path(qpath, expr, args),
+ _ => self.check_expr_kind(expr, expected),
+ });
// Warn for non-block expressions with diverging children.
match expr.kind {
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
self.check_lang_item_path(lang_item, expr)
}
- ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr),
+ ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
ExprKind::LlvmInlineAsm(asm) => {
for expr in asm.outputs_exprs.iter().chain(asm.inputs_exprs.iter()) {
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
}
- fn check_expr_path(
+ pub(crate) fn check_expr_path(
&self,
qpath: &'tcx hir::QPath<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
+ args: &'tcx [hir::Expr<'tcx>],
) -> Ty<'tcx> {
let tcx = self.tcx;
let (res, opt_ty, segs) =
// We just want to check sizedness, so instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
+ let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
let input = self
.replace_bound_vars_with_fresh_vars(
- expr.span,
+ span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
)
.0;
self.require_type_is_sized_deferred(
input,
- expr.span,
+ span,
traits::SizedArgumentType(None),
);
}
if self.ret_coercion_span.get().is_none() {
self.ret_coercion_span.set(Some(e.span));
}
- self.check_return_expr(e);
+ self.check_return_expr(e, true);
} else {
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
if self.ret_coercion_span.get().is_none() {
self.tcx.types.never
}
- pub(super) fn check_return_expr(&self, return_expr: &'tcx hir::Expr<'tcx>) {
+ /// `explicit_return` is `true` if we're checkng an explicit `return expr`,
+ /// and `false` if we're checking a trailing expression.
+ pub(super) fn check_return_expr(
+ &self,
+ return_expr: &'tcx hir::Expr<'tcx>,
+ explicit_return: bool,
+ ) {
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
span_bug!(return_expr.span, "check_return_expr called outside fn body")
});
let ret_ty = ret_coercion.borrow().expected_ty();
let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
+ let mut span = return_expr.span;
+ // Use the span of the trailing expression for our cause,
+ // not the span of the entire function
+ if !explicit_return {
+ if let ExprKind::Block(body, _) = return_expr.kind {
+ if let Some(last_expr) = body.expr {
+ span = last_expr.span;
+ }
+ }
+ }
ret_coercion.borrow_mut().coerce(
self,
- &self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
+ &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
return_expr,
return_expr_ty,
);
field,
expr_t,
expr,
+ None,
);
}
err.emit();
expr_t
);
err.span_label(field.span, "method, not a field");
- if !self.expr_in_place(expr.hir_id) {
+ let expr_is_call =
+ if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
+ self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
+ {
+ expr.hir_id == callee.hir_id
+ } else {
+ false
+ };
+ let expr_snippet =
+ self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new());
+ let is_wrapped = expr_snippet.starts_with("(") && expr_snippet.ends_with(")");
+ let after_open = expr.span.lo() + rustc_span::BytePos(1);
+ let before_close = expr.span.hi() - rustc_span::BytePos(1);
+
+ if expr_is_call && is_wrapped {
+ err.multipart_suggestion(
+ "remove wrapping parentheses to call the method",
+ vec![
+ (expr.span.with_hi(after_open), String::new()),
+ (expr.span.with_lo(before_close), String::new()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ } else if !self.expr_in_place(expr.hir_id) {
+ // Suggest call parentheses inside the wrapping parentheses
+ let span = if is_wrapped {
+ expr.span.with_lo(after_open).with_hi(before_close)
+ } else {
+ expr.span
+ };
self.suggest_method_call(
&mut err,
"use parentheses to call the method",
field,
expr_t,
expr,
+ Some(span),
);
} else {
err.help("methods are immutable and cannot be assigned to");
/// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
/// to get more type information.
- pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+ pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
+ }
+
+ pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
+ &self,
+ mut ty: Ty<'tcx>,
+ mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
+ ) -> Ty<'tcx> {
debug!("resolve_vars_with_obligations(ty={:?})", ty);
// No Infer()? Nothing needs doing.
// possible. This can help substantially when there are
// indirect dependencies that don't seem worth tracking
// precisely.
- self.select_obligations_where_possible(false, |_| {});
+ self.select_obligations_where_possible(false, mutate_fulfillment_errors);
ty = self.resolve_vars_if_possible(ty);
debug!("resolve_vars_with_obligations: ty={:?}", ty);
};
use rustc_ast as ast;
+use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
self.point_at_arg_instead_of_call_if_possible(
errors,
&final_arg_types[..],
+ expr,
sp,
&args,
);
continue;
}
- debug!("checking the argument");
let formal_ty = formal_tys[i];
+ debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
// The special-cased logic below has three functions:
// 1. Provide as good of an expected type as possible.
// to, which is `expected_ty` if `rvalue_hint` returns an
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
+
+ // Cause selection errors caused by resolving a single argument to point at the
+ // argument and not the call. This is otherwise redundant with the `demand_coerce`
+ // call immediately after, but it lets us customize the span pointed to in the
+ // fulfillment error to be more accurate.
+ let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
+ coerce_ty,
+ |errors| {
+ // This is not coming from a macro or a `derive`.
+ if sp.desugaring_kind().is_none()
+ && !arg.span.from_expansion()
+ // Do not change the spans of `async fn`s.
+ && !matches!(
+ expr.kind,
+ hir::ExprKind::Call(
+ hir::Expr {
+ kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
+ ..
+ },
+ _
+ )
+ ) {
+ for error in errors {
+ error.obligation.cause.make_mut().span = arg.span;
+ let code = error.obligation.cause.code.clone();
+ error.obligation.cause.make_mut().code =
+ ObligationCauseCode::FunctionArgumentObligation {
+ arg_hir_id: arg.hir_id,
+ call_hir_id: expr.hir_id,
+ parent_code: Lrc::new(code),
+ };
+ }
+ }
+ },
+ );
+
// We're processing function arguments so we definitely want to use
// two-phase borrows.
self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
Some((variant, ty))
} else {
- struct_span_err!(
- self.tcx.sess,
- path_span,
- E0071,
- "expected struct, variant or union type, found {}",
- ty.sort_string(self.tcx)
- )
- .span_label(path_span, "not a struct")
- .emit();
+ match ty.kind() {
+ ty::Error(_) => {
+ // E0071 might be caused by a spelling error, which will have
+ // already caused an error message and probably a suggestion
+ // elsewhere. Refrain from emitting more unhelpful errors here
+ // (issue #88844).
+ }
+ _ => {
+ struct_span_err!(
+ self.tcx.sess,
+ path_span,
+ E0071,
+ "expected struct, variant or union type, found {}",
+ ty.sort_string(self.tcx)
+ )
+ .span_label(path_span, "not a struct")
+ .emit();
+ }
+ }
None
}
}
&self,
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)],
+ expr: &'tcx hir::Expr<'tcx>,
call_sp: Span,
args: &'tcx [hir::Expr<'tcx>],
) {
// We make sure that only *one* argument matches the obligation failure
// and we assign the obligation's span to its expression's.
error.obligation.cause.make_mut().span = args[ref_in].span;
- error.points_at_arg_span = true;
+ let code = error.obligation.cause.code.clone();
+ error.obligation.cause.make_mut().code =
+ ObligationCauseCode::FunctionArgumentObligation {
+ arg_hir_id: args[ref_in].hir_id,
+ call_hir_id: expr.hir_id,
+ parent_code: Lrc::new(code),
+ };
}
}
}
//! intrinsics that the compiler exposes.
use crate::errors::{
- SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
+ UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
WrongNumberOfGenericArgumentsToIntrinsic,
};
use crate::require_same_types;
| sym::simd_reduce_max
| sym::simd_reduce_min_nanless
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
+ sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
name if name.as_str().starts_with("simd_shuffle") => {
match name.as_str()["simd_shuffle".len()..].parse() {
Ok(n) => {
(2, params, param(1))
}
Err(_) => {
- tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name });
+ let msg =
+ format!("unrecognized platform-specific intrinsic function: `{}`", name);
+ tcx.sess.struct_span_err(it.span, &msg).emit();
return;
}
}
method_name: Ident,
self_ty: Ty<'tcx>,
call_expr: &hir::Expr<'_>,
+ span: Option<Span>,
) {
let params = self
.probe_for_name(
.unwrap_or(0);
// Account for `foo.bar<T>`;
- let sugg_span = call_expr.span.shrink_to_hi();
+ let sugg_span = span.unwrap_or_else(|| call_expr.span).shrink_to_hi();
let (suggestion, applicability) = (
format!("({})", (0..params).map(|_| "_").collect::<Vec<_>>().join(", ")),
if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect },
impl<'tcx> AutorefOrPtrAdjustment<'tcx> {
fn get_unsize(&self) -> Option<Ty<'tcx>> {
match self {
- AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => unsize.clone(),
+ AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
AutorefOrPtrAdjustment::ToConstPtr => None,
}
}
tcx: TyCtxt<'_>,
traits: &mut Vec<DefId>,
external_mods: &mut FxHashSet<DefId>,
- res: Res,
+ res: Res<!>,
) {
match res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
// from normalization. We could just discard these, but to align with
// compare_method and elsewhere, we just add implied bounds for
// these types.
- let mut wf_tys = vec![];
+ let mut wf_tys = FxHashSet::default();
// Compute the fty from point of view of inside the fn.
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
wf_tys.extend(fn_sig.inputs_and_output.iter());
fcx.write_ty(id, expected_type);
- (fcx, vec![])
+ (fcx, FxHashSet::default())
};
let fallback_has_occurred = fcx.type_inference_fallback();
fcx.select_all_obligations_or_error();
if fn_sig.is_some() {
- fcx.regionck_fn(id, body, span, &wf_tys);
+ fcx.regionck_fn(id, body, span, wf_tys);
} else {
fcx.regionck_expr(body);
}
ex.span,
format!("cannot apply unary operator `{}`", op.as_str()),
);
- match actual.kind() {
- Uint(_) if op == hir::UnOp::Neg => {
- err.note("unsigned values cannot be negated");
-
- if let hir::ExprKind::Unary(
- _,
- hir::Expr {
- kind:
- hir::ExprKind::Lit(Spanned {
- node: ast::LitKind::Int(1, _),
- ..
- }),
- ..
- },
- ) = ex.kind
- {
- err.span_suggestion(
- ex.span,
- &format!(
- "you may have meant the maximum value of `{}`",
- actual
- ),
- format!("{}::MAX", actual),
- Applicability::MaybeIncorrect,
- );
+
+ let sp = self.tcx.sess.source_map().start_point(ex.span);
+ if let Some(sp) =
+ self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
+ {
+ // If the previous expression was a block expression, suggest parentheses
+ // (turning this into a binary subtraction operation instead.)
+ // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
+ self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+ } else {
+ match actual.kind() {
+ Uint(_) if op == hir::UnOp::Neg => {
+ err.note("unsigned values cannot be negated");
+
+ if let hir::ExprKind::Unary(
+ _,
+ hir::Expr {
+ kind:
+ hir::ExprKind::Lit(Spanned {
+ node: ast::LitKind::Int(1, _),
+ ..
+ }),
+ ..
+ },
+ ) = ex.kind
+ {
+ err.span_suggestion(
+ ex.span,
+ &format!(
+ "you may have meant the maximum value of `{}`",
+ actual
+ ),
+ format!("{}::MAX", actual),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ Str | Never | Char | Tuple(_) | Array(_, _) => {}
+ Ref(_, ref lty, _) if *lty.kind() == Str => {}
+ _ => {
+ let missing_trait = match op {
+ hir::UnOp::Neg => "std::ops::Neg",
+ hir::UnOp::Not => "std::ops::Not",
+ hir::UnOp::Deref => "std::ops::UnDerf",
+ };
+ suggest_impl_missing(&mut err, operand_ty, &missing_trait);
}
- }
- Str | Never | Char | Tuple(_) | Array(_, _) => {}
- Ref(_, ref lty, _) if *lty.kind() == Str => {}
- _ => {
- let missing_trait = match op {
- hir::UnOp::Neg => "std::ops::Neg",
- hir::UnOp::Not => "std::ops::Not",
- hir::UnOp::Deref => "std::ops::UnDerf",
- };
- suggest_impl_missing(&mut err, operand_ty, &missing_trait);
}
}
err.emit();
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
};
// Require `..` if struct has non_exhaustive attribute.
- if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
+ let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+ if non_exhaustive && !etc {
self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
}
if etc {
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
}
- } else if !etc && !unmentioned_fields.is_empty() {
+ } else if !unmentioned_fields.is_empty() {
let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
.iter()
.copied()
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
})
.collect();
-
- if accessible_unmentioned_fields.is_empty() {
- unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
- } else {
- unmentioned_err = Some(self.error_unmentioned_fields(
- pat,
- &accessible_unmentioned_fields,
- accessible_unmentioned_fields.len() != unmentioned_fields.len(),
- &fields,
- ));
+ if non_exhaustive {
+ self.non_exhaustive_reachable_pattern(pat, &accessible_unmentioned_fields, adt_ty)
+ } else if !etc {
+ if accessible_unmentioned_fields.is_empty() {
+ unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
+ } else {
+ unmentioned_err = Some(self.error_unmentioned_fields(
+ pat,
+ &accessible_unmentioned_fields,
+ accessible_unmentioned_fields.len() != unmentioned_fields.len(),
+ &fields,
+ ));
+ }
}
}
match (inexistent_fields_err, unmentioned_err) {
plural
),
);
- if plural == "" {
+
+ if unmentioned_fields.len() == 1 {
let input =
unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
let suggested_name = find_best_match_for_name(&input, ident.name, None);
// We don't want to throw `E0027` in case we have thrown `E0026` for them.
unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
}
+ } else if inexistent_fields.len() == 1 {
+ let unmentioned_field = unmentioned_fields[0].1.name;
+ err.span_suggestion_short(
+ ident.span,
+ &format!(
+ "`{}` has a field named `{}`",
+ tcx.def_path_str(variant.def_id),
+ unmentioned_field
+ ),
+ unmentioned_field.to_string(),
+ Applicability::MaybeIncorrect,
+ );
}
}
}
err
}
+ /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns`
+ /// is not exhaustive enough.
+ ///
+ /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
+ fn non_exhaustive_reachable_pattern(
+ &self,
+ pat: &Pat<'_>,
+ unmentioned_fields: &[(&ty::FieldDef, Ident)],
+ ty: Ty<'tcx>,
+ ) {
+ fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
+ const LIMIT: usize = 3;
+ match witnesses {
+ [] => bug!(),
+ [witness] => format!("`{}`", witness),
+ [head @ .., tail] if head.len() < LIMIT => {
+ let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+ format!("`{}` and `{}`", head.join("`, `"), tail)
+ }
+ _ => {
+ let (head, tail) = witnesses.split_at(LIMIT);
+ let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+ format!("`{}` and {} more", head.join("`, `"), tail.len())
+ }
+ }
+ }
+ let joined_patterns = joined_uncovered_patterns(
+ &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
+ );
+
+ self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
+ let mut lint = build.build("some fields are not explicitly listed");
+ lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
+
+ lint.help(
+ "ensure that all fields are mentioned explicitly by adding the suggested fields",
+ );
+ lint.note(&format!(
+ "the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+ ty,
+ ));
+ lint.emit();
+ });
+ }
+
/// Returns a diagnostic reporting a struct pattern which does not mention some fields.
///
/// ```text
use crate::check::FnCtxt;
use crate::mem_categorization as mc;
use crate::middle::region;
+use rustc_data_structures::stable_set::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
/// Region checking during the WF phase for items. `wf_tys` are the
/// types from which we should derive implied bounds, if any.
- pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
+ pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) {
debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
let subject = self.tcx.hir().local_def_id(item_id);
let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
fn_id: hir::HirId,
body: &'tcx hir::Body<'tcx>,
span: Span,
- wf_tys: &[Ty<'tcx>],
+ wf_tys: FxHashSet<Ty<'tcx>>,
) {
debug!("regionck_fn(id={})", fn_id);
let subject = self.tcx.hir().body_owner_def_id(body.id());
// because it will have no effect.
//
// FIXME(#27579) return types should not be implied bounds
- let fn_sig_tys: Vec<_> =
+ let fn_sig_tys: FxHashSet<_> =
fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
- self.outlives_environment.add_implied_bounds(
- self.fcx,
- &fn_sig_tys[..],
- body_id.hir_id,
- span,
- );
+ self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span);
self.outlives_environment.save_implied_bounds(body_id.hir_id);
self.link_fn_params(&body.params);
self.visit_body(body);
impl<'tcx> CheckWfFcxBuilder<'tcx> {
fn with_fcx<F>(&mut self, f: F)
where
- F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec<Ty<'tcx>>,
+ F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet<Ty<'tcx>>,
{
let id = self.id;
let span = self.span;
}
let wf_tys = f(&fcx);
fcx.select_all_obligations_or_error();
- fcx.regionck_item(id, span, &wf_tys);
+ fcx.regionck_item(id, span, wf_tys);
});
}
}
let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
let (mut implied_bounds, self_ty) = match item.container {
- ty::TraitContainer(_) => (vec![], fcx.tcx.types.self_param),
+ ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param),
ty::ImplContainer(def_id) => {
(fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id))
}
check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
// No implied bounds in a struct definition.
- vec![]
+ FxHashSet::default()
});
}
for_item(tcx, item).with_fcx(|fcx| {
check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
- vec![]
+ FxHashSet::default()
});
}
for_id(tcx, item_id, span).with_fcx(|fcx| {
let def_id = tcx.hir().local_def_id(item_id);
let sig = tcx.fn_sig(def_id);
- let mut implied_bounds = vec![];
+ let mut implied_bounds = FxHashSet::default();
check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
implied_bounds
})
}
// No implied bounds in a const, etc.
- vec![]
+ FxHashSet::default()
});
}
sig: ty::PolyFnSig<'tcx>,
hir_decl: &hir::FnDecl<'_>,
def_id: DefId,
- implied_bounds: &mut Vec<Ty<'tcx>>,
+ implied_bounds: &mut FxHashSet<Ty<'tcx>>,
) {
let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
// Unnormalized types in signature are WF too
implied_bounds.extend(sig.inputs());
// FIXME(#27579) return types should not be implied bounds
- implied_bounds.push(sig.output());
+ implied_bounds.insert(sig.output());
// Normalize the input and output types one at a time, using a different
// `WellFormedLoc` for each. We cannot call `normalize_associated_types`
);
// FIXME(#27579) return types should not be implied bounds
- implied_bounds.push(sig.output());
+ implied_bounds.insert(sig.output());
debug!(?implied_bounds);
.collect()
}
- pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
+ pub(super) fn impl_implied_bounds(
+ &self,
+ impl_def_id: DefId,
+ span: Span,
+ ) -> FxHashSet<Ty<'tcx>> {
match self.tcx.impl_trait_ref(impl_def_id) {
Some(trait_ref) => {
// Trait impl: take implied bounds from all types that
// Inherent impl: take implied bounds from the `self` type.
let self_ty = self.tcx.type_of(impl_def_id);
let self_ty = self.normalize_associated_types_in(span, self_ty);
- vec![self_ty]
+ std::array::IntoIter::new([self_ty]).collect()
}
}
}
lang: &str,
ty: &str,
span: Span,
- assoc_items: &[hir::ImplItemRef<'_>],
+ assoc_items: &[hir::ImplItemRef],
) {
match (lang_def_id, lang_def_id2) {
(Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::{abi, PanicStrategy, SanitizerSet};
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
use std::iter;
let suggestions = vec![
(lt_sp, sugg),
(
- span,
+ span.with_hi(item_segment.ident.span.lo()),
format!(
- "{}::{}",
+ "{}::",
// Replace the existing lifetimes with a new named lifetime.
self.tcx
.replace_late_bound_regions(poly_trait_ref, |_| {
))
})
.0,
- item_segment.ident
),
),
];
| hir::Node::ForeignItem(_)
| hir::Node::TraitItem(_)
| hir::Node::ImplItem(_) => {
- err.span_suggestion(
- span,
+ err.span_suggestion_verbose(
+ span.with_hi(item_segment.ident.span.lo()),
"use a fully qualified path with inferred lifetimes",
format!(
- "{}::{}",
+ "{}::",
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
- item_segment.ident
),
Applicability::MaybeIncorrect,
);
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
}
+ // With -Z panic-in-drop=abort, drop_in_place never unwinds.
+ if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
+ if Some(id) == tcx.lang_items().drop_in_place_fn() {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+ }
+ }
+
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
let mut inline_span = None;
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[error = "E0439"]
-pub struct SimdShuffleMissingLength {
- #[message = "invalid `simd_shuffle`, needs length: `{name}`"]
- pub span: Span,
- pub name: Symbol,
-}
-
#[derive(SessionDiagnostic)]
#[error = "E0436"]
pub struct FunctionalRecordUpdateOnNonStruct {
// We will tag this as part of the WF check -- logically, it is,
// but it's one that we must perform earlier than the rest of
// WfCheck.
- for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_impl_wf(module);
- }
+ tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
}
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
fn enforce_impl_params_are_constrained(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
- impl_item_refs: &[hir::ImplItemRef<'_>],
+ impl_item_refs: &[hir::ImplItemRef],
) {
// Every lifetime used in an associated type must be constrained.
let impl_self_ty = tcx.type_of(impl_def_id);
}
/// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef<'_>]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
let mut seen_type_items = FxHashMap::default();
let mut seen_value_items = FxHashMap::default();
for impl_item_ref in impl_item_refs {
// FIXME(matthewjasper) We shouldn't need to use `track_errors`.
tcx.sess.track_errors(|| {
tcx.sess.time("type_collecting", || {
- for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().collect_mod_item_types(module);
- }
+ tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
});
})?;
// NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
tcx.sess.time("item_types_checking", || {
- for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_item_types(module);
- }
+ tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
AngleBrackets::Missing => 0,
// Only lifetime arguments can be implied
AngleBrackets::Implied => self.gen_args.args.len(),
- AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
- hir::GenericArg::Lifetime(_) => acc + 1,
- _ => acc,
- }),
+ AngleBrackets::Available => self.gen_args.num_lifetime_params(),
}
}
AngleBrackets::Missing => 0,
// Only lifetime arguments can be implied
AngleBrackets::Implied => 0,
- AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
- hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => acc + 1,
- _ => acc,
- }),
+ AngleBrackets::Available => self.gen_args.num_generic_params(),
}
}
let mut found_redundant = false;
for arg in self.gen_args.args {
match arg {
- hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => {
+ hir::GenericArg::Type(_)
+ | hir::GenericArg::Const(_)
+ | hir::GenericArg::Infer(_) => {
gen_arg_spans.push(arg.span());
if gen_arg_spans.len() > self.num_expected_type_or_const_args() {
found_redundant = true;
# the same format as above, but since these targets are experimental, they are
# not built by default and the experimental Rust compilation targets that depend
# on them will not work unless the user opts in to building them.
-#experimental-targets = "AVR"
+#experimental-targets = "AVR;M68k"
# Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
+where
+ B::Owned: ~const Borrow<B>,
+{
type Target = B;
fn deref(&self) -> &B {
T,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
- pub(crate) inner: VecDeque<T, A>,
+ inner: VecDeque<T, A>,
+}
+
+impl<T, A: Allocator> IntoIter<T, A> {
+ pub(super) fn new(inner: VecDeque<T, A>) -> Self {
+ IntoIter { inner }
+ }
}
#[stable(feature = "collection_debug", since = "1.17.0")]
/// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
/// value.
fn into_iter(self) -> IntoIter<T, A> {
- IntoIter { inner: self }
+ IntoIter::new(self)
}
}
#![feature(binary_heap_retain)]
#![feature(binary_heap_as_slice)]
#![feature(inplace_iteration)]
-#![feature(iter_map_while)]
#![feature(slice_group_by)]
#![feature(slice_partition_dedup)]
#![feature(vec_spare_capacity)]
-Subproject commit 4f925f8d81dfa57067537217e501e1dff7433491
+Subproject commit cc89bb66f91b2b4a640b0b525ca5d753e3346d7e
--- /dev/null
+../std/boxed/struct.Box.html#method.into_raw
--- /dev/null
+../std/fs/struct.File.html
--- /dev/null
+../std/io/trait.BufRead.html
--- /dev/null
+../std/io/trait.Read.html
--- /dev/null
+../std/io/trait.Seek.html
--- /dev/null
+../std/io/trait.Write.html
--- /dev/null
+../std/net/trait.ToSocketAddrs.html
--- /dev/null
+../std/process/fn.exit.html
--- /dev/null
+../std/string/struct.String.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EscapeDefault {
- range: Range<usize>,
+ range: Range<u8>,
data: [u8; 4],
}
impl Iterator for EscapeDefault {
type Item = u8;
fn next(&mut self) -> Option<u8> {
- self.range.next().map(|i| self.data[i])
+ self.range.next().map(|i| self.data[i as usize])
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
fn next_back(&mut self) -> Option<u8> {
- self.range.next_back().map(|i| self.data[i])
+ self.range.next_back().map(|i| self.data[i as usize])
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: ok because `escape_default` created only valid utf-8 data
- f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
+ f.write_str(unsafe {
+ from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
+ })
}
}
#[lang = "bool"]
impl bool {
- /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+ /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
+ /// or `None` otherwise.
///
/// # Examples
///
if self { Some(t) } else { None }
}
- /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+ /// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html),
+ /// or `None` otherwise.
///
/// # Examples
///
/// ```
#[inline(always)]
#[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")]
- pub fn get_mut(&mut self) -> &mut T {
+ #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")]
+ pub const fn get_mut(&mut self) -> &mut T {
&mut self.value
}
/// decoding error.
///
/// It can occur, for example, when giving ill-formed UTF-8 bytes to
- /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy).
+ /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy).
#[stable(feature = "assoc_char_consts", since = "1.52.0")]
pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
/// Converts a `u32` to a `char`.
///
/// Note that all `char`s are valid [`u32`]s, and can be cast to one with
- /// [`as`](keyword.as.html):
+ /// [`as`](../std/keyword.as.html):
///
/// ```
/// let c = '💯';
/// println!("\\u{{2764}}");
/// ```
///
- /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+ /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
/// println!("\\n");
/// ```
///
- /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+ /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('\n'.escape_debug().to_string(), "\\n");
/// println!("\\\"");
/// ```
///
- /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+ /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('"'.escape_default().to_string(), "\\\"");
/// println!("i\u{307}");
/// ```
///
- /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+ /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('C'.to_lowercase().to_string(), "c");
/// println!("SS");
/// ```
///
- /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+ /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('c'.to_uppercase().to_string(), "C");
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "clone"]
#[rustc_diagnostic_item = "Clone"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
pub trait Clone: Sized {
/// Returns a copy of the value.
///
)]
#[doc(alias = "{:?}")]
#[rustc_diagnostic_item = "debug_trait"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
pub trait Debug {
/// Formats the value using the given formatter.
///
/// [`map_while`]: Iterator::map_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
#[derive(Clone)]
pub struct MapWhile<I, P> {
iter: I,
}
}
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
}
}
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
where
P: FnMut(I::Item) -> Option<B>,
#[stable(feature = "iter_intersperse", since = "1.56.0")]
pub use self::intersperse::{Intersperse, IntersperseWith};
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
pub use self::map_while::MapWhile;
#[unstable(feature = "trusted_random_access", issue = "none")]
pub use self::adapters::Copied;
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub use self::adapters::Flatten;
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
pub use self::adapters::MapWhile;
#[unstable(feature = "inplace_iteration", issue = "none")]
pub use self::adapters::SourceIter;
/// Basic usage:
///
/// ```
- /// #![feature(iter_map_while)]
/// let a = [-1i32, 4, 0, 1];
///
/// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
/// Stopping after an initial [`None`]:
///
/// ```
- /// #![feature(iter_map_while)]
/// use std::convert::TryFrom;
///
/// let a = [0, 1, 2, -3, 4, 5, -6];
/// removed:
///
/// ```
- /// #![feature(iter_map_while)]
/// use std::convert::TryFrom;
///
/// let a = [1, 2, -3, 4];
///
/// [`fuse`]: Iterator::fuse
#[inline]
- #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+ #[stable(feature = "iter_map_while", since = "1.57.0")]
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
where
Self: Sized,
/// If the iterator is empty, returns [`None`]; otherwise, returns the
/// result of the reduction.
///
+ /// The reducing function is a closure with two arguments: an 'accumulator', and an element.
/// For iterators with at least one element, this is the same as [`fold()`]
- /// with the first element of the iterator as the initial value, folding
+ /// with the first element of the iterator as the initial accumulator value, folding
/// every subsequent element into it.
///
/// [`fold()`]: Iterator::fold
/// where I: Iterator,
/// I::Item: Ord,
/// {
- /// iter.reduce(|a, b| {
- /// if a >= b { a } else { b }
+ /// iter.reduce(|accum, item| {
+ /// if accum >= item { accum } else { item }
/// })
/// }
/// let a = [10, 20, 5, -23, 0];
if let Some(val) = self.get() {
return Ok(val);
}
- let val = f()?;
+ /// Avoid inlining the initialization closure into the common path that fetches
+ /// the already initialized value
+ #[cold]
+ fn outlined_call<F, T, E>(f: F) -> Result<T, E>
+ where
+ F: FnOnce() -> Result<T, E>,
+ {
+ f()
+ }
+ let val = outlined_call(f)?;
// Note that *some* forms of reentrant initialization might lead to
// UB (see `reentrant_init` test). I believe that just removing this
// `assert`, while keeping `set/get` would be sound, but it seems
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_notable_trait)]
+#![feature(doc_primitive)]
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![feature(fundamental)]
/* compiler built-in */
}
}
+
+include!("primitive_docs.rs");
/// `Unsize<dyn fmt::Debug>`.
///
/// All implementations of `Unsize` are provided automatically by the compiler.
-///
-/// `Unsize` is implemented for:
-///
-/// - `[T; N]` is `Unsize<[T]>`
-/// - `T` is `Unsize<dyn Trait>` when `T: Trait`
-/// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
-/// - `T: Unsize<U>`
-/// - Foo is a struct
-/// - Only the last field of `Foo` has a type involving `T`
-/// - `T` is not part of the type of any other fields
-/// - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
+/// Those implementations are:
+///
+/// - Arrays `[T; N]` implement `Unsize<[T]>`.
+/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`.
+/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions
+/// are met:
+/// - `T: Unsize<U>`.
+/// - Only the last field of `Foo` has a type involving `T`.
+/// - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field.
///
/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
/// "user-defined" containers such as [`Rc`] to contain dynamically-sized
}
#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> Deref for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for ManuallyDrop<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
}
#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
&mut self.value
///
/// assert_eq!(u32::MAX, (zero - one).0);
/// ```
+///
+/// # Layout
+///
+/// `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
#[repr(transparent)]
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for &T {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for &T {
type Target = T;
#[rustc_diagnostic_item = "noop_method_deref"]
impl<T: ?Sized> !DerefMut for &T {}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for &mut T {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for &mut T {
type Target = T;
fn deref(&self) -> &T {
($msg:literal $(,)?) => (
$crate::panicking::panic($msg)
),
+ // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
($msg:expr $(,)?) => (
$crate::panicking::panic_str($msg)
),
+ // Special-case the single-argument case for const_panic.
+ ("{}", $arg:expr $(,)?) => (
+ $crate::panicking::panic_display(&$arg)
+ ),
($fmt:expr, $($arg:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
),
() => (
$crate::panicking::panic("explicit panic")
),
+ // Special-case the single-argument case for const_panic.
+ ("{}", $arg:expr $(,)?) => (
+ $crate::panicking::panic_display(&$arg)
+ ),
($($t:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
),
panic_fmt(format_args!("{}", expr));
}
+#[inline]
+#[track_caller]
+#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
+pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
+ panic_fmt(format_args!("{}", *x));
+}
+
#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
--- /dev/null
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
+#[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[doc(alias = "false")]
+/// The boolean type.
+///
+/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast
+/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0.
+///
+/// # Basic usage
+///
+/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
+/// which allow us to perform boolean operations using `&`, `|` and `!`.
+///
+/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is [`true`] and panics
+/// if it isn't.
+///
+/// ```
+/// let bool_val = true & false | false;
+/// assert!(!bool_val);
+/// ```
+///
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
+/// [`BitAnd`]: ops::BitAnd
+/// [`BitOr`]: ops::BitOr
+/// [`Not`]: ops::Not
+/// [`if`]: ../std/keyword.if.html
+///
+/// # Examples
+///
+/// A trivial example of the usage of `bool`:
+///
+/// ```
+/// let praise_the_borrow_checker = true;
+///
+/// // using the `if` conditional
+/// if praise_the_borrow_checker {
+/// println!("oh, yeah!");
+/// } else {
+/// println!("what?!!");
+/// }
+///
+/// // ... or, a match pattern
+/// match praise_the_borrow_checker {
+/// true => println!("keep praising!"),
+/// false => println!("you should praise!"),
+/// }
+/// ```
+///
+/// Also, since `bool` implements the [`Copy`] trait, we don't
+/// have to worry about the move semantics (just like the integer and float primitives).
+///
+/// Now an example of `bool` cast to integer type:
+///
+/// ```
+/// assert_eq!(true as i32, 1);
+/// assert_eq!(false as i32, 0);
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_bool {}
+
+#[doc(primitive = "never")]
+#[doc(alias = "!")]
+//
+/// The `!` type, also called "never".
+///
+/// `!` represents the type of computations which never resolve to any value at all. For example,
+/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and
+/// so returns `!`.
+///
+/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to
+/// write:
+///
+/// ```
+/// #![feature(never_type)]
+/// # fn foo() -> u32 {
+/// let x: ! = {
+/// return 123
+/// };
+/// # }
+/// ```
+///
+/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never
+/// assigned a value (because `return` returns from the entire function), `x` can be given type
+/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code
+/// would still be valid.
+///
+/// A more realistic usage of `!` is in this code:
+///
+/// ```
+/// # fn get_a_number() -> Option<u32> { None }
+/// # loop {
+/// let num: u32 = match get_a_number() {
+/// Some(num) => num,
+/// None => break,
+/// };
+/// # }
+/// ```
+///
+/// Both match arms must produce values of type [`u32`], but since `break` never produces a value
+/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another
+/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
+///
+/// [`u32`]: prim@u32
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
+///
+/// # `!` and generics
+///
+/// ## Infallible errors
+///
+/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
+/// trait:
+///
+/// ```
+/// trait FromStr: Sized {
+/// type Err;
+/// fn from_str(s: &str) -> Result<Self, Self::Err>;
+/// }
+/// ```
+///
+/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
+/// converting a string into a string will never result in an error, the appropriate type is `!`.
+/// (Currently the type actually used is an enum with no variants, though this is only because `!`
+/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of
+/// `!`, if we have to call [`String::from_str`] for some reason the result will be a
+/// [`Result<String, !>`] which we can unpack like this:
+///
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
+/// let Ok(s) = String::from_str("hello");
+/// ```
+///
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
+///
+/// ## Infinite loops
+///
+/// While [`Result<T, !>`] is very useful for removing errors, `!` can also be used to remove
+/// successes as well. If we think of [`Result<T, !>`] as "if this function returns, it has not
+/// errored," we get a very intuitive idea of [`Result<!, E>`] as well: if the function returns, it
+/// *has* errored.
+///
+/// For example, consider the case of a simple web server, which can be simplified to:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+/// let (client, request) = get_request().expect("disconnected");
+/// let response = request.process();
+/// response.send(client);
+/// }
+/// ```
+///
+/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection.
+/// Instead, we'd like to keep track of this error, like this:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+/// match get_request() {
+/// Err(err) => break err,
+/// Ok((client, request)) => {
+/// let response = request.process();
+/// response.send(client);
+/// },
+/// }
+/// }
+/// ```
+///
+/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it
+/// might be intuitive to simply return the error, we might want to wrap it in a [`Result<!, E>`]
+/// instead:
+///
+/// ```ignore (hypothetical-example)
+/// fn server_loop() -> Result<!, ConnectionError> {
+/// loop {
+/// let (client, request) = get_request()?;
+/// let response = request.process();
+/// response.send(client);
+/// }
+/// }
+/// ```
+///
+/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop
+/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok`
+/// because `!` coerces to `Result<!, ConnectionError>` automatically.
+///
+/// [`String::from_str`]: str::FromStr::from_str
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+/// [`FromStr`]: str::FromStr
+///
+/// # `!` and traits
+///
+/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
+/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!`
+/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other
+/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
+///
+/// ```compile_fail
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+/// unimplemented!()
+/// }
+/// ```
+///
+/// But this code does:
+///
+/// ```
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+/// if true {
+/// unimplemented!()
+/// } else {
+/// 0
+/// }
+/// }
+/// ```
+///
+/// The reason is that, in the first example, there are many possible types that `!` could coerce
+/// to, because many types implement `Add<u32>`. However, in the second example,
+/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type
+/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375]
+/// for more information on this quirk of `!`.
+///
+/// [#36375]: https://github.com/rust-lang/rust/issues/36375
+///
+/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`]
+/// for example:
+///
+/// ```
+/// #![feature(never_type)]
+/// # use std::fmt;
+/// # trait Debug {
+/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
+/// # }
+/// impl Debug for ! {
+/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+/// *self
+/// }
+/// }
+/// ```
+///
+/// Once again we're using `!`'s ability to coerce into any other type, in this case
+/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be
+/// called (because there is no value of type `!` for it to be called with). Writing `*self`
+/// essentially tells the compiler "We know that this code can never be run, so just treat the
+/// entire function body as having type [`fmt::Result`]". This pattern can be used a lot when
+/// implementing traits for `!`. Generally, any trait which only has methods which take a `self`
+/// parameter should have such an impl.
+///
+/// On the other hand, one trait which would not be appropriate to implement is [`Default`]:
+///
+/// ```
+/// trait Default {
+/// fn default() -> Self;
+/// }
+/// ```
+///
+/// Since `!` has no values, it has no default value either. It's true that we could write an
+/// `impl` for this which simply panics, but the same is true for any type (we could `impl
+/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
+///
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
+/// [`Debug`]: fmt::Debug
+/// [`default()`]: Default::default
+///
+#[unstable(feature = "never_type", issue = "35121")]
+mod prim_never {}
+
+#[doc(primitive = "char")]
+/// A character type.
+///
+/// The `char` type represents a single character. More specifically, since
+/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
+/// scalar value]', which is similar to, but not the same as, a '[Unicode code
+/// point]'.
+///
+/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
+///
+/// This documentation describes a number of methods and trait implementations on the
+/// `char` type. For technical reasons, there is additional, separate
+/// documentation in [the `std::char` module](char/index.html) as well.
+///
+/// # Representation
+///
+/// `char` is always four bytes in size. This is a different representation than
+/// a given character would have as part of a [`String`]. For example:
+///
+/// ```
+/// let v = vec!['h', 'e', 'l', 'l', 'o'];
+///
+/// // five elements times four bytes for each element
+/// assert_eq!(20, v.len() * std::mem::size_of::<char>());
+///
+/// let s = String::from("hello");
+///
+/// // five elements times one byte per element
+/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
+/// ```
+///
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+///
+/// As always, remember that a human intuition for 'character' might not map to
+/// Unicode's definitions. For example, despite looking similar, the 'é'
+/// character is one Unicode code point while 'é' is two Unicode code points:
+///
+/// ```
+/// let mut chars = "é".chars();
+/// // U+00e9: 'latin small letter e with acute'
+/// assert_eq!(Some('\u{00e9}'), chars.next());
+/// assert_eq!(None, chars.next());
+///
+/// let mut chars = "é".chars();
+/// // U+0065: 'latin small letter e'
+/// assert_eq!(Some('\u{0065}'), chars.next());
+/// // U+0301: 'combining acute accent'
+/// assert_eq!(Some('\u{0301}'), chars.next());
+/// assert_eq!(None, chars.next());
+/// ```
+///
+/// This means that the contents of the first string above _will_ fit into a
+/// `char` while the contents of the second string _will not_. Trying to create
+/// a `char` literal with the contents of the second string gives an error:
+///
+/// ```text
+/// error: character literal may only contain one codepoint: 'é'
+/// let c = 'é';
+/// ^^^
+/// ```
+///
+/// Another implication of the 4-byte fixed size of a `char` is that
+/// per-`char` processing can end up using a lot more memory:
+///
+/// ```
+/// let s = String::from("love: ❤️");
+/// let v: Vec<char> = s.chars().collect();
+///
+/// assert_eq!(12, std::mem::size_of_val(&s[..]));
+/// assert_eq!(32, std::mem::size_of_val(&v[..]));
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_char {}
+
+#[doc(primitive = "unit")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// The `()` type, also called "unit".
+///
+/// The `()` type has exactly one value `()`, and is used when there
+/// is no other meaningful value that could be returned. `()` is most
+/// commonly seen implicitly: functions without a `-> ...` implicitly
+/// have return type `()`, that is, these are equivalent:
+///
+/// ```rust
+/// fn long() -> () {}
+///
+/// fn short() {}
+/// ```
+///
+/// The semicolon `;` can be used to discard the result of an
+/// expression at the end of a block, making the expression (and thus
+/// the block) evaluate to `()`. For example,
+///
+/// ```rust
+/// fn returns_i64() -> i64 {
+/// 1i64
+/// }
+/// fn returns_unit() {
+/// 1i64;
+/// }
+///
+/// let is_i64 = {
+/// returns_i64()
+/// };
+/// let is_unit = {
+/// returns_i64();
+/// };
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_unit {}
+
+#[doc(primitive = "pointer")]
+#[doc(alias = "ptr")]
+#[doc(alias = "*")]
+#[doc(alias = "*const")]
+#[doc(alias = "*mut")]
+//
+/// Raw, unsafe pointers, `*const T`, and `*mut T`.
+///
+/// *[See also the `std::ptr` module](ptr).*
+///
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
+/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
+/// dereferenced (using the `*` operator), it must be non-null and aligned.
+///
+/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
+/// [`write`] must be used if the type has drop glue and memory is not already
+/// initialized - otherwise `drop` would be called on the uninitialized memory.
+///
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
+///
+/// # Common ways to create raw pointers
+///
+/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
+///
+/// ```
+/// let my_num: i32 = 10;
+/// let my_num_ptr: *const i32 = &my_num;
+/// let mut my_speed: i32 = 88;
+/// let my_speed_ptr: *mut i32 = &mut my_speed;
+/// ```
+///
+/// To get a pointer to a boxed value, dereference the box:
+///
+/// ```
+/// let my_num: Box<i32> = Box::new(10);
+/// let my_num_ptr: *const i32 = &*my_num;
+/// let mut my_speed: Box<i32> = Box::new(88);
+/// let my_speed_ptr: *mut i32 = &mut *my_speed;
+/// ```
+///
+/// This does not take ownership of the original allocation
+/// and requires no resource management later,
+/// but you must not use the pointer after its lifetime.
+///
+/// ## 2. Consume a box (`Box<T>`).
+///
+/// The [`into_raw`] function consumes a box and returns
+/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
+///
+/// ```
+/// let my_speed: Box<i32> = Box::new(88);
+/// let my_speed: *mut i32 = Box::into_raw(my_speed);
+///
+/// // By taking ownership of the original `Box<T>` though
+/// // we are obligated to put it together later to be destroyed.
+/// unsafe {
+/// drop(Box::from_raw(my_speed));
+/// }
+/// ```
+///
+/// Note that here the call to [`drop`] is for clarity - it indicates
+/// that we are done with the given value and it should be destroyed.
+///
+/// ## 3. Create it using `ptr::addr_of!`
+///
+/// Instead of coercing a reference to a raw pointer, you can use the macros
+/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
+/// These macros allow you to create raw pointers to fields to which you cannot
+/// create a reference (without causing undefined behaviour), such as an
+/// unaligned field. This might be necessary if packed structs or uninitialized
+/// memory is involved.
+///
+/// ```
+/// #[derive(Debug, Default, Copy, Clone)]
+/// #[repr(C, packed)]
+/// struct S {
+/// aligned: u8,
+/// unaligned: u32,
+/// }
+/// let s = S::default();
+/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
+/// ```
+///
+/// ## 4. Get it from C.
+///
+/// ```
+/// # #![feature(rustc_private)]
+/// extern crate libc;
+///
+/// use std::mem;
+///
+/// unsafe {
+/// let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
+/// if my_num.is_null() {
+/// panic!("failed to allocate memory");
+/// }
+/// libc::free(my_num as *mut libc::c_void);
+/// }
+/// ```
+///
+/// Usually you wouldn't literally use `malloc` and `free` from Rust,
+/// but C APIs hand out a lot of pointers generally, so are a common source
+/// of raw pointers in Rust.
+///
+/// [`null`]: ptr::null
+/// [`null_mut`]: ptr::null_mut
+/// [`is_null`]: pointer::is_null
+/// [`offset`]: pointer::offset
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
+/// [`drop`]: mem::drop
+/// [`write`]: ptr::write
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_pointer {}
+
+#[doc(primitive = "array")]
+#[doc(alias = "[]")]
+#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
+#[doc(alias = "[T; N]")]
+/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
+/// non-negative compile-time constant size, `N`.
+///
+/// There are two syntactic forms for creating an array:
+///
+/// * A list with each element, i.e., `[x, y, z]`.
+/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
+/// The type of `x` must be [`Copy`].
+///
+/// Note that `[expr; 0]` is allowed, and produces an empty array.
+/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
+/// be mindful of side effects.
+///
+/// Arrays of *any* size implement the following traits if the element type allows it:
+///
+/// - [`Copy`]
+/// - [`Clone`]
+/// - [`Debug`]
+/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`)
+/// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`]
+/// - [`Hash`]
+/// - [`AsRef`], [`AsMut`]
+/// - [`Borrow`], [`BorrowMut`]
+///
+/// Arrays of sizes from 0 to 32 (inclusive) implement the [`Default`] trait
+/// if the element type allows it. As a stopgap, trait implementations are
+/// statically generated up to size 32.
+///
+/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
+/// an array. Indeed, this provides most of the API for working with arrays.
+/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// You can move elements out of an array with a [slice pattern]. If you want
+/// one element, see [`mem::replace`].
+///
+/// # Examples
+///
+/// ```
+/// let mut array: [i32; 3] = [0; 3];
+///
+/// array[1] = 1;
+/// array[2] = 2;
+///
+/// assert_eq!([1, 2], &array[1..]);
+///
+/// // This loop prints: 0 1 2
+/// for x in array {
+/// print!("{} ", x);
+/// }
+/// ```
+///
+/// You can also iterate over reference to the array's elements:
+///
+/// ```
+/// let array: [i32; 3] = [0; 3];
+///
+/// for x in &array { }
+/// ```
+///
+/// You can use a [slice pattern] to move elements out of an array:
+///
+/// ```
+/// fn move_away(_: String) { /* Do interesting things. */ }
+///
+/// let [john, roa] = ["John".to_string(), "Roa".to_string()];
+/// move_away(john);
+/// move_away(roa);
+/// ```
+///
+/// # Editions
+///
+/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old
+/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
+/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition
+/// might be made consistent to the behavior of later editions.
+///
+/// ```rust,edition2018
+/// // Rust 2015 and 2018:
+///
+/// # #![allow(array_into_iter)] // override our `deny(warnings)`
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This creates a slice iterator, producing references to each value.
+/// for item in array.into_iter().enumerate() {
+/// let (i, x): (usize, &i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+///
+/// // The `array_into_iter` lint suggests this change for future compatibility:
+/// for item in array.iter().enumerate() {
+/// let (i, x): (usize, &i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+///
+/// // You can explicitly iterate an array by value using
+/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+/// let (i, x): (usize, i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate
+/// by value, and `iter()` should be used to iterate by reference like previous editions.
+///
+/// ```rust,edition2021
+/// // Rust 2021:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter().enumerate() {
+/// let (i, x): (usize, &i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array.into_iter().enumerate() {
+/// let (i, x): (usize, i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// Future language versions might start treating the `array.into_iter()`
+/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using
+/// those older editions should still be written with this change in mind, to
+/// prevent breakage in the future. The safest way to accomplish this is to
+/// avoid the `into_iter` syntax on those editions. If an edition update is not
+/// viable/desired, there are multiple alternatives:
+/// * use `iter`, equivalent to the old behavior, creating references
+/// * use [`IntoIterator::into_iter`], equivalent to the post-2021 behavior (Rust 1.53+)
+/// * replace `for ... in array.into_iter() {` with `for ... in array {`,
+/// equivalent to the post-2021 behavior (Rust 1.53+)
+///
+/// ```rust,edition2018
+/// // Rust 2015 and 2018:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter() {
+/// let x: &i32 = item;
+/// println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array) {
+/// let x: i32 = item;
+/// println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array {
+/// let x: i32 = item;
+/// println!("{}", x);
+/// }
+///
+/// // IntoIter can also start a chain.
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+/// let (i, x): (usize, i32) = item;
+/// println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// [slice]: prim@slice
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+/// [`Borrow`]: borrow::Borrow
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [slice pattern]: ../reference/patterns.html#slice-patterns
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_array {}
+
+#[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
+/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here
+/// means that elements are laid out so that every element is the same
+/// distance from its neighbors.
+///
+/// *[See also the `std::slice` module](crate::slice).*
+///
+/// Slices are a view into a block of memory represented as a pointer and a
+/// length.
+///
+/// ```
+/// // slicing a Vec
+/// let vec = vec![1, 2, 3];
+/// let int_slice = &vec[..];
+/// // coercing an array to a slice
+/// let str_slice: &[&str] = &["one", "two", "three"];
+/// ```
+///
+/// Slices are either mutable or shared. The shared slice type is `&[T]`,
+/// while the mutable slice type is `&mut [T]`, where `T` represents the element
+/// type. For example, you can mutate the block of memory that a mutable slice
+/// points to:
+///
+/// ```
+/// let mut x = [1, 2, 3];
+/// let x = &mut x[..]; // Take a full slice of `x`.
+/// x[1] = 7;
+/// assert_eq!(x, &[1, 7, 3]);
+/// ```
+///
+/// As slices store the length of the sequence they refer to, they have twice
+/// the size of pointers to [`Sized`](marker/trait.Sized.html) types.
+/// Also see the reference on
+/// [dynamically sized types](../reference/dynamically-sized-types.html).
+///
+/// ```
+/// # use std::rc::Rc;
+/// let pointer_size = std::mem::size_of::<&u8>();
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_slice {}
+
+#[doc(primitive = "str")]
+//
+/// String slices.
+///
+/// *[See also the `std::str` module](crate::str).*
+///
+/// The `str` type, also called a 'string slice', is the most primitive string
+/// type. It is usually seen in its borrowed form, `&str`. It is also the type
+/// of string literals, `&'static str`.
+///
+/// String slices are always valid UTF-8.
+///
+/// # Examples
+///
+/// String literals are string slices:
+///
+/// ```
+/// let hello = "Hello, world!";
+///
+/// // with an explicit type annotation
+/// let hello: &'static str = "Hello, world!";
+/// ```
+///
+/// They are `'static` because they're stored directly in the final binary, and
+/// so will be valid for the `'static` duration.
+///
+/// # Representation
+///
+/// A `&str` is made up of two components: a pointer to some bytes, and a
+/// length. You can look at these with the [`as_ptr`] and [`len`] methods:
+///
+/// ```
+/// use std::slice;
+/// use std::str;
+///
+/// let story = "Once upon a time...";
+///
+/// let ptr = story.as_ptr();
+/// let len = story.len();
+///
+/// // story has nineteen bytes
+/// assert_eq!(19, len);
+///
+/// // We can re-build a str out of ptr and len. This is all unsafe because
+/// // we are responsible for making sure the two components are valid:
+/// let s = unsafe {
+/// // First, we build a &[u8]...
+/// let slice = slice::from_raw_parts(ptr, len);
+///
+/// // ... and then convert that slice into a string slice
+/// str::from_utf8(slice)
+/// };
+///
+/// assert_eq!(s, Ok(story));
+/// ```
+///
+/// [`as_ptr`]: str::as_ptr
+/// [`len`]: str::len
+///
+/// Note: This example shows the internals of `&str`. `unsafe` should not be
+/// used to get a string slice under normal circumstances. Use `as_str`
+/// instead.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_str {}
+
+#[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// A finite heterogeneous sequence, `(T, U, ..)`.
+///
+/// Let's cover each of those in turn:
+///
+/// Tuples are *finite*. In other words, a tuple has a length. Here's a tuple
+/// of length `3`:
+///
+/// ```
+/// ("hello", 5, 'c');
+/// ```
+///
+/// 'Length' is also sometimes called 'arity' here; each tuple of a different
+/// length is a different, distinct type.
+///
+/// Tuples are *heterogeneous*. This means that each element of the tuple can
+/// have a different type. In that tuple above, it has the type:
+///
+/// ```
+/// # let _:
+/// (&'static str, i32, char)
+/// # = ("hello", 5, 'c');
+/// ```
+///
+/// Tuples are a *sequence*. This means that they can be accessed by position;
+/// this is called 'tuple indexing', and it looks like this:
+///
+/// ```rust
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// assert_eq!(tuple.1, 5);
+/// assert_eq!(tuple.2, 'c');
+/// ```
+///
+/// The sequential nature of the tuple applies to its implementations of various
+/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared
+/// sequentially until the first non-equal set is found.
+///
+/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
+///
+/// # Trait implementations
+///
+/// If every type inside a tuple implements one of the following traits, then a
+/// tuple itself also implements it.
+///
+/// * [`Clone`]
+/// * [`Copy`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Debug`]
+/// * [`Default`]
+/// * [`Hash`]
+///
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only
+/// implemented on tuples of arity 12 or less. In the future, this may change.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// ```
+///
+/// Tuples are often used as a return type when you want to return more than
+/// one value:
+///
+/// ```
+/// fn calculate_point() -> (i32, i32) {
+/// // Don't do a calculation, that's not the point of the example
+/// (4, 5)
+/// }
+///
+/// let point = calculate_point();
+///
+/// assert_eq!(point.0, 4);
+/// assert_eq!(point.1, 5);
+///
+/// // Combining this with patterns can be nicer.
+///
+/// let (x, y) = calculate_point();
+///
+/// assert_eq!(x, 4);
+/// assert_eq!(y, 5);
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_tuple {}
+
+#[doc(primitive = "f32")]
+/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
+///
+/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
+/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
+/// (such as `i32`), floating point types can represent non-integer numbers,
+/// too.
+///
+/// However, being able to represent this wide range of numbers comes at the
+/// cost of precision: floats can only represent some of the real numbers and
+/// calculation with floats round to a nearby representable number. For example,
+/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results
+/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented
+/// as `f32`. Note, however, that printing floats with `println` and friends will
+/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
+/// print `0.2`.
+///
+/// Additionally, `f32` can represent some special values:
+///
+/// - −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a
+/// possible value. For comparison −0.0 = +0.0, but floating point operations can carry
+/// the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and
+/// a negative number rounded to a value smaller than a float can represent also produces −0.0.
+/// - [∞](#associatedconstant.INFINITY) and
+/// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
+/// like `1.0 / 0.0`.
+/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
+/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
+/// behavior: it is unequal to any float, including itself! It is also neither
+/// smaller nor greater than any float, making it impossible to sort. Lastly,
+/// it is considered infectious as almost all calculations where one of the
+/// operands is NaN will also result in NaN.
+///
+/// For more information on floating point numbers, see [Wikipedia][wikipedia].
+///
+/// *[See also the `std::f32::consts` module](crate::f32::consts).*
+///
+/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f32 {}
+
+#[doc(primitive = "f64")]
+/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
+///
+/// This type is very similar to [`f32`], but has increased
+/// precision by using twice as many bits. Please see [the documentation for
+/// `f32`][`f32`] or [Wikipedia on double precision
+/// values][wikipedia] for more information.
+///
+/// *[See also the `std::f64::consts` module](crate::f64::consts).*
+///
+/// [`f32`]: prim@f32
+/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f64 {}
+
+#[doc(primitive = "i8")]
+//
+/// The 8-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i8 {}
+
+#[doc(primitive = "i16")]
+//
+/// The 16-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i16 {}
+
+#[doc(primitive = "i32")]
+//
+/// The 32-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i32 {}
+
+#[doc(primitive = "i64")]
+//
+/// The 64-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i64 {}
+
+#[doc(primitive = "i128")]
+//
+/// The 128-bit signed integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_i128 {}
+
+#[doc(primitive = "u8")]
+//
+/// The 8-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u8 {}
+
+#[doc(primitive = "u16")]
+//
+/// The 16-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u16 {}
+
+#[doc(primitive = "u32")]
+//
+/// The 32-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u32 {}
+
+#[doc(primitive = "u64")]
+//
+/// The 64-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u64 {}
+
+#[doc(primitive = "u128")]
+//
+/// The 128-bit unsigned integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_u128 {}
+
+#[doc(primitive = "isize")]
+//
+/// The pointer-sized signed integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_isize {}
+
+#[doc(primitive = "usize")]
+//
+/// The pointer-sized unsigned integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_usize {}
+
+#[doc(primitive = "reference")]
+#[doc(alias = "&")]
+#[doc(alias = "&mut")]
+//
+/// References, both shared and mutable.
+///
+/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
+/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html)</code> pattern.
+///
+/// For those familiar with pointers, a reference is just a pointer that is assumed to be
+/// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
+/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but
+/// creating a <code>&[bool]</code> that points to an allocation containing
+/// the value `3` causes undefined behaviour.
+/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
+/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
+///
+/// In most cases, references can be used much like the original value. Field access, method
+/// calling, and indexing work the same (save for mutability rules, of course). In addition, the
+/// comparison operators transparently defer to the referent's implementation, allowing references
+/// to be compared the same as owned values.
+///
+/// References have a lifetime attached to them, which represents the scope for which the borrow is
+/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or
+/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the
+/// total life of the program. For example, string literals have a `'static` lifetime because the
+/// text data is embedded into the binary of the program, rather than in an allocation that needs
+/// to be dynamically managed.
+///
+/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
+/// references with longer lifetimes can be freely coerced into references with shorter ones.
+///
+/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
+/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
+/// [`PartialEq`] compares values.
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(five_ref == other_five_ref);
+///
+/// assert!(ptr::eq(five_ref, same_five_ref));
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
+/// For more information on how to use references, see [the book's section on "References and
+/// Borrowing"][book-refs].
+///
+/// [book-refs]: ../book/ch04-02-references-and-borrowing.html
+///
+/// # Trait implementations
+///
+/// The following traits are implemented for all `&T`, regardless of the type of its referent:
+///
+/// * [`Copy`]
+/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!)
+/// * [`Deref`]
+/// * [`Borrow`]
+/// * [`Pointer`]
+///
+/// [`Deref`]: ops::Deref
+/// [`Borrow`]: borrow::Borrow
+/// [`Pointer`]: fmt::Pointer
+///
+/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating
+/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its
+/// referent:
+///
+/// * [`DerefMut`]
+/// * [`BorrowMut`]
+///
+/// [`DerefMut`]: ops::DerefMut
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
+///
+/// The following traits are implemented on `&T` references if the underlying `T` also implements
+/// that trait:
+///
+/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`AsRef`]
+/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`)
+/// * [`Hash`]
+/// * [`ToSocketAddrs`]
+///
+/// [`std::fmt`]: fmt
+/// ['Pointer`]: fmt::Pointer
+/// [`Hash`]: hash::Hash
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
+///
+/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
+/// implements that trait:
+///
+/// * [`AsMut`]
+/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`)
+/// * [`fmt::Write`]
+/// * [`Iterator`]
+/// * [`DoubleEndedIterator`]
+/// * [`ExactSizeIterator`]
+/// * [`FusedIterator`]
+/// * [`TrustedLen`]
+/// * [`Send`] \(note that `&T` references only get `Send` if <code>T: [Sync]</code>)
+/// * [`io::Write`]
+/// * [`Read`]
+/// * [`Seek`]
+/// * [`BufRead`]
+///
+/// [`FusedIterator`]: iter::FusedIterator
+/// [`TrustedLen`]: iter::TrustedLen
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
+///
+/// Note that due to method call deref coercion, simply calling a trait method will act like they
+/// work on references as well as they do on owned values! The implementations described here are
+/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
+/// locally known.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_ref {}
+
+#[doc(primitive = "fn")]
+//
+/// Function pointers, like `fn(usize) -> bool`.
+///
+/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].*
+///
+/// [`Fn`]: ops::Fn
+/// [`FnMut`]: ops::FnMut
+/// [`FnOnce`]: ops::FnOnce
+///
+/// Function pointers are pointers that point to *code*, not data. They can be called
+/// just like functions. Like references, function pointers are, among other things, assumed to
+/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
+/// pointers, make your type [`Option<fn()>`](core::option#options-and-pointers-nullable-pointers)
+/// with your required signature.
+///
+/// ### Safety
+///
+/// Plain function pointers are obtained by casting either plain functions, or closures that don't
+/// capture an environment:
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+/// x + 1
+/// }
+///
+/// let ptr: fn(usize) -> usize = add_one;
+/// assert_eq!(ptr(5), 6);
+///
+/// let clos: fn(usize) -> usize = |x| x + 5;
+/// assert_eq!(clos(5), 10);
+/// ```
+///
+/// In addition to varying based on their signature, function pointers come in two flavors: safe
+/// and unsafe. Plain `fn()` function pointers can only point to safe functions,
+/// while `unsafe fn()` function pointers can point to safe or unsafe functions.
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+/// x + 1
+/// }
+///
+/// unsafe fn add_one_unsafely(x: usize) -> usize {
+/// x + 1
+/// }
+///
+/// let safe_ptr: fn(usize) -> usize = add_one;
+///
+/// //ERROR: mismatched types: expected normal fn, found unsafe fn
+/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely;
+///
+/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
+/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
+/// ```
+///
+/// ### ABI
+///
+/// On top of that, function pointers can vary based on what ABI they use. This
+/// is achieved by adding the `extern` keyword before the type, followed by the
+/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
+/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
+/// type `extern "C" fn()`.
+///
+/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
+/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
+/// ABI.
+///
+/// For more information and a list of supported ABIs, see [the nomicon's
+/// section on foreign calling conventions][nomicon-abi].
+///
+/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+///
+/// ### Variadic functions
+///
+/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
+/// to be called with a variable number of arguments. Normal Rust functions, even those with an
+/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
+/// variadic functions][nomicon-variadic].
+///
+/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
+///
+/// ### Creating function pointers
+///
+/// When `bar` is the name of a function, then the expression `bar` is *not* a
+/// function pointer. Rather, it denotes a value of an unnameable type that
+/// uniquely identifies the function `bar`. The value is zero-sized because the
+/// type already identifies the function. This has the advantage that "calling"
+/// the value (it implements the `Fn*` traits) does not require dynamic
+/// dispatch.
+///
+/// This zero-sized type *coerces* to a regular function pointer. For example:
+///
+/// ```rust
+/// use std::mem;
+///
+/// fn bar(x: i32) {}
+///
+/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
+/// assert_eq!(mem::size_of_val(¬_bar_ptr), 0);
+///
+/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
+/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
+///
+/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
+/// ```
+///
+/// The last line shows that `&bar` is not a function pointer either. Rather, it
+/// is a reference to the function-specific ZST. `&bar` is basically never what you
+/// want when `bar` is a function.
+///
+/// ### Traits
+///
+/// Function pointers implement the following traits:
+///
+/// * [`Clone`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Hash`]
+/// * [`Pointer`]
+/// * [`Debug`]
+///
+/// [`Hash`]: hash::Hash
+/// [`Pointer`]: fmt::Pointer
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change.
+///
+/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
+/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
+/// are specially known to the compiler.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_fn {}
/// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
// Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is
- // in crate `alloc`, and as such doesn't exists yet when building `core`.
- // links to downstream crate: #74481. Since primitives are only documented in
- // libstd (#73423), this never leads to broken links in practice.
+ // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481.
+ // This breaks links when slice is displayed in core, but changing it to use relative links
+ // would break when the item is re-exported. So allow the core links to be broken for now.
#[allow(rustdoc::broken_intra_doc_links)]
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
#[inline]
fn test_formatting_parameters_are_forwarded() {
use std::collections::{BTreeMap, BTreeSet};
#[derive(Debug)]
+ #[allow(dead_code)]
struct Foo {
bar: u32,
baz: u32,
#![feature(iter_partition_in_place)]
#![feature(iter_is_partitioned)]
#![feature(iter_order_by)]
-#![feature(iter_map_while)]
#![feature(const_mut_refs)]
#![feature(const_pin)]
#![feature(const_slice_from_raw_parts)]
fn source($self: $S::Span) -> $S::Span;
fn start($self: $S::Span) -> LineColumn;
fn end($self: $S::Span) -> LineColumn;
+ fn before($self: $S::Span) -> $S::Span;
+ fn after($self: $S::Span) -> $S::Span;
fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>;
fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
fn source_text($self: $S::Span) -> Option<String>;
self.0.end().add_1_to_column()
}
+ /// Creates an empty span pointing to directly before this span.
+ #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+ pub fn before(&self) -> Span {
+ Span(self.0.before())
+ }
+
+ /// Creates an empty span pointing to directly after this span.
+ #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+ pub fn after(&self) -> Span {
+ Span(self.0.after())
+ }
+
/// Creates a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
--- /dev/null
+Box::into_raw
--- /dev/null
+io::BufRead
--- /dev/null
+net::ToSocketAddrs
--- /dev/null
+process::exit
--- /dev/null
+string::String
//! Iterators also provide a series of *adapter* methods for performing common
//! threads to sequences. Among the adapters are functional favorites like `map`,
//! `fold`, `skip` and `take`. Of particular interest to collections is the
-//! `rev` adapter, that reverses any iterator that supports this operation. Most
+//! `rev` adapter, which reverses any iterator that supports this operation. Most
//! collections provide reversible iterators as the way to iterate over them in
//! reverse order.
//!
/// - x86_64
/// - arm
/// - aarch64
+ /// - m68k
/// - mips
/// - mips64
/// - powerpc
use crate::str;
use crate::string;
use crate::sync::Arc;
+use crate::time;
/// `Error` is a trait representing the basic expectations for error values,
/// i.e., values of type `E` in [`Result<T, E>`].
///
/// impl fmt::Display for AnError {
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f , "An error")
+ /// write!(f, "An error")
/// }
/// }
///
///
/// impl fmt::Display for AnError {
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f , "An error")
+ /// write!(f, "An error")
/// }
/// }
///
impl Error for alloc::collections::TryReserveError {}
#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for core::time::FromSecsError {}
+impl Error for time::FromSecsError {}
// Copied from `any.rs`.
impl dyn Error + 'static {
#[stable(feature = "cow_from_cstr", since = "1.28.0")]
impl<'a> From<CString> for Cow<'a, CStr> {
+ /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating.
#[inline]
fn from(s: CString) -> Cow<'a, CStr> {
Cow::Owned(s)
#[stable(feature = "cow_from_cstr", since = "1.28.0")]
impl<'a> From<&'a CStr> for Cow<'a, CStr> {
+ /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating.
#[inline]
fn from(s: &'a CStr) -> Cow<'a, CStr> {
Cow::Borrowed(s)
#[stable(feature = "cow_from_cstr", since = "1.28.0")]
impl<'a> From<&'a CString> for Cow<'a, CStr> {
+ /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating.
#[inline]
fn from(s: &'a CString) -> Cow<'a, CStr> {
Cow::Borrowed(s.as_c_str())
// Writes append to this slice
pub buffer: Vec<u8>,
- // Flush sets this flag
- pub flushed: bool,
-
// If true, writes will always be an error
pub always_write_error: bool,
if self.always_flush_error {
Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error"))
} else {
- self.flushed = true;
Ok(())
}
}
/// encountered.
///
/// This method is primarily used to interface with the
- /// [`format_args!()`] macro, but it is rare that this should
+ /// [`format_args!()`] macro, and it is rare that this should
/// explicitly be called. The [`write!()`] macro should be favored to
/// invoke this method instead.
///
/// '_inner: for j in 1..=200 {
/// println!(" inner iteration (j): {}", j);
/// if j >= 3 {
-/// // breaks from inner loop, let's outer loop continue.
+/// // breaks from inner loop, lets outer loop continue.
/// break;
/// }
/// if i >= 2 {
#![feature(atomic_mut_ptr)]
#![feature(auto_traits)]
#![feature(bench_black_box)]
+#![feature(bool_to_option)]
#![feature(box_syntax)]
#![feature(c_unwind)]
#![feature(c_variadic)]
#![feature(const_trait_impl)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
+#![feature(core_panic)]
#![feature(custom_test_frameworks)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
listener: &'a TcpListener,
}
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
+///
+/// This `struct` is created by the [`TcpListener::into_incoming`] method.
+/// See its documentation for more.
+///
+/// [`accept`]: TcpListener::accept
+#[derive(Debug)]
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+pub struct IntoIncoming {
+ listener: TcpListener,
+}
+
impl TcpStream {
/// Opens a TCP connection to a remote host.
///
Incoming { listener: self }
}
+ /// Turn this into an iterator over the connections being received on this
+ /// listener.
+ ///
+ /// The returned iterator will never return [`None`] and will also not yield
+ /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+ /// calling [`TcpListener::accept`] in a loop.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(tcplistener_into_incoming)]
+ /// use std::net::{TcpListener, TcpStream};
+ ///
+ /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> {
+ /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+ /// listener.into_incoming()
+ /// .filter_map(Result::ok) /* Ignore failed connections */
+ /// }
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// for stream in listen_on(80) {
+ /// /* handle the connection here */
+ /// }
+ /// Ok(())
+ /// }
+ /// ```
+ #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+ pub fn into_incoming(self) -> IntoIncoming {
+ IntoIncoming { listener: self }
+ }
+
/// Sets the value for the `IP_TTL` option on this socket.
///
/// This value sets the time-to-live field that is used in every packet sent
}
}
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+impl Iterator for IntoIncoming {
+ type Item = io::Result<TcpStream>;
+ fn next(&mut self) -> Option<io::Result<TcpStream>> {
+ Some(self.listener.accept().map(|p| p.0))
+ }
+}
+
impl AsInner<net_imp::TcpListener> for TcpListener {
fn as_inner(&self) -> &net_imp::TcpListener {
&self.0
-//! Linux-specific extensions to primitives in the `std::fs` module.
+//! Linux-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
#![stable(feature = "metadata_ext", since = "1.1.0")]
-//! Linux-specific extensions to primitives in the `std::process` module.
+//! Linux-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
#![unstable(feature = "linux_pidfd", issue = "82971")]
#[cfg(any(
target_arch = "x86",
target_arch = "le32",
+ target_arch = "m68k",
target_arch = "powerpc",
target_arch = "sparc",
target_arch = "arm",
// of a macro that is not vendored by Rust and included in the toolchain.
// See https://github.com/rust-analyzer/rust-analyzer/issues/6038.
+// On certain platforms right now the "main modules" modules that are
+// documented don't compile (missing things in `libc` which is empty),
+// so just omit them with an empty module and add the "unstable" attribute.
+
+// Unix, linux, wasi and windows are handled a bit differently.
#[cfg(all(
doc,
- not(any(
+ any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
- ))
+ )
))]
-#[path = "."]
-mod doc {
- // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi`
- // modules as these are the "main modules" that are used across platforms,
- // so these modules are enabled when `cfg(doc)` is set.
- // This should help show platform-specific functionality in a hopefully cross-platform
- // way in the documentation.
-
- pub mod unix;
-
- pub mod linux;
-
- pub mod wasi;
-
- pub mod windows;
-}
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod unix {}
#[cfg(all(
doc,
any(
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
-mod doc {
- // On certain platforms right now the "main modules" modules that are
- // documented don't compile (missing things in `libc` which is empty),
- // so just omit them with an empty module.
-
- #[unstable(issue = "none", feature = "std_internals")]
- pub mod unix {}
-
- #[unstable(issue = "none", feature = "std_internals")]
- pub mod linux {}
-
- #[unstable(issue = "none", feature = "std_internals")]
- pub mod wasi {}
-
- #[unstable(issue = "none", feature = "std_internals")]
- pub mod windows {}
-}
-#[cfg(doc)]
-#[stable(feature = "os", since = "1.0.0")]
-pub use doc::*;
-
-#[cfg(not(doc))]
-#[path = "."]
-mod imp {
- // If we're not documenting std then we only expose modules appropriate for the
- // current platform.
-
- #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
- pub mod fortanix_sgx;
-
- #[cfg(target_os = "hermit")]
- #[path = "hermit/mod.rs"]
- pub mod unix;
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod linux {}
+#[cfg(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod wasi {}
+#[cfg(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod windows {}
- #[cfg(target_os = "android")]
- pub mod android;
- #[cfg(target_os = "dragonfly")]
- pub mod dragonfly;
- #[cfg(target_os = "emscripten")]
- pub mod emscripten;
- #[cfg(target_os = "espidf")]
- pub mod espidf;
- #[cfg(target_os = "freebsd")]
- pub mod freebsd;
- #[cfg(target_os = "fuchsia")]
- pub mod fuchsia;
- #[cfg(target_os = "haiku")]
- pub mod haiku;
- #[cfg(target_os = "illumos")]
- pub mod illumos;
- #[cfg(target_os = "ios")]
- pub mod ios;
- #[cfg(target_os = "l4re")]
- pub mod linux;
- #[cfg(target_os = "linux")]
- pub mod linux;
- #[cfg(target_os = "macos")]
- pub mod macos;
- #[cfg(target_os = "netbsd")]
- pub mod netbsd;
- #[cfg(target_os = "openbsd")]
- pub mod openbsd;
- #[cfg(target_os = "redox")]
- pub mod redox;
- #[cfg(target_os = "solaris")]
- pub mod solaris;
- #[cfg(unix)]
- pub mod unix;
+// unix
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
+#[cfg(target_os = "hermit")]
+#[path = "hermit/mod.rs"]
+pub mod unix;
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
+#[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
+pub mod unix;
- #[cfg(target_os = "vxworks")]
- pub mod vxworks;
+// linux
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
+#[cfg(any(target_os = "linux", target_os = "l4re", doc))]
+pub mod linux;
- #[cfg(target_os = "wasi")]
- pub mod wasi;
+// wasi
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
+#[cfg(any(target_os = "wasi", doc))]
+pub mod wasi;
- #[cfg(windows)]
- pub mod windows;
-}
-#[cfg(not(doc))]
-#[stable(feature = "os", since = "1.0.0")]
-pub use imp::*;
+// windows
+#[cfg(not(all(
+ doc,
+ any(
+ all(target_arch = "wasm32", not(target_os = "wasi")),
+ all(target_vendor = "fortanix", target_env = "sgx")
+ )
+)))]
+#[cfg(any(windows, doc))]
+pub mod windows;
+
+// Others.
+#[cfg(target_os = "android")]
+pub mod android;
+#[cfg(target_os = "dragonfly")]
+pub mod dragonfly;
+#[cfg(target_os = "emscripten")]
+pub mod emscripten;
+#[cfg(target_os = "espidf")]
+pub mod espidf;
+#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
+pub mod fortanix_sgx;
+#[cfg(target_os = "freebsd")]
+pub mod freebsd;
+#[cfg(target_os = "fuchsia")]
+pub mod fuchsia;
+#[cfg(target_os = "haiku")]
+pub mod haiku;
+#[cfg(target_os = "illumos")]
+pub mod illumos;
+#[cfg(target_os = "ios")]
+pub mod ios;
+#[cfg(target_os = "macos")]
+pub mod macos;
+#[cfg(target_os = "netbsd")]
+pub mod netbsd;
+#[cfg(target_os = "openbsd")]
+pub mod openbsd;
+#[cfg(target_os = "redox")]
+pub mod redox;
+#[cfg(target_os = "solaris")]
+pub mod solaris;
+
+#[cfg(target_os = "vxworks")]
+pub mod vxworks;
#[cfg(any(unix, target_os = "wasi", doc))]
mod fd;
Equivalent to C's `char` type.
-[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long.
+[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
-//! Unix-specific extension to the primitives in the `std::ffi` module.
+//! Unix-specific extensions to primitives in the [`std::ffi`] module.
//!
//! # Examples
//!
//! let bytes = os_str.as_bytes();
//! assert_eq!(bytes, b"foo");
//! ```
+//!
+//! [`std::ffi`]: crate::ffi
#![stable(feature = "rust1", since = "1.0.0")]
-//! Unix-specific extensions to primitives in the `std::fs` module.
+//! Unix-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
#![stable(feature = "rust1", since = "1.0.0")]
use super::platform::fs::MetadataExt as _;
use crate::fs::{self, OpenOptions, Permissions};
use crate::io;
+use crate::os::unix::io::{AsFd, AsRawFd};
use crate::path::Path;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
}
}
+/// Change the owner and group of the specified path.
+///
+/// Specifying either the uid or gid as `None` will leave it unchanged.
+///
+/// Changing the owner typically requires privileges, such as root or a specific capability.
+/// Changing the group typically requires either being the owner and a member of the group, or
+/// having privileges.
+///
+/// If called on a symbolic link, this will change the owner and group of the link target. To
+/// change the owner and group of the link itself, see [`lchown`].
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+/// fs::chown("/sandbox", Some(0), Some(0))?;
+/// Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+ sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
+/// Change the owner and group of the file referenced by the specified open file descriptor.
+///
+/// For semantics and required privileges, see [`chown`].
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+/// let f = std::fs::File::open("/file")?;
+/// fs::fchown(f, Some(0), Some(0))?;
+/// Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+ sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
+/// Change the owner and group of the specified path, without dereferencing symbolic links.
+///
+/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner
+/// and group of the link itself rather than the owner and group of the link target.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+/// fs::lchown("/symlink", Some(0), Some(0))?;
+/// Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+ sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
/// Change the root directory of the current process to the specified path.
///
/// This typically requires privileges, such as root or a specific capability.
//! exposes Unix-specific functions that would otherwise be inappropriate as
//! part of the core `std` library.
//!
-//! It exposes more ways to deal with platform-specific strings (`OsStr`,
-//! `OsString`), allows to set permissions more granularly, extract low-level
+//! It exposes more ways to deal with platform-specific strings ([`OsStr`],
+//! [`OsString`]), allows to set permissions more granularly, extract low-level
//! file descriptors from files and sockets, and has platform-specific helpers
//! for spawning processes.
//!
//! Ok(())
//! }
//! ```
+//!
+//! [`OsStr`]: crate::ffi::OsStr
+//! [`OsString`]: crate::ffi::OsString
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(cfg(unix))]
-//! Unix-specific networking functionality
+//! Unix-specific networking functionality.
#![stable(feature = "unix_socket", since = "1.10.0")]
-//! Unix-specific extensions to primitives in the `std::process` module.
+//! Unix-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
#![stable(feature = "rust1", since = "1.0.0")]
-//! Unix-specific extensions to primitives in the `std::thread` module.
+//! Unix-specific extensions to primitives in the [`std::thread`] module.
+//!
+//! [`std::thread`]: crate::thread
#![stable(feature = "thread_extensions", since = "1.9.0")]
-//! WASI-specific extension to the primitives in the `std::ffi` module
+//! WASI-specific extensions to primitives in the [`std::ffi`] module
+//!
+//! [`std::ffi`]: crate::ffi
#![stable(feature = "rust1", since = "1.0.0")]
-//! WASI-specific extensions to primitives in the `std::fs` module.
+//! WASI-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
#![deny(unsafe_op_in_unsafe_fn)]
#![unstable(feature = "wasi_ext", issue = "71213")]
//! Ok(())
//! }
//! ```
+//!
+//! [`OsStr`]: crate::ffi::OsStr
+//! [`OsString`]: crate::ffi::OsString
#![stable(feature = "rust1", since = "1.0.0")]
#![deny(unsafe_op_in_unsafe_fn)]
-//! Windows-specific extensions to the primitives in the `std::ffi` module.
+//! Windows-specific extensions to primitives in the [`std::ffi`] module.
//!
//! # Overview
//!
//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16
//! [`collect`]: crate::iter::Iterator::collect
//! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
+//! [`std::ffi`]: crate::ffi
#![stable(feature = "rust1", since = "1.0.0")]
-//! Windows-specific extensions for the primitives in the `std::fs` module.
+//! Windows-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
#![stable(feature = "rust1", since = "1.0.0")]
//! the core `std` library. These extensions allow developers to use
//! `std` types and idioms with Windows in a way that the normal
//! platform-agnostic idioms would not normally support.
+//!
+//! # Examples
+//!
+//! ```no_run
+//! use std::fs::File;
+//! use std::os::windows::prelude::*;
+//!
+//! fn main() -> std::io::Result<()> {
+//! let f = File::create("foo.txt")?;
+//! let handle = f.as_raw_handle();
+//!
+//! // use handle with native windows bindings
+//!
+//! Ok(())
+//! }
+//! ```
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(cfg(windows))]
-//! Extensions to `std::process` for Windows.
+//! Windows-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
#![stable(feature = "process_extensions", since = "1.2.0")]
-//! Extensions to `std::thread` for Windows.
+//! Windows-specific extensions to primitives in the [`std::thread`] module.
+//!
+//! [`std::thread`]: crate::thread
#![stable(feature = "thread_extensions", since = "1.9.0")]
#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
-#[allow_internal_unstable(libstd_sys_internals, const_format_args)]
+#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
#[rustc_macro_transparency = "semitransparent"]
pub macro panic_2015 {
($msg:expr $(,)?) => ({
$crate::rt::begin_panic($msg)
}),
+ // Special-case the single-argument case for const_panic.
+ ("{}", $arg:expr $(,)?) => ({
+ $crate::rt::panic_display(&$arg)
+ }),
($fmt:expr, $($arg:tt)+) => ({
$crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+))
}),
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
#[doc(primitive = "bool")]
#[doc(alias = "true")]
#[doc(alias = "false")]
/// assert!(!bool_val);
/// ```
///
-/// [`true`]: keyword.true.html
-/// [`false`]: keyword.false.html
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
/// [`BitAnd`]: ops::BitAnd
/// [`BitOr`]: ops::BitOr
/// [`Not`]: ops::Not
-/// [`if`]: keyword.if.html
+/// [`if`]: ../std/keyword.if.html
///
/// # Examples
///
/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
///
/// [`u32`]: prim@u32
-/// [`exit`]: process::exit
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
///
/// # `!` and generics
///
/// because `!` coerces to `Result<!, ConnectionError>` automatically.
///
/// [`String::from_str`]: str::FromStr::from_str
-/// [`String`]: string::String
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
/// [`FromStr`]: str::FromStr
///
/// # `!` and traits
/// `impl` for this which simply panics, but the same is true for any type (we could `impl
/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
///
-/// [`File`]: fs::File
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
/// [`Debug`]: fmt::Debug
/// [`default()`]: Default::default
///
mod prim_never {}
#[doc(primitive = "char")]
-//
/// A character type.
///
/// The `char` type represents a single character. More specifically, since
/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
/// ```
///
-/// [`String`]: string/struct.String.html
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
///
/// As always, remember that a human intuition for 'character' might not map to
/// Unicode's definitions. For example, despite looking similar, the 'é'
/// [`null_mut`]: ptr::null_mut
/// [`is_null`]: pointer::is_null
/// [`offset`]: pointer::offset
-/// [`into_raw`]: Box::into_raw
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
/// [`drop`]: mem::drop
/// [`write`]: ptr::write
#[stable(feature = "rust1", since = "1.0.0")]
/// # Editions
///
/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
-/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old behavior
-/// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
-/// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old
+/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
+/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition
/// might be made consistent to the behavior of later editions.
///
/// ```rust,edition2018
/// References, both shared and mutable.
///
/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
-/// operators on a value, or by using a [`ref`](keyword.ref.html) or
-/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
+/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html)</code> pattern.
///
/// For those familiar with pointers, a reference is just a pointer that is assumed to be
/// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
-/// ([`true`](keyword.true.html)) or `0` ([`false`](keyword.false.html)), but creating a
-/// <code>&[bool]</code> that points to an allocation containing the value `3` causes
-/// undefined behaviour.
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but
+/// creating a <code>&[bool]</code> that points to an allocation containing
+/// the value `3` causes undefined behaviour.
/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
///
///
/// [`DerefMut`]: ops::DerefMut
/// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
///
/// The following traits are implemented on `&T` references if the underlying `T` also implements
/// that trait:
/// [`std::fmt`]: fmt
/// ['Pointer`]: fmt::Pointer
/// [`Hash`]: hash::Hash
-/// [`ToSocketAddrs`]: net::ToSocketAddrs
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
///
/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
/// implements that trait:
///
/// [`FusedIterator`]: iter::FusedIterator
/// [`TrustedLen`]: iter::TrustedLen
-/// [`Seek`]: io::Seek
-/// [`BufRead`]: io::BufRead
-/// [`Read`]: io::Read
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
///
/// Note that due to method call deref coercion, simply calling a trait method will act like they
/// work on references as well as they do on owned values! The implementations described here are
// Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count};
+pub use core::panicking::panic_display;
// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
argc: isize,
argv: *const *const u8,
) -> isize {
- lang_start_internal(
+ let Ok(v) = lang_start_internal(
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(),
argc,
argv,
- )
- .into_ok()
+ );
+ v
}
Ok(bytes_copied as u64)
}
+pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
+ let path = cstr(path)?;
+ cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
+ Ok(())
+}
+
+pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
+ cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?;
+ Ok(())
+}
+
+pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
+ let path = cstr(path)?;
+ cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
+ Ok(())
+}
+
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
pub fn chroot(dir: &Path) -> io::Result<()> {
let dir = cstr(dir)?;
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+pub use core::time::FromSecsError;
+
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with [`Duration`].
///
// This could be a problem for programs that call instants at intervals greater
// than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true.
let packed = (secs << 32) | nanos;
- let old = mono.load(Relaxed);
-
- if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 {
- mono.store(packed, Relaxed);
- raw
- } else {
- // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
- // passed in value and the 64bits loaded from the atomic
- let seconds_lower = old >> 32;
- let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
- if secs & 0xffff_ffff > seconds_lower {
- // Backslide caused the lower 32bit of the seconds part to wrap.
- // This must be the case because the seconds part is larger even though
- // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
- //
- // We assume that backslides are smaller than 2^32 seconds
- // which means we need to add 1 to the upper half to restore it.
- //
- // Example:
- // most recent observed time: 0xA1_0000_0000_0000_0000u128
- // bits stored in AtomicU64: 0x0000_0000_0000_0000u64
- // backslide by 1s
- // caller time is 0xA0_ffff_ffff_0000_0000u128
- // -> we can fix up the upper half time by adding 1 << 32
- seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
+ let updated = mono.fetch_update(Relaxed, Relaxed, |old| {
+ (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed)
+ });
+ match updated {
+ Ok(_) => raw,
+ Err(newer) => {
+ // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
+ // passed in value and the 64bits loaded from the atomic
+ let seconds_lower = newer >> 32;
+ let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
+ if secs & 0xffff_ffff > seconds_lower {
+ // Backslide caused the lower 32bit of the seconds part to wrap.
+ // This must be the case because the seconds part is larger even though
+ // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
+ //
+ // We assume that backslides are smaller than 2^32 seconds
+ // which means we need to add 1 to the upper half to restore it.
+ //
+ // Example:
+ // most recent observed time: 0xA1_0000_0000_0000_0000u128
+ // bits stored in AtomicU64: 0x0000_0000_0000_0000u64
+ // backslide by 1s
+ // caller time is 0xA0_ffff_ffff_0000_0000u128
+ // -> we can fix up the upper half time by adding 1 << 32
+ seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
+ }
+ let secs = seconds_upper | seconds_lower;
+ let nanos = newer as u32;
+ ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
}
- let secs = seconds_upper | seconds_lower;
- let nanos = old as u32;
- ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
}
}
}
// Because the testsuit node holds some of the information as attributes, we can't write it
// until all of the tests has ran. Instead of writting every result as they come in, we add
// them to a Vec and write them all at once when run is complete.
- let duration = exec_time.map(|t| t.0.clone()).unwrap_or_default();
+ let duration = exec_time.map(|t| t.0).unwrap_or_default();
self.results.push((desc.clone(), result.clone(), duration));
Ok(())
}
use searcher::get_dbpath_for_term;
/// A parsed terminfo database entry.
+#[allow(unused)]
#[derive(Debug)]
pub(crate) struct TermInfo {
/// Names for the terminal
[package]
name = "bootstrap"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
build = "build.rs"
[lib]
'i486': 'i686',
'i686': 'i686',
'i786': 'i686',
+ 'm68k': 'm68k',
'powerpc': 'powerpc',
'powerpc64': 'powerpc64',
'powerpc64le': 'powerpc64le',
let mut cargo = builder.cargo(
compiler,
Mode::Codegen,
- SourceType::Submodule,
+ SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
- let mut cargo =
- builder.cargo(compiler, Mode::Codegen, SourceType::Submodule, target, "build");
+ let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build");
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.krate("rustc-main").default_condition(builder.config.docs)
+ run.krate("rustc-main").path("compiler").default_condition(builder.config.docs)
}
fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
+ let mut is_explicit_request = false;
builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
- if !builder.config.compiler_docs {
+ let paths = builder
+ .paths
+ .iter()
+ .map(components_simplified)
+ .filter_map(|path| {
+ if path.get(0) == Some(&"compiler") {
+ is_explicit_request = true;
+ path.get(1).map(|p| p.to_owned())
+ } else {
+ None
+ }
+ })
+ .collect::<Vec<_>>();
+
+ if !builder.config.compiler_docs && !is_explicit_request {
builder.info("\tskipping - compiler/librustdoc docs disabled");
return;
}
cargo.rustdocflag("-Zunstable-options");
cargo.rustdocflag("-Znormalize-docs");
cargo.rustdocflag("--show-type-layout");
+ cargo.rustdocflag("--generate-link-to-definition");
compile::rustc_cargo(builder, &mut cargo, target);
+ cargo.arg("-Zunstable-options");
cargo.arg("-Zskip-rustdoc-fingerprint");
// Only include compiler crates, no dependencies of those, such as `libc`.
+ // Do link to dependencies on `docs.rs` however using `rustdoc-map`.
cargo.arg("--no-deps");
+ cargo.arg("-Zrustdoc-map");
+
+ // FIXME: `-Zrustdoc-map` does not yet correctly work for transitive dependencies,
+ // once this is no longer an issue the special case for `ena` can be removed.
+ cargo.rustdocflag("--extern-html-root-url");
+ cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
- // Find dependencies for top level crates.
let mut compiler_crates = HashSet::new();
- for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] {
- compiler_crates.extend(
- builder
- .in_tree_crates(root_crate, Some(target))
- .into_iter()
- .map(|krate| krate.name),
- );
+
+ if paths.is_empty() {
+ // Find dependencies for top level crates.
+ for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] {
+ compiler_crates.extend(
+ builder
+ .in_tree_crates(root_crate, Some(target))
+ .into_iter()
+ .map(|krate| krate.name),
+ );
+ }
+ } else {
+ for root_crate in paths {
+ if !builder.src.join("compiler").join(&root_crate).exists() {
+ builder.info(&format!(
+ "\tskipping - compiler/{} (unknown compiler crate)",
+ root_crate
+ ));
+ } else {
+ compiler_crates.extend(
+ builder
+ .in_tree_crates(root_crate, Some(target))
+ .into_iter()
+ .map(|krate| krate.name),
+ );
+ }
+ }
}
+ let mut to_open = None;
for krate in &compiler_crates {
// Create all crate output directories first to make sure rustdoc uses
// relative links.
// FIXME: Cargo should probably do this itself.
t!(fs::create_dir_all(out_dir.join(krate)));
cargo.arg("-p").arg(krate);
+ if to_open.is_none() {
+ to_open = Some(krate);
+ }
}
builder.run(&mut cargo.into());
+ // Let's open the first crate documentation page:
+ if let Some(krate) = to_open {
+ let index = out.join(krate).join("index.html");
+ open(builder, &index);
+ }
}
}
{
eprintln!(
"
-Couldn't find required command: ninja
-You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
+Couldn't find required command: ninja (or ninja-build)
+
+You should install ninja as described at
+<https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages>,
+or set `ninja = false` in the `[llvm]` section of `config.toml`.
+Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
+to download LLVM rather than building it.
"
);
std::process::exit(1);
let llvm_exp_targets = match builder.config.llvm_experimental_targets {
Some(ref s) => s,
- None => "AVR",
+ None => "AVR;M68k",
};
let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
host,
"test",
"src/tools/rustfmt",
- SourceType::Submodule,
+ SourceType::InTree,
&[],
);
.env("RUSTDOC", builder.rustdoc(self.compiler))
.env("RUSTC", builder.rustc(self.compiler))
.current_dir(path);
+ // FIXME: implement a `// compile-flags` command or similar
+ // instead of hard-coding this test
+ if entry.file_name() == "link_to_definition" {
+ cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
+ }
builder.run(&mut cargo);
}
}
[package]
name = "build_helper"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
--- /dev/null
+FROM ubuntu:20.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++ \
+ make \
+ file \
+ curl \
+ ca-certificates \
+ python2.7 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ xz-utils \
+ g++-m68k-linux-gnu \
+ libssl-dev \
+ pkg-config
+
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV HOSTS=m68k-unknown-linux-gnu
+
+ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
SCRIPT: python x.py dist
# RLS does not build for aarch64-pc-windows-msvc. See rust-lang/rls#1693
DIST_REQUIRE_ALL_TOOLS: 0
+ # Hack around this SDK version, because it doesn't work with clang.
+ # See https://github.com/rust-lang/rust/issues/88796
+ WINDOWS_SDK_20348_HACK: 1
<<: *job-windows-xl
- name: dist-i686-mingw
# `clang-ar` by accident.
ciCommandSetEnv AR "ar"
elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
+
+ if [[ ${WINDOWS_SDK_20348_HACK-0} -eq 1 ]]; then
+ rm -rf '/c/Program Files (x86)/Windows Kits/10/include/10.0.20348.0'
+ mv '/c/Program Files (x86)/Windows Kits/10/include/'10.0.{19041,20348}.0
+ fi
+
# If we're compiling for MSVC then we, like most other distribution builders,
# switch to clang as the compiler. This'll allow us eventually to enable LTO
# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
exit 0
fi
- echo 'git: unshallowing the repository so we can check commits'
- git fetch \
- --no-tags \
- --no-recurse-submodules \
- --progress \
- --prune \
- --unshallow
-
if [[ $ci_base_branch == "beta" ]]; then
verify_cherries master "$BETA_LIMIT" \
|| exit 1
-Subproject commit c3a51e23859554369e6bbb5128dcef0e4f159fb5
+Subproject commit 4c76da9ddb4650203c129fceffdea95a3466c205
-Subproject commit 04f489c889235fe3b6dfe678ae5410d07deda958
+Subproject commit 9d4132b56c4999cd3ce1aeca5f1b2f2cb0d11c24
-Subproject commit 95f1acf9a39d6f402f654e917e2c1dfdb779c5fc
+Subproject commit 9198465b6ca8bed669df0cbb67c0e6d0b140803c
`armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
`armv6-unknown-netbsd-eabihf` | ? | |
+`armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
`i686-uwp-windows-gnu` | ? | |
`i686-uwp-windows-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
+`m68k-unknown-linux-gnu` | ? | | Motorola 680x0 Linux
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
--- /dev/null
+# m68k-unknown-linux-gnu
+
+**Tier: 3**
+
+Motorola 680x0 Linux
+
+## Designated Developers
+
+* [@glaubitz](https://github.com/glaubitz)
+* [@ricky26](https://github.com/ricky26)
+
+## Requirements
+
+This target requires a Linux/m68k build environment for cross-compilation which
+is available on Debian and Debian-based systems, openSUSE and other distributions.
+
+On Debian, it should be sufficient to install a g++ cross-compiler for the m68k
+architecture which will automatically pull in additional dependencies such as
+the glibc cross development package:
+
+```text
+# apt install g++-m68k-linux-gnu
+```
+
+Binaries can be run using QEMU user emulation. On Debian-based systems, it should be
+sufficient to install the package `qemu-user-static` to be able to run simple static
+binaries:
+
+```text
+# apt install qemu-user-static
+```
+
+To run more complex programs, it will be necessary to set up a Debian/m68k chroot with
+the help of the command `debootstrap`:
+
+```text
+# apt install debootstrap debian-ports-archive-keyring
+# debootstrap --keyring=/usr/share/keyrings/debian-ports-archive-keyring.gpg --arch=m68k unstable debian-68k http://ftp.ports.debian.org/debian-ports
+```
+
+This chroot can then seamlessly entered using the normal `chroot` command thanks to
+QEMU user emulation:
+
+```text
+# chroot /path/to/debian-68k
+```
+
+To get started with native builds, which are currently untested, a native Debian/m68k
+system can be installed either on real hardware such as 68k-based Commodore Amiga or
+Atari systems or emulated environments such as QEMU version 4.2 or newer or ARAnyM.
+
+ISO images for installation are provided by the Debian Ports team and can be obtained
+from the Debian CD image server available at:
+
+[https://cdimage.debian.org/cdimage/ports/current](https://cdimage.debian.org/cdimage/ports/current/)
+
+Documentation for Debian/m68k is available on the Debian Wiki at:
+
+[https://wiki.debian.org/M68k](https://wiki.debian.org/M68k)
+
+Support is available either through the `debian-68k` mailing list:
+
+[https://lists.debian.org/debian-68k/](https://lists.debian.org/debian-68k/)
+
+or the `#debian-68k` IRC channel on OFTC network.
+
+## Building
+
+The codegen for this target should be built by default. However, core and std
+are currently missing but are being worked on and should become available in
+the near future.
+
+## Cross-compilation
+
+This target can be cross-compiled from a standard Debian or Debian-based, openSUSE or any
+other distribution which has a basic m68k cross-toolchain available.
+
+## Testing
+
+Currently there is no support to run the rustc test suite for this target.
+
+## Building Rust programs
+
+Rust programs can be built for that target:
+
+```text
+rustc --target m68k-unknown-linux-gnu your-code.rs
+```
+
+Very simple progams can be run using the `qemu-m68k-static` program:
+
+```text
+$ qemu-m68k-static your-code
+```
+
+For more complex applications, a chroot or native (emulated) Debian/m68k system are required
+for testing.
specially cache them. This flag will rename all these files in the output to include the suffix in
the filename. For example, `light.css` would become `light-suf.css` with the above command.
-### `--display-warnings`: display warnings when documenting or running documentation tests
+### `--display-doctest-warnings`: display warnings when documenting or running documentation tests
Using this flag looks like this:
```bash
-$ rustdoc src/lib.rs -Z unstable-options --display-warnings
-$ rustdoc --test src/lib.rs -Z unstable-options --display-warnings
+$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings
+$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings
```
The intent behind this flag is to allow the user to see warnings that occur within their library or
--- /dev/null
+# `remap-cwd-prefix`
+
+The tracking issue for this feature is: [#87325](https://github.com/rust-lang/rust/issues/87325).
+
+------------------------
+
+This flag will rewrite absolute paths under the current working directory,
+replacing the current working directory prefix with a specified value.
+
+The given value may be absolute or relative, or empty. This switch takes
+precidence over `--remap-path-prefix` in case they would both match a given
+path.
+
+This flag helps to produce deterministic output, by removing the current working
+directory from build output, while allowing the command line to be universally
+reproducible, such that the same execution will work on all machines, regardless
+of build environment.
+
+## Example
+```sh
+# This would produce an absolute path to main.rs in build outputs of
+# "./main.rs".
+rustc -Z remap-cwd-prefix=. main.rs
+```
As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
-Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `option(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
+Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
```rust,allow_fail
#![feature(asm)]
| Architecture | ABI name | Clobbered registers |
| ------------ | -------- | ------------------- |
-| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
+| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
| AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` |
| ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` |
| RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` |
[package]
name = "test-float-parse"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
publish = false
[workspace]
[package]
name = "rustdoc"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
let param_env = self.cx.tcx.param_env(item_def_id);
let ty = self.cx.tcx.type_of(item_def_id);
- debug!("get_blanket_impls({:?})", ty);
+ trace!("get_blanket_impls({:?})", ty);
let mut impls = Vec::new();
for &trait_def_id in self.cx.tcx.all_traits(()).iter() {
if !self.cx.cache.access_levels.is_public(trait_def_id)
// NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id);
for &impl_def_id in trait_impls.blanket_impls() {
- debug!(
+ trace!(
"get_blanket_impls: Considering impl for trait '{:?}' {:?}",
- trait_def_id, impl_def_id
+ trait_def_id,
+ impl_def_id
);
let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap();
let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_));
// FIXME(eddyb) ignoring `obligations` might cause false positives.
drop(obligations);
- debug!(
+ trace!(
"invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
- param_env, trait_ref, ty
+ param_env,
+ trait_ref,
+ ty
);
let predicates = self
.cx
"aarch64" => "AArch64",
"arm" => "ARM",
"asmjs" => "JavaScript",
+ "m68k" => "M68k",
"mips" => "MIPS",
"mips64" => "MIPS-64",
"msp430" => "MSP430",
}
let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
- debug!("merged_attrs={:?}", merged_attrs);
+ trace!("merged_attrs={:?}", merged_attrs);
- debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
+ trace!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
ret.push(clean::Item::from_def_id_and_attrs_and_parts(
did,
None,
// visit each node at most once.
for &item in cx.tcx.item_children(did).iter() {
if item.vis == ty::Visibility::Public {
- if let Some(def_id) = item.res.mod_def_id() {
+ let res = item.res.expect_non_local();
+ if let Some(def_id) = res.mod_def_id() {
if did == def_id || !visited.insert(def_id) {
continue;
}
}
- if let Res::PrimTy(p) = item.res {
+ if let Res::PrimTy(p) = res {
// Primitive types can't be inlined so generate an import instead.
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
clean::ImportSource {
path: clean::Path {
global: false,
- res: item.res,
+ res,
segments: vec![clean::PathSegment {
name: prim_ty.as_sym(),
args: clean::GenericArgs::AngleBracketed {
))),
cfg: None,
});
- } else if let Some(i) =
- try_inline(cx, did, None, item.res, item.ident.name, None, visited)
- {
+ } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
items.extend(i)
}
}
name: Symbol,
import_def_id: Option<DefId>,
) -> clean::ItemKind {
- let imported_from = cx.tcx.crate_name(def_id.krate);
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) {
LoadedMacro::MacroDef(item_def, _) => {
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
def_id,
cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
),
- imported_from: Some(imported_from),
})
} else {
unreachable!()
);
}
inline::record_extern_fqn(cx, trait_ref.def_id, kind);
- let path = external_path(
- cx,
- cx.tcx.item_name(trait_ref.def_id),
- Some(trait_ref.def_id),
- true,
- bounds.to_vec(),
- trait_ref.substs,
- );
+ let path = external_path(cx, trait_ref.def_id, true, bounds.to_vec(), trait_ref.substs);
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
impl Clean<Type> for hir::TraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
let path = self.path.clean(cx);
- resolve_type(cx, path, self.hir_ref_id)
+ resolve_type(cx, path)
}
}
fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
use rustc_hir::GenericParamCount;
- let hir::Ty { hir_id, span, ref kind } = *hir_ty;
+ let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
let qpath = match kind {
hir::TyKind::Path(qpath) => qpath,
_ => unreachable!(),
return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
}
let path = path.clean(cx);
- resolve_type(cx, path, hir_id)
+ resolve_type(cx, path)
}
hir::QPath::Resolved(Some(ref qself), ref p) => {
// Try to normalize `<X as Y>::T` to a type
name: p.segments.last().expect("segments were empty").ident.name,
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
self_type: Box::new(qself.clean(cx)),
- trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+ trait_: Box::new(resolve_type(cx, trait_path)),
}
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
name: segment.ident.name,
self_def_id: res.opt_def_id(),
self_type: Box::new(qself.clean(cx)),
- trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+ trait_: Box::new(resolve_type(cx, trait_path)),
}
}
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
impl<'tcx> Clean<Type> for Ty<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
- debug!("cleaning type: {:?}", self);
+ trace!("cleaning type: {:?}", self);
let ty = normalize(cx, self).unwrap_or(self);
match *ty.kind() {
ty::Never => Never,
AdtKind::Enum => ItemType::Enum,
};
inline::record_extern_fqn(cx, did, kind);
- let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
+ let path = external_path(cx, did, false, vec![], substs);
ResolvedPath { path, did, is_generic: false }
}
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
- let path = external_path(
- cx,
- cx.tcx.item_name(did),
- None,
- false,
- vec![],
- InternalSubsts::empty(),
- );
+ let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
ResolvedPath { path, did, is_generic: false }
}
ty::Dynamic(ref obj, ref reg) => {
for did in dids {
let empty = cx.tcx.intern_substs(&[]);
- let path =
- external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+ let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
let bound = PolyTrait {
trait_: ResolvedPath { path, did, is_generic: false },
});
}
- let path =
- external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
+ let path = external_path(cx, did, false, bindings, substs);
bounds.insert(
0,
PolyTrait {
}
ItemKind::Macro(ref macro_def) => MacroItem(Macro {
source: display_macro_source(cx, name, ¯o_def, def_id, &item.vis),
- imported_from: None,
}),
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
let items = item_ids
crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
let root = self.def_id();
- let as_keyword = |res: Res| {
+ let as_keyword = |res: Res<!>| {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = tcx.get_attrs(def_id);
let mut keyword = None;
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
- as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
+ as_keyword(path.res.expect_non_local())
+ .map(|(_, prim)| (id.def_id.to_def_id(), prim))
}
_ => None,
}
// Also note that this does not attempt to deal with modules tagged
// duplicately for the same primitive. This is handled later on when
// rendering by delegating everything to a hash map.
- let as_primitive = |res: Res| {
+ let as_primitive = |res: Res<!>| {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = tcx.get_attrs(def_id);
let mut prim = None;
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
- as_primitive(path.res).map(|(_, prim)| {
+ as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
// Pretend the primitive is local.
(id.def_id.to_def_id(), prim)
})
.map_or(&[][..], |v| v.as_slice())
.iter()
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
- match did {
- Some(did) => {
- if let Ok((mut href, ..)) = href(did.clone(), cx) {
- if let Some(ref fragment) = *fragment {
- href.push('#');
- href.push_str(fragment);
- }
- Some(RenderedLink {
- original_text: s.clone(),
- new_text: link_text.clone(),
- href,
- })
- } else {
- None
- }
- }
- // FIXME(83083): using fragments as a side-channel for
- // primitive names is very unfortunate
- None => {
- let relative_to = &cx.current;
- if let Some(ref fragment) = *fragment {
- let url = match cx.cache().extern_locations.get(&self.def_id.krate()) {
- Some(&ExternalLocation::Local) => {
- if relative_to[0] == "std" {
- let depth = relative_to.len() - 1;
- "../".repeat(depth)
- } else {
- let depth = relative_to.len();
- format!("{}std/", "../".repeat(depth))
- }
- }
- Some(ExternalLocation::Remote(ref s)) => {
- format!("{}/std/", s.trim_end_matches('/'))
- }
- Some(ExternalLocation::Unknown) | None => {
- format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
- }
- };
- // This is a primitive so the url is done "by hand".
- let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
- Some(RenderedLink {
- original_text: s.clone(),
- new_text: link_text.clone(),
- href: format!(
- "{}primitive.{}.html{}",
- url,
- &fragment[..tail],
- &fragment[tail..]
- ),
- })
- } else {
- panic!("This isn't a primitive?!");
- }
+ debug!(?did);
+ if let Ok((mut href, ..)) = href(*did, cx) {
+ debug!(?href);
+ if let Some(ref fragment) = *fragment {
+ href.push('#');
+ href.push_str(fragment);
}
+ Some(RenderedLink {
+ original_text: s.clone(),
+ new_text: link_text.clone(),
+ href,
+ })
+ } else {
+ None
}
})
.collect()
.get(&self.def_id)
.map_or(&[][..], |v| v.as_slice())
.iter()
- .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
- // FIXME(83083): using fragments as a side-channel for
- // primitive names is very unfortunate
- if did.is_some() || fragment.is_some() {
- Some(RenderedLink {
- original_text: s.clone(),
- new_text: link_text.clone(),
- href: String::new(),
- })
- } else {
- None
- }
+ .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
+ original_text: s.clone(),
+ new_text: link_text.clone(),
+ href: String::new(),
})
.collect()
}
crate other_attrs: Vec<ast::Attribute>,
}
-#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// A link that has not yet been rendered.
///
/// This link will be turned into a rendered link by [`Item::links`].
/// This may not be the same as `link` if there was a disambiguator
/// in an intra-doc link (e.g. \[`fn@f`\])
pub(crate) link_text: String,
- pub(crate) did: Option<DefId>,
+ pub(crate) did: DefId,
/// The url fragment to append to the link
pub(crate) fragment: Option<String>,
}
crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
let empty = cx.tcx.intern_substs(&[]);
- let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+ let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
PolyTrait {
Never => sym::never,
}
}
+
+ /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
+ /// Panics if there is no such module.
+ ///
+ /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
+ /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
+ /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
+ /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
+ crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
+ static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
+ PRIMITIVE_LOCATIONS.get_or_init(|| {
+ let mut primitive_locations = FxHashMap::default();
+ // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
+ // This is a degenerate case that I don't plan to support.
+ for &crate_num in tcx.crates(()) {
+ let e = ExternalCrate { crate_num };
+ let crate_name = e.name(tcx);
+ debug!(?crate_num, ?crate_name);
+ for &(def_id, prim) in &e.primitives(tcx) {
+ // HACK: try to link to std instead where possible
+ if crate_name == sym::core && primitive_locations.contains_key(&prim) {
+ continue;
+ }
+ primitive_locations.insert(prim, def_id);
+ }
+ }
+ let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
+ for (def_id, prim) in local_primitives {
+ primitive_locations.insert(prim, def_id);
+ }
+ primitive_locations
+ })
+ }
}
impl From<ast::IntTy> for PrimitiveType {
#[derive(Clone, Debug)]
crate struct Macro {
crate source: String,
- crate imported_from: Option<Symbol>,
}
#[derive(Clone, Debug)]
let krate = cx.tcx.hir().krate();
let module = crate::visit_ast::RustdocVisitor::new(cx).visit(krate);
- cx.cache.deref_trait_did = cx.tcx.lang_items().deref_trait();
- cx.cache.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
- cx.cache.owned_box_did = cx.tcx.lang_items().owned_box();
-
let mut externs = Vec::new();
for &cnum in cx.tcx.crates(()).iter() {
externs.push(ExternalCrate { crate_num: cnum });
fn external_generic_args(
cx: &mut DocContext<'_>,
- trait_did: Option<DefId>,
+ did: DefId,
has_self: bool,
bindings: Vec<TypeBinding>,
substs: SubstsRef<'_>,
})
.collect();
- match trait_did {
- // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
- Some(did) if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() => {
- assert!(ty_kind.is_some());
- let inputs = match ty_kind {
- Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
- _ => return GenericArgs::AngleBracketed { args, bindings },
- };
- let output = None;
- // FIXME(#20299) return type comes from a projection now
- // match types[1].kind {
- // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
- // _ => Some(types[1].clean(cx))
- // };
- GenericArgs::Parenthesized { inputs, output }
- }
- _ => GenericArgs::AngleBracketed { args, bindings },
+ if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
+ let inputs = match ty_kind.unwrap() {
+ ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
+ _ => return GenericArgs::AngleBracketed { args, bindings },
+ };
+ let output = None;
+ // FIXME(#20299) return type comes from a projection now
+ // match types[1].kind {
+ // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
+ // _ => Some(types[1].clean(cx))
+ // };
+ GenericArgs::Parenthesized { inputs, output }
+ } else {
+ GenericArgs::AngleBracketed { args, bindings }
}
}
-// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
-// from Fn<(A, B,), C> to Fn(A, B) -> C
pub(super) fn external_path(
cx: &mut DocContext<'_>,
- name: Symbol,
- trait_did: Option<DefId>,
+ did: DefId,
has_self: bool,
bindings: Vec<TypeBinding>,
substs: SubstsRef<'_>,
) -> Path {
+ let def_kind = cx.tcx.def_kind(did);
+ let name = cx.tcx.item_name(did);
Path {
global: false,
- res: Res::Err,
+ res: Res::Def(def_kind, did),
segments: vec![PathSegment {
name,
- args: external_generic_args(cx, trait_did, has_self, bindings, substs),
+ args: external_generic_args(cx, did, has_self, bindings, substs),
}],
}
}
}
/// Given a type Path, resolve it to a Type using the TyCtxt
-crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Type {
- debug!("resolve_type({:?},{:?})", path, id);
+crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
+ debug!("resolve_type({:?})", path);
let is_generic = match path.res {
Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)),
return Generic(kw::SelfUpper);
}
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
- return Generic(Symbol::intern(&path.whole_name()));
+ return Generic(path.segments[0].name);
}
Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
_ => false,
crate manual_passes: Vec<String>,
/// Whether to display warnings during doc generation or while gathering doctests. By default,
/// all non-rustdoc-specific lints are allowed when generating docs.
- crate display_warnings: bool,
+ crate display_doctest_warnings: bool,
/// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
/// with and without documentation.
crate show_coverage: bool,
.field("persist_doctests", &self.persist_doctests)
.field("default_passes", &self.default_passes)
.field("manual_passes", &self.manual_passes)
- .field("display_warnings", &self.display_warnings)
+ .field("display_doctest_warnings", &self.display_doctest_warnings)
.field("show_coverage", &self.show_coverage)
.field("crate_version", &self.crate_version)
.field("render_options", &self.render_options)
let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
let playground_url = matches.opt_str("playground-url");
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
- let display_warnings = matches.opt_present("display-warnings");
+ let display_doctest_warnings = matches.opt_present("display-doctest-warnings");
let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
let enable_minification = !matches.opt_present("disable-minification");
test_args,
default_passes,
manual_passes,
- display_warnings,
+ display_doctest_warnings,
show_coverage,
crate_version,
test_run_directory,
lint_opts,
describe_lints,
lint_cap,
- display_warnings,
..
}: RustdocOptions,
) -> rustc_interface::Config {
maybe_sysroot,
search_paths: libs,
crate_types,
- lint_opts: if !display_warnings { lint_opts } else { vec![] },
+ lint_opts,
lint_cap,
cg: codegen_options,
externs,
// NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
tcx.sess.time("item_types_checking", || {
- for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_item_types(module);
- }
+ tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
tcx.sess.abort_if_errors();
tcx.sess.time("missing_docs", || {
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
});
tcx.sess.time("check_mod_attrs", || {
- for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_attrs(module);
- }
+ tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
});
rustc_passes::stability::check_unused_or_stable_features(tcx);
use std::fs;
use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::string::ToString;
use std::sync::mpsc::Sender;
fs::create_dir_all(path)
}
- crate fn write<P, C, E>(&self, path: P, contents: C) -> Result<(), E>
+ crate fn write<E>(
+ &self,
+ path: PathBuf,
+ contents: impl 'static + Send + AsRef<[u8]>,
+ ) -> Result<(), E>
where
- P: AsRef<Path>,
- C: AsRef<[u8]>,
E: PathError,
{
if !self.sync_only && cfg!(windows) {
// A possible future enhancement after more detailed profiling would
// be to create the file sync so errors are reported eagerly.
- let path = path.as_ref().to_path_buf();
- let contents = contents.as_ref().to_vec();
let sender = self.errors.clone().expect("can't write after closing");
rayon::spawn(move || {
fs::write(&path, contents).unwrap_or_else(|e| {
crate no_crate_inject: bool,
/// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
/// the default `#![allow(unused)]`.
- crate display_warnings: bool,
+ crate display_doctest_warnings: bool,
/// Additional crate-level attributes to add to doctests.
crate attrs: Vec<String>,
}
maybe_sysroot: options.maybe_sysroot.clone(),
search_paths: options.libs.clone(),
crate_types,
- lint_opts: if !options.display_warnings { lint_opts } else { vec![] },
- lint_cap: Some(options.lint_cap.clone().unwrap_or_else(|| lint::Forbid)),
+ lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
+ lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)),
cg: options.codegen_options.clone(),
externs: options.externs.clone(),
unstable_features: options.render_options.unstable_features,
};
let test_args = options.test_args.clone();
- let display_warnings = options.display_warnings;
+ let display_doctest_warnings = options.display_doctest_warnings;
let nocapture = options.nocapture;
let externs = options.externs.clone();
let json_unused_externs = options.json_unused_externs;
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let mut opts = scrape_test_config(crate_attrs);
- opts.display_warnings |= options.display_warnings;
+ opts.display_doctest_warnings |= options.display_doctest_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
tcx.crate_name(LOCAL_CRATE),
Err(ErrorReported) => return Err(ErrorReported),
};
- run_tests(test_args, nocapture, display_warnings, tests);
+ run_tests(test_args, nocapture, display_doctest_warnings, tests);
// Collect and warn about unused externs, but only if we've gotten
// reports for each doctest
crate fn run_tests(
mut test_args: Vec<String>,
nocapture: bool,
- display_warnings: bool,
+ display_doctest_warnings: bool,
tests: Vec<test::TestDescAndFn>,
) {
test_args.insert(0, "rustdoctest".to_string());
if nocapture {
test_args.push("--nocapture".to_string());
}
- test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+ test::test_main(
+ &test_args,
+ tests,
+ Some(test::Options::new().display_output(display_doctest_warnings)),
+ );
}
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
use rustc_ast_pretty::pprust;
let mut opts =
- TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
+ TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() };
let test_attrs: Vec<_> = attrs
.iter()
let mut prog = String::new();
let mut supports_color = false;
- if opts.attrs.is_empty() && !opts.display_warnings {
+ if opts.attrs.is_empty() && !opts.display_doctest_warnings {
// If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
// lints that are commonly triggered in doctests. The crate-level test attributes are
// commonly used to make tests fail in case they trigger warnings, so having this there in
fn make_test_no_crate_inject() {
// Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
// adding it anyway.
- let opts = TestOptions { no_crate_inject: true, display_warnings: false, attrs: vec![] };
+ let opts =
+ TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] };
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
}
#[test]
-fn make_test_display_warnings() {
+fn make_test_display_doctest_warnings() {
// If the user is asking to display doctest warnings, suppress the default `allow(unused)`.
let mut opts = TestOptions::default();
- opts.display_warnings = true;
+ opts.display_doctest_warnings = true;
let input = "assert_eq!(2+2, 4);";
let expected = "fn main() {
assert_eq!(2+2, 4);
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
-use crate::clean::{self, GetDefId, ItemId};
+use crate::clean::{self, GetDefId, ItemId, PrimitiveType};
use crate::config::RenderOptions;
use crate::fold::DocFolder;
use crate::formats::item_type::ItemType;
stripped_mod: bool,
crate search_index: Vec<IndexItem>,
- crate deref_trait_did: Option<DefId>,
- crate deref_mut_trait_did: Option<DefId>,
- crate owned_box_did: Option<DefId>,
// In rare case where a structure is defined in one module but implemented
// in another, if the implementing module is parsed before defining module,
self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
}
- // Cache where all known primitives have their documentation located.
- //
- // Favor linking to as local extern as possible, so iterate all crates in
- // reverse topological order.
- for &e in krate.externs.iter().rev() {
- for &(def_id, prim) in &e.primitives(tcx) {
- self.primitive_locations.insert(prim, def_id);
- }
- }
- for &(def_id, prim) in &krate.primitives {
- self.primitive_locations.insert(prim, def_id);
+ // FIXME: avoid this clone (requires implementing Default manually)
+ self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone();
+ for (prim, &def_id) in &self.primitive_locations {
+ let crate_name = tcx.crate_name(def_id.krate);
+ // Recall that we only allow primitive modules to be at the root-level of the crate.
+ // If that restriction is ever lifted, this will have to include the relative paths instead.
+ self.external_paths.insert(
+ def_id,
+ (vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive),
+ );
}
krate = CacheBuilder { tcx, cache: self }.fold_crate(krate);
if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
}
- if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
+ if !did.is_local()
+ && !cache.access_levels.is_public(did)
+ && !cache.document_private
+ && !cache.primitive_locations.values().any(|&id| id == did)
+ {
return Err(HrefError::Private);
}
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
Some(&(ref fqp, shortty)) => (fqp, shortty, {
let module_fqp = to_module_fqp(shortty, fqp);
+ debug!(?fqp, ?shortty, ?module_fqp);
href_relative_parts(module_fqp, relative_to)
}),
None => {
url_parts.insert(0, root);
}
}
+ debug!(?url_parts);
let last = &fqp.last().unwrap()[..];
let filename;
match shortty {
use_absolute: bool,
cx: &'cx Context<'_>,
) -> fmt::Result {
- debug!("fmt_type(t = {:?})", t);
+ trace!("fmt_type(t = {:?})", t);
match *t {
clean::Generic(name) => write!(f, "{}", name),
//!
//! Use the `render_with_highlighting` to highlight some rust code.
+use crate::clean::PrimitiveType;
use crate::html::escape::Escape;
use crate::html::render::Context;
.ok()
.map(|(url, _, _)| url)
}
+ LinkFromSrc::Primitive(prim) => format::href_with_root_path(
+ PrimitiveType::primitive_locations(context.tcx())[&prim],
+ context,
+ Some(context_info.root_path),
+ )
+ .ok()
+ .map(|(url, _, _)| url),
}
})
{
mod tests;
/// Options for rendering Markdown in the main body of documentation.
-pub(crate) fn opts() -> Options {
+pub(crate) fn main_body_opts() -> Options {
Options::ENABLE_TABLES
| Options::ENABLE_FOOTNOTES
| Options::ENABLE_STRIKETHROUGH
| Options::ENABLE_SMART_PUNCTUATION
}
-/// A subset of [`opts()`] used for rendering summaries.
+/// Options for rendering Markdown in summaries (e.g., in search results).
pub(crate) fn summary_opts() -> Options {
- Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES
+ Options::ENABLE_TABLES
+ | Options::ENABLE_FOOTNOTES
+ | Options::ENABLE_STRIKETHROUGH
+ | Options::ENABLE_TASKLISTS
+ | Options::ENABLE_SMART_PUNCTUATION
}
/// When `to_string` is called, this struct will emit the HTML corresponding to
}
}
+/// Wrap HTML tables into `<div>` to prevent having the doc blocks width being too big.
+struct TableWrapper<'a, I: Iterator<Item = Event<'a>>> {
+ inner: I,
+ stored_events: VecDeque<Event<'a>>,
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> TableWrapper<'a, I> {
+ fn new(iter: I) -> Self {
+ Self { inner: iter, stored_events: VecDeque::new() }
+ }
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> Iterator for TableWrapper<'a, I> {
+ type Item = Event<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(first) = self.stored_events.pop_front() {
+ return Some(first);
+ }
+
+ let event = self.inner.next()?;
+
+ Some(match event {
+ Event::Start(Tag::Table(t)) => {
+ self.stored_events.push_back(Event::Start(Tag::Table(t)));
+ Event::Html(CowStr::Borrowed("<div>"))
+ }
+ Event::End(Tag::Table(t)) => {
+ self.stored_events.push_back(Event::Html(CowStr::Borrowed("</div>")));
+ Event::End(Tag::Table(t))
+ }
+ e => e,
+ })
+ }
+}
+
type SpannedEvent<'a> = (Event<'a>, Range<usize>);
/// Make headings links with anchor IDs and build up TOC.
}
};
- let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+ let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
let p = p.into_offset_iter();
let mut s = String::with_capacity(md.len() * 3 / 2);
let p = HeadingLinks::new(p, None, &mut ids);
let p = Footnotes::new(p);
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+ let p = TableWrapper::new(p);
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
crate fn into_string(self) -> String {
let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
- let p = Parser::new_ext(md, opts()).into_offset_iter();
+ let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
let mut s = String::with_capacity(md.len() * 3 / 2);
{
let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
let p = Footnotes::new(p);
- let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+ let p = TableWrapper::new(p.map(|(ev, _)| ev));
+ let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
}
if md.is_empty() {
return String::new();
}
- let p = Parser::new_ext(md, opts()).into_offset_iter();
+ let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
// Treat inline HTML as plain text.
let p = p.map(|event| match event.0 {
let p = HeadingLinks::new(p, None, &mut ids);
let p = Footnotes::new(p);
- let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+ let p = TableWrapper::new(p.map(|(ev, _)| ev));
+ let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
s
}
};
- let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+ let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
let mut p = LinkReplacer::new(p, link_names);
let mut buf = HtmlWithLimit::new(length_limit);
});
None
};
- let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter();
+ let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push))
+ .into_offset_iter();
// There's no need to thread an IdMap through to here because
// the IDs generated aren't going to be emitted anywhere.
return code_blocks;
}
- let mut p = Parser::new_ext(md, opts()).into_offset_iter();
+ let mut p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
while let Some((event, offset)) = p.next() {
if let Event::Start(Tag::CodeBlock(syntax)) = event {
}
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 104);
/// Shared mutable state used in [`Context`] and elsewhere.
|buf: &mut Buffer| all.print(buf),
&self.shared.style_files,
);
- self.shared.fs.write(final_file, v.as_bytes())?;
+ self.shared.fs.write(final_file, v)?;
// Generating settings page.
page.title = "Rustdoc settings";
)?,
&style_files,
);
- self.shared.fs.write(&settings_file, v.as_bytes())?;
+ self.shared.fs.write(settings_file, v)?;
if let Some(ref redirections) = self.shared.redirections {
if !redirections.borrow().is_empty() {
let redirect_map_path =
self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
- self.shared.fs.write(&redirect_map_path, paths.as_bytes())?;
+ self.shared.fs.write(redirect_map_path, paths)?;
}
}
if !buf.is_empty() {
self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join("index.html");
- scx.fs.write(&joint_dst, buf.as_bytes())?;
+ scx.fs.write(joint_dst, buf)?;
}
// Render sidebar-items.js used throughout this module.
let items = self.build_sidebar_items(module);
let js_dst = self.dst.join("sidebar-items.js");
let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
- scx.fs.write(&js_dst, &v)?;
+ scx.fs.write(js_dst, v)?;
}
Ok(())
}
let file_name = &item_path(item_type, &name.as_str());
self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join(file_name);
- self.shared.fs.write(&joint_dst, buf.as_bytes())?;
+ self.shared.fs.write(joint_dst, buf)?;
if !self.render_redirect_pages {
self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
} else {
let v = layout::redirect(file_name);
let redir_dst = self.dst.join(redir_name);
- self.shared.fs.write(&redir_dst, v.as_bytes())?;
+ self.shared.fs.write(redir_dst, v)?;
}
}
}
use rustc_hir::def_id::DefId;
use rustc_hir::Mutability;
use rustc_middle::middle::stability;
+use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{kw, sym, Symbol};
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
opaque_tys: FxHashSet<ItemEntry>,
statics: FxHashSet<ItemEntry>,
constants: FxHashSet<ItemEntry>,
- keywords: FxHashSet<ItemEntry>,
attributes: FxHashSet<ItemEntry>,
derives: FxHashSet<ItemEntry>,
trait_aliases: FxHashSet<ItemEntry>,
opaque_tys: new_set(100),
statics: new_set(100),
constants: new_set(100),
- keywords: new_set(100),
attributes: new_set(100),
derives: new_set(100),
trait_aliases: new_set(100),
return;
}
if !traits.is_empty() {
- let deref_impl = traits
- .iter()
- .find(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did);
+ let deref_impl = traits.iter().find(|t| {
+ t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait()
+ });
if let Some(impl_) = deref_impl {
- let has_deref_mut = traits
- .iter()
- .any(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_mut_trait_did);
+ let has_deref_mut = traits.iter().any(|t| {
+ t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_mut_trait()
+ });
render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
}
let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
}
}
-fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bool {
+fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
let self_type_opt = match *item.kind {
clean::MethodItem(ref method, _) => method.decl.self_type(),
clean::TyMethodItem(ref method) => method.decl.self_type(),
(mutability == Mutability::Mut, false, false)
}
SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
- (false, Some(did) == cache.owned_box_did, false)
+ (false, Some(did) == tcx.lang_items().owned_box(), false)
}
SelfTy::SelfValue => (false, false, true),
_ => (false, false, false),
&& match render_mode {
RenderMode::Normal => true,
RenderMode::ForDeref { mut_: deref_mut_ } => {
- should_render_item(&item, deref_mut_, cx.cache())
+ should_render_item(&item, deref_mut_, cx.tcx())
}
};
for_deref: bool,
used_links: &mut FxHashSet<String>,
deref_mut: bool,
- cache: &Cache,
+ tcx: TyCtxt<'_>,
) -> Vec<String> {
i.items
.iter()
.filter_map(|item| match item.name {
Some(ref name) if !name.is_empty() && item.is_method() => {
- if !for_deref || should_render_item(item, deref_mut, cache) {
+ if !for_deref || should_render_item(item, deref_mut, tcx) {
Some(format!(
"<a href=\"#{}\">{}</a>",
get_next_url(used_links, format!("method.{}", name)),
let mut ret = v
.iter()
.filter(|i| i.inner_impl().trait_.is_none())
- .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false, cache))
+ .flat_map(move |i| {
+ get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())
+ })
.collect::<Vec<_>>();
if !ret.is_empty() {
// We want links' order to be reproducible so we don't use unstable sort.
}
if v.iter().any(|i| i.inner_impl().trait_.is_some()) {
- if let Some(impl_) = v
- .iter()
- .filter(|i| i.inner_impl().trait_.is_some())
- .find(|i| i.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did)
- {
+ if let Some(impl_) = v.iter().filter(|i| i.inner_impl().trait_.is_some()).find(|i| {
+ i.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait()
+ }) {
sidebar_deref_methods(cx, out, impl_, v);
}
}
}
}
- let deref_mut = v
- .iter()
- .filter(|i| i.inner_impl().trait_.is_some())
- .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did);
+ let deref_mut = v.iter().filter(|i| i.inner_impl().trait_.is_some()).any(|i| {
+ i.inner_impl().trait_.def_id_full(c) == cx.tcx().lang_items().deref_mut_trait()
+ });
let inner_impl = target
.def_id_full(c)
.or_else(|| {
let mut ret = impls
.iter()
.filter(|i| i.inner_impl().trait_.is_none())
- .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c))
+ .flat_map(|i| {
+ get_methods(i.inner_impl(), true, &mut used_links, deref_mut, cx.tcx())
+ })
.collect::<Vec<_>>();
if !ret.is_empty() {
write!(
debug!("{:?}", indices);
let mut curty = None;
+ // See: https://github.com/rust-lang/rust/issues/88545
+ let item_table_block_size = 900usize;
+ let mut item_table_nth_element = 0usize;
+
for &idx in &indices {
let myitem = &items[idx];
if myitem.is_stripped() {
write!(
w,
"<h2 id=\"{id}\" class=\"section-header\">\
- <a href=\"#{id}\">{name}</a></h2>\n{}",
+ <a href=\"#{id}\">{name}</a>\
+ </h2>\n{}",
ITEM_TABLE_OPEN,
id = cx.derive_id(short.to_owned()),
name = name
);
+ item_table_nth_element = 0;
}
match *myitem.kind {
);
}
}
+
+ item_table_nth_element += 1;
+ if item_table_nth_element > item_table_block_size {
+ w.write_str(ITEM_TABLE_CLOSE);
+ w.write_str(ITEM_TABLE_OPEN);
+ item_table_nth_element = 0;
+ }
}
if curty.is_some() {
}
fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
- for (i, ty) in s
- .iter()
- .map(|f| if let clean::StructFieldItem(ref ty) = *f.kind { ty } else { unreachable!() })
- .enumerate()
- {
+ for (i, ty) in s.iter().enumerate() {
if i > 0 {
w.write_str(", ");
}
- write!(w, "{}", ty.print(cx));
+ match *ty.kind {
+ clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
+ clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)),
+ _ => unreachable!(),
+ }
}
}
name = variant.name.as_ref().unwrap(),
);
for field in fields {
- use crate::clean::StructFieldItem;
- if let StructFieldItem(ref ty) = *field.kind {
- let id = cx.derive_id(format!(
- "variant.{}.field.{}",
- variant.name.as_ref().unwrap(),
- field.name.as_ref().unwrap()
- ));
- write!(
- w,
- "<span id=\"{id}\" class=\"variant small-section-header\">\
- <a href=\"#{id}\" class=\"anchor field\"></a>\
- <code>{f}: {t}</code>\
- </span>",
- id = id,
- f = field.name.as_ref().unwrap(),
- t = ty.print(cx)
- );
- document(w, cx, field, Some(variant));
+ match *field.kind {
+ clean::StrippedItem(box clean::StructFieldItem(_)) => {}
+ clean::StructFieldItem(ref ty) => {
+ let id = cx.derive_id(format!(
+ "variant.{}.field.{}",
+ variant.name.as_ref().unwrap(),
+ field.name.as_ref().unwrap()
+ ));
+ write!(
+ w,
+ "<span id=\"{id}\" class=\"variant small-section-header\">\
+ <a href=\"#{id}\" class=\"anchor field\"></a>\
+ <code>{f}: {t}</code>\
+ </span>",
+ id = id,
+ f = field.name.as_ref().unwrap(),
+ t = ty.print(cx)
+ );
+ document(w, cx, field, Some(variant));
+ }
+ _ => unreachable!(),
}
}
w.write_str("</div></div>");
-use crate::clean;
+use crate::clean::{self, PrimitiveType};
use crate::html::sources;
use rustc_data_structures::fx::FxHashMap;
crate enum LinkFromSrc {
Local(clean::Span),
External(DefId),
+ Primitive(PrimitiveType),
}
/// This function will do at most two things:
Some(def_id)
}
Res::Local(_) => None,
+ Res::PrimTy(p) => {
+ // FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
+ let span = path_span.unwrap_or(path.span);
+ self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
+ return;
+ }
Res::Err => return,
_ => return,
};
if let Some(span) = self.tcx.hir().res_span(path.res) {
- self.matches.insert(
- path_span.unwrap_or_else(|| path.span),
- LinkFromSrc::Local(clean::Span::new(span)),
- );
- } else if let Some(def_id) = info {
self.matches
- .insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id));
+ .insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span)));
+ } else if let Some(def_id) = info {
+ self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id));
}
}
}
self.dst.join(&filename)
}
- fn write_shared<C: AsRef<[u8]>>(
+ fn write_shared(
&self,
resource: SharedResource<'_>,
- contents: C,
+ contents: impl 'static + Send + AsRef<[u8]>,
emit: &[EmitType],
) -> Result<(), Error> {
if resource.should_emit(emit) {
fn write_minify(
&self,
resource: SharedResource<'_>,
- contents: &str,
+ contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
minify: bool,
emit: &[EmitType],
) -> Result<(), Error> {
- let tmp;
- let contents = if minify {
- tmp = if resource.extension() == Some(&OsStr::new("css")) {
+ if minify {
+ let contents = contents.as_ref();
+ let contents = if resource.extension() == Some(&OsStr::new("css")) {
minifier::css::minify(contents).map_err(|e| {
Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
})?
} else {
minifier::js::minify(contents)
};
- tmp.as_bytes()
+ self.write_shared(resource, contents, emit)
} else {
- contents.as_bytes()
- };
-
- self.write_shared(resource, contents, emit)
+ self.write_shared(resource, contents, emit)
+ }
}
}
let lock_file = cx.dst.join(".lock");
let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
- // The weird `: &_` is to work around a borrowck bug: https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723
- let write_minify = |p, c: &_| {
+ // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly.
+ fn write_minify(
+ basename: &'static str,
+ contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
+ cx: &Context<'_>,
+ options: &RenderOptions,
+ ) -> Result<(), Error> {
cx.write_minify(
- SharedResource::ToolchainSpecific { basename: p },
- c,
+ SharedResource::ToolchainSpecific { basename },
+ contents,
options.enable_minification,
&options.emit,
)
- };
+ }
+
// Toolchain resources should never be dynamic.
let write_toolchain = |p: &'static _, c: &'static _| {
cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit)
"details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
"toggle-plus.svg",
);
- write_minify("rustdoc.css", &rustdoc_css)?;
+ write_minify("rustdoc.css", rustdoc_css, cx, options)?;
// Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date.
- write_minify("settings.css", static_files::SETTINGS_CSS)?;
- write_minify("noscript.css", static_files::NOSCRIPT_CSS)?;
+ write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?;
+ write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?;
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
// then we'll run over the "official" styles.
// Handle the official themes
match theme {
- "light" => write_minify("light.css", static_files::themes::LIGHT)?,
- "dark" => write_minify("dark.css", static_files::themes::DARK)?,
- "ayu" => write_minify("ayu.css", static_files::themes::AYU)?,
+ "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
+ "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
+ "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
_ => {
// Handle added third-party themes
let filename = format!("{}.{}", theme, extension);
// Maybe we can change the representation to move this out of main.js?
write_minify(
"main.js",
- &static_files::MAIN_JS.replace(
- "/* INSERT THEMES HERE */",
- &format!(" = {}", serde_json::to_string(&themes).unwrap()),
- ),
+ static_files::MAIN_JS
+ .replace(
+ "/* INSERT THEMES HERE */",
+ &format!(" = {}", serde_json::to_string(&themes).unwrap()),
+ )
+ .replace(
+ "/* INSERT RUSTDOC_VERSION HERE */",
+ &format!(
+ "rustdoc {}",
+ rustc_interface::util::version_str().unwrap_or("unknown version")
+ ),
+ ),
+ cx,
+ options,
)?;
- write_minify("search.js", static_files::SEARCH_JS)?;
- write_minify("settings.js", static_files::SETTINGS_JS)?;
+ write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
+ write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
if cx.include_sources {
- write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?;
+ write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
}
{
write_minify(
"storage.js",
- &format!(
+ format!(
"var resourcesSuffix = \"{}\";{}",
cx.shared.resource_suffix,
static_files::STORAGE_JS
),
+ cx,
+ options,
)?;
}
// This varies based on the invocation, so it can't go through the write_minify wrapper.
cx.write_minify(
SharedResource::InvocationSpecific { basename: "theme.css" },
- &buffer,
+ buffer,
options.enable_minification,
&options.emit,
)?;
}
- write_minify("normalize.css", static_files::NORMALIZE_CSS)?;
+ write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?;
for (name, contents) in &*FILES_UNVERSIONED {
cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?;
}
content,
&cx.shared.style_files,
);
- cx.shared.fs.write(&dst, v.as_bytes())?;
+ cx.shared.fs.write(dst, v)?;
}
}
}",
);
v.push_str("})()");
- cx.shared.fs.write(&mydst, &v)?;
+ cx.shared.fs.write(mydst, v)?;
}
Ok(())
}
},
&self.cx.shared.style_files,
);
- self.cx.shared.fs.write(&cur, v.as_bytes())?;
+ self.cx.shared.fs.write(cur, v)?;
self.emitted_local_sources.insert(p);
Ok(())
}
position: relative;
}
+.docblock > * {
+ max-width: 100%;
+ overflow-x: auto;
+}
+
.content .out-of-band {
flex-grow: 0;
text-align: right;
display: block;
margin-right: 0.5rem;
}
-#help > div > span {
+#help span.top, #help span.bottom {
text-align: center;
display: block;
- margin: 10px 0;
font-size: 18px;
- border-bottom: 1px solid #ccc;
+
+}
+#help span.top {
+ text-align: center;
+ display: block;
+ margin: 10px 0;
+ border-bottom: 1px solid;
padding-bottom: 4px;
margin-bottom: 6px;
}
+#help span.bottom {
+ clear: both;
+ border-top: 1px solid;
+}
#help dd { margin: 5px 35px; }
#help .infos { padding-left: 0; }
#help h1, #help h2 { margin-top: 0; }
color: #c5c5c5;
}
body.source .example-wrap pre.rust a {
- background: #c5c5c5;
+ background: #333;
}
.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
border-radius: 4px;
}
-#help > div > span {
- border-bottom-color: #5c6773;
+#help span.bottom, #help span.top {
+ border-color: #5c6773;
}
.since {
border-color: #bfbfbf;
}
-#help > div > span {
- border-bottom-color: #bfbfbf;
+#help span.bottom, #help span.top {
+ border-color: #bfbfbf;
}
#help dt {
border-color: #bfbfbf;
}
-#help > div > span {
- border-bottom-color: #bfbfbf;
+#help span.bottom, #help span.top {
+ border-color: #bfbfbf;
}
.since {
});
var book_info = document.createElement("span");
+ book_info.className = "top";
book_info.innerHTML = "You can find more information in \
<a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
container.appendChild(div_shortcuts);
container.appendChild(div_infos);
+ var rustdoc_version = document.createElement("span");
+ rustdoc_version.className = "bottom";
+ var rustdoc_version_code = document.createElement("code");
+ rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */";
+ rustdoc_version.appendChild(rustdoc_version_code);
+
+ container.appendChild(rustdoc_version);
+
popup.appendChild(container);
insertAfter(popup, searchState.outputElement());
// So that it's only built once and then it'll do nothing when called!
.get(&item.def_id)
.into_iter()
.flatten()
- .filter_map(|clean::ItemLink { link, did, .. }| {
- did.map(|did| (link.clone(), from_item_id(did.into())))
- })
+ .map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
.collect();
let docs = item.attrs.collapsed_doc_value();
let attrs = item
"URL",
)
}),
- unstable("display-warnings", |o| {
- o.optflagmulti("", "display-warnings", "to print code warnings when testing doc")
+ unstable("display-doctest-warnings", |o| {
+ o.optflagmulti(
+ "",
+ "display-doctest-warnings",
+ "show warnings that originate in doctests",
+ )
}),
stable("crate-version", |o| {
o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
.map_err(|err| format!("{}: {}", options.input.display(), err))?;
let mut opts = TestOptions::default();
opts.no_crate_inject = true;
- opts.display_warnings = options.display_warnings;
+ opts.display_doctest_warnings = options.display_doctest_warnings;
let mut collector = Collector::new(
Symbol::intern(&options.input.display().to_string()),
options.clone(),
crate::doctest::run_tests(
options.test_args,
options.nocapture,
- options.display_warnings,
+ options.display_doctest_warnings,
collector.tests,
);
Ok(())
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use regex::Regex;
});
};
- let mut p = Parser::new_ext(&dox, opts()).into_offset_iter();
+ let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
while let Some((event, range)) = p.next() {
match event {
use crate::html::markdown::{find_testable_code, ErrorCodes};
use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
use crate::passes::Pass;
+use rustc_hir as hir;
use rustc_lint::builtin::MISSING_DOCS;
use rustc_middle::lint::LintLevelSource;
+use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
use rustc_span::FileName;
use serde::Serialize;
.hir()
.local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
+
+ // In case we have:
+ //
+ // ```
+ // enum Foo { Bar(u32) }
+ // // or:
+ // struct Bar(u32);
+ // ```
+ //
+ // there is no need to require documentation on the fields of tuple variants and
+ // tuple structs.
+ let should_be_ignored = i
+ .def_id
+ .as_def_id()
+ .and_then(|def_id| self.ctx.tcx.parent(def_id))
+ .and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
+ .map(|node| {
+ matches!(
+ node,
+ hir::Node::Variant(hir::Variant {
+ data: hir::VariantData::Tuple(_, _),
+ ..
+ }) | hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _), _),
+ ..
+ })
+ )
+ })
+ .unwrap_or(false);
+
// `missing_docs` is allow-by-default, so don't treat this as ignoring the item
- // unless the user had an explicit `allow`
- let should_have_docs =
- level != lint::Level::Allow || matches!(source, LintLevelSource::Default);
+ // unless the user had an explicit `allow`.
+ //
+ let should_have_docs = !should_be_ignored
+ && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default));
+
debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
self.items.entry(filename).or_default().count_item(
has_docs,
);
} else if empty_block {
diag.span_suggestion(
- sp.from_inner(InnerSpan::new(0, 3)),
+ sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
explanation,
- String::from("```text"),
+ String::from("text"),
Applicability::MachineApplicable,
);
}
};
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::ty::TyCtxt;
-use rustc_middle::{bug, ty};
+use rustc_middle::{bug, span_bug, ty};
use rustc_resolve::ParentScope;
use rustc_session::lint::Lint;
use rustc_span::hygiene::{MacroKind, SyntaxContext};
}
}
- fn def_id(self) -> DefId {
- self.opt_def_id().expect("called def_id() on a primitive")
- }
-
- fn opt_def_id(self) -> Option<DefId> {
+ fn def_id(self, tcx: TyCtxt<'_>) -> DefId {
match self {
- Res::Def(_, id) => Some(id),
- Res::Primitive(_) => None,
+ Res::Def(_, id) => id,
+ Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(),
}
}
/// link, Rustdoc disallows having a user-specified anchor.
///
/// Most of the time this is fine, because you can just link to the page of
- /// the item if you want to provide your own anchor. For primitives, though,
- /// rustdoc uses the anchor as a side channel to know which page to link to;
- /// it doesn't show up in the generated link. Ideally, rustdoc would remove
- /// this limitation, allowing you to link to subheaders on primitives.
+ /// the item if you want to provide your own anchor.
RustdocAnchorConflict(Res),
}
ty::AssocKind::Const => "associatedconstant",
ty::AssocKind::Type => "associatedtype",
};
- let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
+ let fragment = format!("{}.{}", out, item_name);
(Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
})
})
return handle_variant(self.cx, res, extra_fragment);
}
// Not a trait item; just return what we found.
- Res::Primitive(ty) => {
- if extra_fragment.is_some() {
- return Err(ErrorKind::AnchorFailure(
- AnchorFailure::RustdocAnchorConflict(res),
- ));
- }
- return Ok((res, Some(ty.as_sym().to_string())));
- }
_ => return Ok((res, extra_fragment.clone())),
}
}
let (res, fragment, side_channel) =
self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
let result = if extra_fragment.is_some() {
+ // NOTE: can never be a primitive since `side_channel.is_none()` only when `res`
+ // is a trait (and the side channel DefId is always an associated item).
let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r));
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res)))
} else {
module_id = DefId { krate, index: CRATE_DEF_INDEX };
}
- let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(
+ let (mut res, fragment) = self.resolve_with_disambiguator_cached(
ResolutionInfo {
module_id,
dis: disambiguator,
if let Some(prim) = resolve_primitive(path_str, TypeNS) {
// `prim@char`
if matches!(disambiguator, Some(Disambiguator::Primitive)) {
- if fragment.is_some() {
- anchor_failure(
- self.cx,
- diag_info,
- AnchorFailure::RustdocAnchorConflict(prim),
- );
- return None;
- }
res = prim;
- fragment = Some(prim.name(self.cx.tcx).to_string());
} else {
// `[char]` when a `char` module is in scope
let candidates = vec![res, prim];
}
}
- Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
+ Some(ItemLink {
+ link: ori_link.link,
+ link_text,
+ did: res.def_id(self.cx.tcx),
+ fragment,
+ })
}
Res::Def(kind, id) => {
verify(kind, id)?;
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
- Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
+ Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
}
}
}
if let Some(ref cached) = self.visited_links.get(&key) {
match cached {
Some(cached) => {
- self.kind_side_channel.set(cached.side_channel.clone());
+ self.kind_side_channel.set(cached.side_channel);
return Some(cached.res.clone());
}
None if cache_resolution_failure => return None,
diag.span_label(sp, "invalid anchor");
}
if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure {
- diag.note("this restriction may be lifted in a future release");
- diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information");
+ if let Some(sp) = sp {
+ span_bug!(sp, "anchors should be allowed now");
+ } else {
+ bug!("anchors should be allowed now");
+ }
}
});
}
use rustc_middle::ty::DefIdTree;
if extra_fragment.is_some() {
+ // NOTE: `res` can never be a primitive since this function is only called when `tcx.def_kind(res) == DefKind::Variant`.
return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res)));
}
cx.tcx
- .parent(res.def_id())
+ .parent(res.def_id(cx.tcx))
.map(|parent| {
let parent_def = Res::Def(DefKind::Enum, parent);
let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use crate::visit_ast::inherits_doc_hidden;
+use rustc_hir as hir;
use rustc_middle::lint::LintLevelSource;
use rustc_session::lint;
use rustc_span::symbol::sym;
| clean::ImportItem(_)
| clean::PrimitiveItem(_)
| clean::KeywordItem(_)
+ // check for trait impl
+ | clean::ImplItem(clean::Impl { trait_: Some(_), .. })
)
{
return false;
}
+
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
+
+ // check if parent is trait impl
+ if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
+ if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) {
+ if matches!(
+ parent_node,
+ hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }),
+ ..
+ })
+ ) {
+ return false;
+ }
+ }
+ }
+
if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
|| inherits_doc_hidden(cx.tcx, hir_id)
+ || cx.tcx.hir().span(hir_id).in_derive_expansion()
{
return false;
}
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use std::iter::Peekable;
let mut is_in_comment = None;
let mut in_code_block = false;
- let p = Parser::new_ext(&dox, opts()).into_offset_iter();
+ let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
for (event, range) in p {
match event {
}
}
- fn visit_item(&mut self, res: Res) {
+ fn visit_item(&mut self, res: Res<!>) {
let def_id = res.def_id();
let vis = self.tcx.visibility(def_id);
let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None };
-Subproject commit ec995b75d71c5f3b9a82fe084259477eb22f74da
+Subproject commit 86c7daa627aefda1371568b948eba21edf720747
[package]
name = "rustdoc-json-types"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
--- /dev/null
+// Check that niche selection prefers zero and that jumps are optimized away.
+// See https://github.com/rust-lang/rust/pull/87794
+// assembly-output: emit-asm
+// only-x86
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Size {
+ One = 1,
+ Two = 2,
+ Three = 3,
+}
+
+#[no_mangle]
+pub fn handle(x: Option<Size>) -> u8 {
+ match x {
+ None => 0,
+ Some(size) => size as u8,
+ }
+}
+
+// There should be no jumps in output
+// CHECK-NOT: j
--- /dev/null
+// only-x86_64
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
+
+// CHECK-LABEL: banana
+// CHECK: crc32
+#[no_mangle]
+pub unsafe fn banana(v: u8) -> u32 {
+ use std::arch::x86_64::*;
+ let out = !0u32;
+ _mm_crc32_u8(out, v)
+}
--- /dev/null
+// compile-flags: -Z panic-in-drop=abort -O
+
+// Ensure that unwinding code paths are eliminated from the output after
+// optimization.
+
+#![crate_type = "lib"]
+use std::any::Any;
+use std::mem::forget;
+
+pub struct ExternDrop;
+impl Drop for ExternDrop {
+ #[inline(always)]
+ fn drop(&mut self) {
+ // This call may potentially unwind.
+ extern "Rust" {
+ fn extern_drop();
+ }
+ unsafe {
+ extern_drop();
+ }
+ }
+}
+
+struct AssertNeverDrop;
+impl Drop for AssertNeverDrop {
+ #[inline(always)]
+ fn drop(&mut self) {
+ // This call should be optimized away as unreachable.
+ extern "C" {
+ fn should_not_appear_in_output();
+ }
+ unsafe {
+ should_not_appear_in_output();
+ }
+ }
+}
+
+// CHECK-LABEL: normal_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn normal_drop(x: ExternDrop) {
+ let guard = AssertNeverDrop;
+ drop(x);
+ forget(guard);
+}
+
+// CHECK-LABEL: indirect_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn indirect_drop(x: Box<dyn Any>) {
+ let guard = AssertNeverDrop;
+ drop(x);
+ forget(guard);
+}
--- /dev/null
+// only-x86_64
+// min-llvm-version: 14.0
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse4.2")]
+#[no_mangle]
+pub unsafe fn crc32sse(v: u8) -> u32 {
+ use std::arch::x86_64::*;
+ let out = !0u32;
+ _mm_crc32_u8(out, v)
+}
+
+// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
// cdb-command:dx f64
// cdb-check:f64 : 3.500000 [Type: double]
// cdb-command:.enable_unicode 1
+// FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str.
// cdb-command:dx s
-// cdb-check:s : "Hello, World!" [Type: str]
+// cdb-check:s : [...] [Type: str]
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
// only-cdb
-// ignore-tidy-linelength
// compile-flags:-g
// cdb-command: g
-// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
-// so the best we can do is to make sure we are generating the right debuginfo.
-// Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers)
-// to disable the natvis for a given expression. We also provide the `-r2` flag
-// to expand the expression 2 levels.
-
-// cdb-command: dx -r2 a,!
-// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
-// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
-
-// cdb-command: dx -r2 b,!
-// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
-// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
-
-// cdb-command: dx -r2 c,!
-// cdb-check:c,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 d,!
-// cdb-check:d,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 e,!
-// cdb-check:e,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 f,!
-// cdb-check:f,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
-// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
-// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 g,!
-// cdb-check:g,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
-// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
-// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 h,!
-// cdb-check:h,! : Some [Type: enum$<core::option::Option<u32> >]
-// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
-// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
-// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
-// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option]
+// cdb-command: dx a
+// cdb-check:a : Some({...}) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
+
+// cdb-command: dx b
+// cdb-check:b : None [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check: [variant] : None
+
+// cdb-command: dx c
+// cdb-check:c : Tag1 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [variant] : Tag1
+
+// cdb-command: dx d
+// cdb-check:d : Data({...}) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [variant] : Data
+// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
+
+// cdb-command: dx e
+// cdb-check:e : Tag2 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [<Raw View>] [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check: [variant] : Tag2
+
+// cdb-command: dx f
+// cdb-check:f : Some({...}) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *]
+
+// cdb-command: dx g
+// cdb-check:g : None [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check: [variant] : None
// cdb-command: dx h
// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
// cdb-check: [variant] : Some
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
-// cdb-command: dx -r2 i,!
-// cdb-check:i,! : None [Type: enum$<core::option::Option<u32> >]
-// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
-// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
-// cdb-check: [+0x004] __0 : 0x[...] [Type: unsigned int]
-// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option]
-
// cdb-command: dx i
// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
// cdb-command: dx j
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-command: dx -r2 k,!
-// cdb-check:k,! [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
-// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some]
-// cdb-check: [+0x000] __0 [Type: alloc::string::String]
-// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 l,!
-// cdb-check:l,! : $T2 [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
-// cdb-check: [+0x000] Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>::Ok]
-// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int]
+// cdb-command: dx k
+// cdb-check:k : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
+
+// cdb-command: dx l
+// cdb-check:l : Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check: [<Raw View>] [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check: [variant] : Ok
+// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int]
pub enum CStyleEnum {
Low = 2,
--- /dev/null
+// only-cdb
+// compile-flags: -g
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1 : (0xa..0xc) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2 : (0x14..0x1e) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1 : (0x9..0x64) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2 : (0xc..0x5a) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx o1
+// cdb-check:o1 : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]]
+// cdb-command: dx o2
+// cdb-check:o2 : Some [Type: enum$<core::option::Option<u64> >]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx t1
+// cdb-check:t1 : (0xa, 0x14) [Type: tuple$<u32,u32>]
+// cdb-check: [0] : 0xa [Type: unsigned int]
+// cdb-check: [1] : 0x14 [Type: unsigned int]
+// cdb-command: dx t2
+// cdb-check:t2 : (0x1e, 0x28) [Type: tuple$<u64,u64>]
+// cdb-check: [0] : 0x1e [Type: unsigned __int64]
+// cdb-check: [1] : 0x28 [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s : "this is a static str" [Type: str]
+// cdb-check: [len] : 0x14 [Type: unsigned [...]]
+// cdb-check: [chars]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s : { len=0x5 } [Type: slice$<u8>]
+// cdb-check: [len] : 0x5 [Type: unsigned [...]]
+// cdb-check: [0] : 0x1 [Type: unsigned char]
+// cdb-check: [1] : 0x2 [Type: unsigned char]
+// cdb-check: [2] : 0x3 [Type: unsigned char]
+// cdb-check: [3] : 0x4 [Type: unsigned char]
+// cdb-check: [4] : 0x5 [Type: unsigned char]
+
+use std::ops::Range;
+
+fn range(r1: Range<u32>, r2: Range<u64>) {
+ zzz(); // #break
+}
+
+fn range_mut(mut r1: Range<u32>, mut r2: Range<u64>) {
+ if r1.start == 9 {
+ r1.end = 100;
+ }
+
+ if r2.start == 12 {
+ r2.end = 90;
+ }
+
+ zzz(); // #break
+}
+
+fn option(o1: Option<u32>, o2: Option<u64>) {
+ zzz(); // #break
+}
+
+fn tuple(t1: (u32, u32), t2: (u64, u64)) {
+ zzz(); // #break
+}
+
+fn str(s: &str) {
+ zzz(); // #break
+}
+
+fn slice(s: &[u8]) {
+ zzz(); // #break
+}
+
+fn zzz() { }
+
+fn main() {
+ range(10..12, 20..30);
+ range_mut(9..20, 12..80);
+ option(Some(1234), Some(5678));
+ tuple((10, 20), (30, 40));
+ str("this is a static str");
+ slice(&[1, 2, 3, 4, 5]);
+}
// cdb-only
// min-cdb-version: 10.0.21287.1005
// compile-flags:-g
+// FIXME: Failed on update to 10.0.22000.1
+// ignore-windows
// === CDB TESTS ==================================================================================
//
// cdb-check: [11] : 33 '!' [Type: char]
// cdb-command: dx os_string
-// cdb-check:os_string : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString]
+// NOTE: OSString is WTF-8 encoded which Windows debuggers don't understand. Verify the UTF-8
+// portion displays correctly.
+// cdb-check:os_string : "IAMA OS string [...]" [Type: std::ffi::os_str::OsString]
// cdb-check: [<Raw View>] [Type: std::ffi::os_str::OsString]
-// cdb-check: [chars] : "IAMA OS string 😃"
+// cdb-check: [chars] : "IAMA OS string [...]"
// cdb-command: dx some
// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
// cdb-check: [variant] : None
// cdb-command: dx some_string
-// NOTE: cdb fails to interpret debug info of Option enums on i686.
-// cdb-check:some_string [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:some_string : Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String]
// cdb-command: dx linkedlist
// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList<i32>]
-// revisions: rpass1 rpass2
+// revisions: rpass1 rpass2 rpass3 rpass4
// compile-flags: -Zquery-dep-graph
+// [rpass1]compile-flags: -Zincremental-ignore-spans
+// [rpass2]compile-flags: -Zincremental-ignore-spans
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
#![feature(rustc_attrs)]
-#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass4")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass4")]
// This test case makes sure that a change in symbol visibility is detected by
// our dependency tracking. We do this by changing a module's visibility to
// even from an executable. Plain Rust functions are only exported from Rust
// libraries, which our test infrastructure does not support.
-#[cfg(rpass1)]
+#[cfg(any(rpass1,rpass3))]
pub mod mod1 {
#[no_mangle]
pub fn foo() {}
}
-#[cfg(rpass2)]
+#[cfg(any(rpass2,rpass4))]
mod mod1 {
#[no_mangle]
pub fn foo() {}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
// Change Callee (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_callee_function() {
callee1(1, 2)
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_callee_function() {
callee2(1, 2)
}
// Change Argument (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_argument_function() {
callee1(1, 2)
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_argument_function() {
callee1(1, 3)
}
// Change Callee Indirectly (Function)
mod change_callee_indirectly_function {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::callee1 as callee;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::callee2 as callee;
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
pub fn change_callee_indirectly_function() {
callee(1, 2)
}
}
// Change Callee (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_callee_method() {
let s = Struct;
s.method1('x', true);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_callee_method() {
let s = Struct;
s.method2('x', true);
// Change Argument (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_argument_method() {
let s = Struct;
s.method1('x', true);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_argument_method() {
let s = Struct;
s.method1('y', true);
// Change Callee (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_ufcs_callee_method() {
let s = Struct;
Struct::method1(&s, 'x', true);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_ufcs_callee_method() {
let s = Struct;
Struct::method2(&s, 'x', true);
// Change Argument (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_argument_method_ufcs() {
let s = Struct;
Struct::method1(&s, 'x', true);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_argument_method_ufcs() {
let s = Struct;
- Struct::method1(&s, 'x', false);
+ Struct::method1(&s, 'x',false);
}
// Change To UFCS
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_to_ufcs() {
let s = Struct;
- s.method1('x', true);
+ s.method1('x', true); // ------
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
// One might think this would be expanded in the hir_owner_nodes/Mir, but it actually
// results in slightly different hir_owner/Mir.
pub fn change_to_ufcs() {
// Change UFCS Callee Indirectly
pub mod change_ufcs_callee_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Struct as Struct;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Struct2 as Struct;
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
-
-
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub fn change_ufcs_callee_indirectly() {
let s = Struct;
Struct::method1(&s, 'q', false)
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change closure body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_closure_body() {
let _ = || 1u32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_closure_body() {
let _ = || 3u32;
}
// Add parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_parameter() {
let x = 0u32;
- let _ = || x + 1;
+ let _ = | | x + 1;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_parameter() {
let x = 0u32;
let _ = |x: u32| x + 1;
// Change parameter pattern
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_parameter_pattern() {
- let _ = |x: (u32,)| x;
+ let _ = | x : (u32,)| x;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_parameter_pattern() {
let _ = |(x,): (u32,)| x;
}
// Add `move` to closure
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_move() {
- let _ = || 1;
+ let _ = || 1;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_move() {
let _ = move || 1;
}
// Add type ascription to parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_type_ascription_to_parameter() {
- let closure = |x| x + 1u32;
+ let closure = |x | x + 1u32;
let _: u32 = closure(1);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")]
+#[rustc_clean(cfg = "cfail6")]
pub fn add_type_ascription_to_parameter() {
let closure = |x: u32| x + 1u32;
let _: u32 = closure(1);
// Change parameter type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_parameter_type() {
let closure = |x: u32| (x as u64) + 1;
let _ = closure(1);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_parameter_type() {
let closure = |x: u16| (x as u64) + 1;
let _ = closure(1);
// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
#![allow(warnings)]
#![feature(rustc_attrs)]
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
}
// Change field value (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_value_struct_like() -> Enum {
Enum::Struct {
x: 0,
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_value_struct_like() -> Enum {
Enum::Struct {
x: 0,
// Change field order (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_order_struct_like() -> Enum {
Enum::Struct {
x: 3,
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
// FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
// would if it were not all constants
pub fn change_field_order_struct_like() -> Enum {
}
// Change constructor path (struct-like) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_path_struct_like() {
- let _ = Enum::Struct {
+ let _ = Enum ::Struct {
x: 0,
y: 1,
z: 2,
};
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_path_struct_like() {
let _ = Enum2::Struct {
x: 0,
// Change variant (regular struct) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_variant_struct_like() {
- let _ = Enum2::Struct {
+ let _ = Enum2::Struct {
x: 0,
y: 1,
z: 2,
};
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_variant_struct_like() {
let _ = Enum2::Struct2 {
x: 0,
// Change constructor path indirectly (struct-like) -------------------------
pub mod change_constructor_path_indirectly_struct_like {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Enum as TheEnum;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Enum2 as TheEnum;
#[rustc_clean(
typeck"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> TheEnum {
TheEnum::Struct {
x: 0,
// Change constructor variant indirectly (struct-like) ---------------------------
pub mod change_constructor_variant_indirectly_struct_like {
use super::Enum2;
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Enum2::Struct as Variant;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Enum2::Struct2 as Variant;
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> Enum2 {
Variant {
x: 0,
// Change field value (tuple-like) -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_value_tuple_like() -> Enum {
Enum::Tuple(0, 1, 2)
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_value_tuple_like() -> Enum {
Enum::Tuple(0, 1, 3)
}
// Change constructor path (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_path_tuple_like() {
- let _ = Enum::Tuple(0, 1, 2);
+ let _ = Enum ::Tuple(0, 1, 2);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg="cfail2",
except="hir_owner_nodes,optimized_mir,typeck"
)]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_path_tuple_like() {
let _ = Enum2::Tuple(0, 1, 2);
}
// Change constructor variant (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_variant_tuple_like() {
- let _ = Enum2::Tuple(0, 1, 2);
+ let _ = Enum2::Tuple (0, 1, 2);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg="cfail2",
except="hir_owner_nodes,optimized_mir,typeck"
)]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_variant_tuple_like() {
let _ = Enum2::Tuple2(0, 1, 2);
}
// Change constructor path indirectly (tuple-like) ---------------------------
pub mod change_constructor_path_indirectly_tuple_like {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Enum as TheEnum;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Enum2 as TheEnum;
#[rustc_clean(
typeck"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> TheEnum {
TheEnum::Tuple(0, 1, 2)
}
// Change constructor variant indirectly (tuple-like) ---------------------------
pub mod change_constructor_variant_indirectly_tuple_like {
use super::Enum2;
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Enum2::Tuple as Variant;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Enum2::Tuple2 as Variant;
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> Enum2 {
Variant(0, 1, 2)
}
}
// Change constructor path (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_path_c_like() {
- let _x = Clike::B;
+ let _x = Clike ::B;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_path_c_like() {
let _x = Clike2::B;
}
// Change constructor variant (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_variant_c_like() {
let _x = Clike::A;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_variant_c_like() {
let _x = Clike::C;
}
// Change constructor path indirectly (C-like) ---------------------------
pub mod change_constructor_path_indirectly_c_like {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Clike as TheEnum;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Clike2 as TheEnum;
#[rustc_clean(
typeck"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> TheEnum {
TheEnum::B
}
// Change constructor variant indirectly (C-like) ---------------------------
pub mod change_constructor_variant_indirectly_c_like {
use super::Clike;
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::Clike::A as Variant;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::Clike::B as Variant;
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> Clike {
Variant
}
// the same between rev2 and rev3.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change enum visibility -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumVisibility { A }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub enum EnumVisibility {
A
}
// Change name of a c-style variant -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeNameCStyleVariant {
Variant1,
Variant2,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeNameCStyleVariant {
Variant1,
Variant2Changed,
// Change name of a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeNameTupleStyleVariant {
Variant1,
Variant2(u32, f32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeNameTupleStyleVariant {
Variant1,
Variant2Changed(u32, f32),
// Change name of a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeNameStructStyleVariant {
Variant1,
Variant2 { a: u32, b: f32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeNameStructStyleVariant {
Variant1,
Variant2Changed { a: u32, b: f32 },
// Change the value of a c-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeValueCStyleVariant0 {
Variant1,
Variant2 = 11,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeValueCStyleVariant0 {
Variant1,
-
- Variant2 =
- 22,
+ Variant2 = 22,
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeValueCStyleVariant1 {
Variant1,
Variant2,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeValueCStyleVariant1 {
Variant1,
Variant2 = 11,
// Add a c-style variant ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddCStyleVariant {
Variant1,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddCStyleVariant {
Variant1,
Variant2,
// Remove a c-style variant ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumRemoveCStyleVariant {
Variant1,
Variant2,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumRemoveCStyleVariant {
Variant1,
}
// Add a tuple-style variant --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddTupleStyleVariant {
Variant1,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddTupleStyleVariant {
Variant1,
Variant2(u32, f32),
// Remove a tuple-style variant -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumRemoveTupleStyleVariant {
Variant1,
Variant2(u32, f32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumRemoveTupleStyleVariant {
Variant1,
}
// Add a struct-style variant -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddStructStyleVariant {
Variant1,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddStructStyleVariant {
Variant1,
Variant2 { a: u32, b: f32 },
// Remove a struct-style variant ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumRemoveStructStyleVariant {
Variant1,
Variant2 { a: u32, b: f32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumRemoveStructStyleVariant {
Variant1,
}
// Change the type of a field in a tuple-style variant ------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeFieldTypeTupleStyleVariant {
Variant1(u32, u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeFieldTypeTupleStyleVariant {
Variant1(u32,
u64),
// Change the type of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeFieldTypeStructStyleVariant {
Variant1,
Variant2 { a: u32, b: u32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeFieldTypeStructStyleVariant {
Variant1,
Variant2 {
// Change the name of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeFieldNameStructStyleVariant {
Variant1 { a: u32, b: u32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeFieldNameStructStyleVariant {
Variant1 { a: u32, c: u32 },
}
// Change order of fields in a tuple-style variant ----------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeOrderTupleStyleVariant {
Variant1(u32, u64),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeOrderTupleStyleVariant {
Variant1(
u64,
// Change order of fields in a struct-style variant ---------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeFieldOrderStructStyleVariant {
Variant1 { a: u32, b: f32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeFieldOrderStructStyleVariant {
Variant1 { b: f32, a: u32 },
}
// Add a field to a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddFieldTupleStyleVariant {
Variant1(u32, u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddFieldTupleStyleVariant {
Variant1(u32, u32, u32),
}
// Add a field to a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddFieldStructStyleVariant {
Variant1 { a: u32, b: u32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddFieldStructStyleVariant {
Variant1 { a: u32, b: u32, c: u32 },
}
// Add #[must_use] to the enum ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddMustUse {
Variant1,
Variant2,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[must_use]
enum EnumAddMustUse {
Variant1,
// Add #[repr(C)] to the enum -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddReprC {
Variant1,
Variant2,
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="type_of")]
+#[rustc_clean(cfg="cfail6")]
#[repr(C)]
enum EnumAddReprC {
Variant1,
// Change the name of a type parameter ----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeNameOfTypeParameter<S> {
Variant1(S),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeNameOfTypeParameter<T> {
Variant1(T),
}
// Add a type parameter ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddTypeParameter<S> {
Variant1(S),
Variant2(S),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddTypeParameter<S, T> {
Variant1(S),
Variant2(T),
// Change the name of a lifetime parameter ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumChangeNameOfLifetimeParameter<'a> {
Variant1(&'a u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumChangeNameOfLifetimeParameter<'b> {
Variant1(&'b u32),
}
// Add a lifetime parameter ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddLifetimeParameter<'a> {
Variant1(&'a u32),
Variant2(&'a u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddLifetimeParameter<'a, 'b> {
Variant1(&'a u32),
Variant2(&'b u32),
// Add a lifetime bound to a lifetime parameter -------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddLifetimeParameterBound<'a, 'b> {
Variant1(&'a u32),
Variant2(&'b u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
Variant1(&'a u32),
Variant2(&'b u32),
}
// Add a lifetime bound to a type parameter -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddLifetimeBoundToParameter<'a, T> {
Variant1(T),
Variant2(&'a u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
Variant1(T),
Variant2(&'a u32),
// Add a trait bound to a type parameter --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddTraitBound<S> {
Variant1(S),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddTraitBound<T: Sync> {
Variant1(T),
}
// Add a lifetime bound to a lifetime parameter in where clause ---------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddLifetimeParameterBoundWhere<'a, 'b> {
Variant1(&'a u32),
Variant2(&'b u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
Variant1(&'a u32),
Variant2(&'b u32),
// Add a lifetime bound to a type parameter in where clause -------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddLifetimeBoundToParameterWhere<'a, T> {
Variant1(T),
Variant2(&'a u32),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
Variant1(T),
Variant2(&'a u32),
// Add a trait bound to a type parameter in where clause ----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumAddTraitBoundWhere<S> {
Variant1(S),
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
enum EnumAddTraitBoundWhere<T> where T: Sync {
Variant1(T),
}
// In an enum with two variants, swap usage of type parameters ----------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumSwapUsageTypeParameters<A, B> {
Variant1 { a: A },
Variant2 { a: B },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumSwapUsageTypeParameters<A, B> {
Variant1 {
a: B
// In an enum with two variants, swap usage of lifetime parameters ------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
enum EnumSwapUsageLifetimeParameters<'a, 'b> {
Variant1 { a: &'a u32 },
Variant2 { b: &'b u32 },
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
enum EnumSwapUsageLifetimeParameters<'a, 'b> {
Variant1 {
a: &'b u32
// Change field type in tuple-style variant indirectly by modifying a use statement
mod change_field_type_indirectly_tuple_style {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as FieldType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as FieldType;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
enum TupleStyle {
Variant1(
FieldType
// Change field type in record-style variant indirectly by modifying a use statement
mod change_field_type_indirectly_struct_style {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as FieldType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as FieldType;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
enum StructStyle {
Variant1 {
a: FieldType
// Change trait bound of type parameter indirectly by modifying a use statement
mod change_trait_bound_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
enum Enum<T: Trait> {
Variant1(T)
}
// Change trait bound of type parameter in where clause indirectly by modifying a use statement
mod change_trait_bound_indirectly_where {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
enum Enum<T> where T: Trait {
Variant1(T)
}
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// the hash of the hir_owner_nodes node should change, but not the hash of
// either the hir_owner or the Metadata node.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn body_not_exported_to_metadata() -> u32 {
1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn body_not_exported_to_metadata() -> u32 {
2
}
// marked as #[inline]. Only the hash of the hir_owner depnode should be
// unaffected by a change to the body.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[inline]
pub fn body_exported_to_metadata_because_of_inline() -> u32 {
1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[inline]
pub fn body_exported_to_metadata_because_of_inline() -> u32 {
2
// generic. Only the hash of the hir_owner depnode should be
// unaffected by a change to the body.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[inline]
pub fn body_exported_to_metadata_because_of_generic() -> u32 {
1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[inline]
pub fn body_exported_to_metadata_because_of_generic() -> u32 {
2
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type = "rlib"]
// Change function name --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn change_function_name1(c: i64) -> i32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn change_function_name2(c: i64) -> i32;
}
// Change parameter name -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn change_parameter_name(c: i64) -> i32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn change_parameter_name(d: i64) -> i32;
}
// Change parameter type -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn change_parameter_type(c: i64) -> i32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn change_parameter_type(c: i32) -> i32;
}
// Change return type ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn change_return_type(c: i32) -> i32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
- pub fn change_return_type(c: i32) -> i8;
+ pub fn change_return_type(c: i32) -> i8 ;
}
// Add parameter ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
- pub fn add_parameter(c: i32) -> i32;
+ pub fn add_parameter(c: i32 ) -> i32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn add_parameter(c: i32, d: i32) -> i32;
}
// Add return type -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
- pub fn add_return_type(c: i32);
+ pub fn add_return_type(c: i32) ;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn add_return_type(c: i32) -> i32;
}
// Make function variadic ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
- pub fn make_function_variadic(c: i32);
+ pub fn make_function_variadic(c: i32 );
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn make_function_variadic(c: i32, ...);
}
// Change calling convention ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn change_calling_convention(c: i32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
extern "rust-call" {
pub fn change_calling_convention(c: i32);
}
// Make function public --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
- fn make_function_public(c: i32);
+ fn make_function_public(c: i32);
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn make_function_public(c: i32);
}
// Add function ----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
extern "C" {
pub fn add_function1(c: i32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn add_function1(c: i32);
pub fn add_function2();
}
// Change link-name ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[link(name = "foo")]
extern "C" {
pub fn change_link_name(c: i32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
#[link(name = "bar")]
extern "C" {
pub fn change_link_name(c: i32);
// Indirectly change parameter type --------------------------------------------
mod indirectly_change_parameter_type {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::c_i32 as c_int;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::c_i64 as c_int;
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5")]
+ #[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn indirectly_change_parameter_type(c: c_int);
}
// Indirectly change return type --------------------------------------------
mod indirectly_change_return_type {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::c_i32 as c_int;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::c_i64 as c_int;
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5")]
+ #[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn indirectly_change_return_type() -> c_int;
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change loop body ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_body() {
let mut _x = 0;
for _ in 0..1 {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_body() {
let mut _x = 0;
for _ in 0..1 {
// Change iteration variable name ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_iteration_variable_name() {
let mut _x = 0;
for _i in 0..1 {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_iteration_variable_name() {
let mut _x = 0;
for _a in 0..1 {
// Change iteration variable pattern -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_iteration_variable_pattern() {
let mut _x = 0;
- for _i in &[0, 1, 2] {
+ for _i in &[0, 1, 2] {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck, promoted_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_iteration_variable_pattern() {
let mut _x = 0;
for &_i in &[0, 1, 2] {
// Change iterable -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_iterable() {
let mut _x = 0;
for _ in &[0, 1, 2] {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_iterable() {
let mut _x = 0;
for _ in &[0, 1, 3] {
// Add break -------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_break() {
let mut _x = 0;
for _ in 0..1 {
_x = 1;
+ // ---
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_break() {
let mut _x = 0;
for _ in 0..1 {
// Add loop label --------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label() {
let mut _x = 0;
- for _ in 0..1 {
+ for _ in 0..1 {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label() {
let mut _x = 0;
'label: for _ in 0..1 {
// Add loop label to break -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: for _ in 0..1 {
_x = 1;
- break;
+ break ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: for _ in 0..1 {
// Change break label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_break_label() {
let mut _x = 0;
'outer: for _ in 0..1 {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
'outer: for _ in 0..1 {
// Add loop label to continue --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: for _ in 0..1 {
_x = 1;
- continue;
+ continue ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: for _ in 0..1 {
// Change continue label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_label() {
let mut _x = 0;
'outer: for _ in 0..1 {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
'outer: for _ in 0..1 {
// Change continue to break ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_to_break() {
let mut _x = 0;
for _ in 0..1 {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_to_break() {
let mut _x = 0;
for _ in 0..1 {
_x = 1;
- break;
+ break ;
}
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(linkage)]
// Add Parameter ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_parameter() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn add_parameter(p: i32) {}
// Add Return Type -------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn add_return_type() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn add_return_type() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
pub fn add_return_type() -> () {}
// Change Parameter Type -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn type_of_parameter(p: i32) {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn type_of_parameter(p: i64) {}
// Change Parameter Type Reference ---------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn type_of_parameter_ref(p: &i32) {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn type_of_parameter_ref(p: &mut i32) {}
// Change Parameter Order ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn order_of_parameters(p1: i32, p2: i64) {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn order_of_parameters(p2: i64, p1: i32) {}
// Unsafe ----------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn make_unsafe() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub unsafe fn make_unsafe() {}
// Extern ----------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn make_extern() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn make_extern() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
pub extern "C" fn make_extern() {}
// Type Parameter --------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn type_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn type_parameter () {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn type_parameter<T>() {}
// Lifetime Parameter ----------------------------------------------------------
-#[cfg(cfail1)]
-pub fn lifetime_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn lifetime_parameter () {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
pub fn lifetime_parameter<'a>() {}
// Trait Bound -----------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn trait_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn trait_bound<T >() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
pub fn trait_bound<T: Eq>() {}
// Builtin Bound ---------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn builtin_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn builtin_bound<T >() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
pub fn builtin_bound<T: Send>() {}
// Lifetime Bound --------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn lifetime_bound<'a, T>() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn lifetime_bound<'a, T: 'a>() {}
// Second Trait Bound ----------------------------------------------------------
-#[cfg(cfail1)]
-pub fn second_trait_bound<T: Eq>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_trait_bound<T: Eq >() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
pub fn second_trait_bound<T: Eq + Clone>() {}
// Second Builtin Bound --------------------------------------------------------
-#[cfg(cfail1)]
-pub fn second_builtin_bound<T: Send>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_builtin_bound<T: Send >() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
pub fn second_builtin_bound<T: Send + Sized>() {}
// Second Lifetime Bound -------------------------------------------------------
-#[cfg(cfail1)]
-pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_lifetime_bound<'a, 'b, T: 'a >() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(
cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
// Inline ----------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn inline() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
#[inline]
pub fn inline() {}
// Inline Never ----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[inline(always)]
pub fn inline_never() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
#[inline(never)]
pub fn inline_never() {}
// No Mangle -------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn no_mangle() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
#[no_mangle]
pub fn no_mangle() {}
// Linkage ---------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn linkage() {}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
#[linkage = "weak_odr"]
pub fn linkage() {}
// Return Impl Trait -----------------------------------------------------------
-#[cfg(cfail1)]
-pub fn return_impl_trait() -> i32 {
+#[cfg(any(cfail1,cfail4))]
+pub fn return_impl_trait() -> i32 {
0
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
pub fn return_impl_trait() -> impl Clone {
0
}
// Change Return Impl Trait ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_return_impl_trait() -> impl Clone {
0u32
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
-pub fn change_return_impl_trait() -> impl Copy {
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn change_return_impl_trait() -> impl Copy {
0u32
}
pub struct ReferencedType2;
pub mod change_return_type_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as ReturnType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as ReturnType;
#[rustc_clean(
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail6")]
pub fn indirect_return_type() -> ReturnType {
ReturnType {}
}
// Change Parameter Type Indirectly --------------------------------------------
pub mod change_parameter_type_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as ParameterType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as ParameterType;
#[rustc_clean(
except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
)]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail6")]
pub fn indirect_parameter_type(p: ParameterType) {}
}
pub trait ReferencedTrait2 {}
pub mod change_trait_bound_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail6")]
pub fn indirect_trait_bound<T: Trait>(p: T) {}
}
// Change Trait Bound Indirectly In Where Clause -------------------------------
pub mod change_trait_bound_indirectly_in_where_clause {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
#[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail6")]
pub fn indirect_trait_bound_where<T>(p: T)
where
T: Trait,
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Change condition (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_condition(x: bool) -> u32 {
- if x {
+ if x {
return 1
}
return 0
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_condition(x: bool) -> u32 {
if !x {
return 1
}
// Change then branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_then_branch(x: bool) -> u32 {
if x {
return 1
return 0
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_then_branch(x: bool) -> u32 {
if x {
return 2
// Change else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_else_branch(x: bool) -> u32 {
if x {
1
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_else_branch(x: bool) -> u32 {
if x {
1
// Add else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_else_branch(x: bool) -> u32 {
let mut ret = 1;
if x {
ret = 2;
+ /*----*/
}
ret
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_else_branch(x: bool) -> u32 {
let mut ret = 1;
// Change condition (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
if let Some(_x) = x {
return 1
0
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
- if let Some(_) = x {
+ if let Some(_ ) = x {
return 1
}
// Change then branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
- return x
+ return x //-
}
0
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
return x + 1
// Change else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
x
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
if let Some(x) = x {
x
// Add else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
let mut ret = 1;
if let Some(x) = x {
ret = x;
+ /*----*/
}
ret
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
let mut ret = 1;
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Change simple index
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn change_simple_index(slice: &[u32]) -> u32 {
slice[3]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn change_simple_index(slice: &[u32]) -> u32 {
slice[4]
}
// Change lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn change_lower_bound(slice: &[u32]) -> &[u32] {
&slice[3..5]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn change_lower_bound(slice: &[u32]) -> &[u32] {
&slice[2..5]
}
// Change upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn change_upper_bound(slice: &[u32]) -> &[u32] {
&slice[3..5]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn change_upper_bound(slice: &[u32]) -> &[u32] {
&slice[3..7]
}
// Add lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn add_lower_bound(slice: &[u32]) -> &[u32] {
- &slice[..4]
+ &slice[ ..4]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn add_lower_bound(slice: &[u32]) -> &[u32] {
&slice[3..4]
}
// Add upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn add_upper_bound(slice: &[u32]) -> &[u32] {
- &slice[3..]
+ &slice[3.. ]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn add_upper_bound(slice: &[u32]) -> &[u32] {
&slice[3..7]
}
// Change mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn change_mutability(slice: &mut [u32]) -> u32 {
(&mut slice[3..5])[0]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn change_mutability(slice: &mut [u32]) -> u32 {
- (&slice[3..5])[0]
+ (& slice[3..5])[0]
}
// Exclusive to inclusive range
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
- &slice[3..7]
+ &slice[3.. 7]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
&slice[3..=7]
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
pub struct Foo;
// Change Method Name -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
pub fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
pub fn method_name2() { }
}
// Change Method Body -----------------------------------------------------------
//
// This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub fn method_body() { }
+ //--------------------------------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn method_body() {
+ // -----------------------
+ }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(
- cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
- )]
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub fn method_body() {
println!("Hello, world!");
}
// Change Method Body (inlined) ------------------------------------------------
//
// This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //------------------------------------------------------------
+ //
+ //--------------------------
#[inline]
- pub fn method_body_inlined() { }
+ pub fn method_body_inlined() {
+ // -----------------------
+ }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(
cfg="cfail2",
except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
#[inline]
pub fn method_body_inlined() {
println!("Hello, world!");
// Change Method Privacy -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------
+ //--------------------------
pub fn method_privacy() { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
- fn method_privacy() { }
+ #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_privacy() { }
}
// Change Method Selfness -----------------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //---------------------------------------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //---------------------------------------------------------------------------------------------
+ //
+ //--------------------------
pub fn method_selfness() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(
cfg="cfail2",
except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn method_selfness(&self) { }
}
// Change Method Selfmutness ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub fn method_selfmutness(&self) { }
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn method_selfmutness(& self) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(
- cfg="cfail2",
- except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
- )]
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn method_selfmutness(&mut self) { }
}
// Add Method To Impl ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
pub fn add_method_to_impl1(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_method_to_impl1(&self) { }
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_method_to_impl2(&self) { }
}
// Add Method Parameter --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub fn add_method_parameter(&self) { }
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn add_method_parameter(&self ) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(
- cfg="cfail2",
- except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
- )]
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_method_parameter(&self, _: i32) { }
}
// Change Method Parameter Name ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
pub fn change_method_parameter_name(&self, a: i64) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn change_method_parameter_name(&self, b: i64) { }
}
// Change Method Return Type ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
pub fn change_method_return_type(&self) -> u16 { 0 }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(
- cfg="cfail2",
- except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
- pub fn change_method_return_type(&self) -> u8 { 0 }
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_method_return_type(&self) -> u32 { 0 }
}
// Make Method #[inline] -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //-------
pub fn make_method_inline(&self) -> u8 { 0 }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
#[inline]
pub fn make_method_inline(&self) -> u8 { 0 }
}
// Change order of parameters -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
}
// Make method unsafe ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub fn make_method_unsafe(&self) { }
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn make_method_unsafe(&self) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(
- cfg="cfail2",
- except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
- )]
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
pub unsafe fn make_method_unsafe(&self) { }
}
// Make method extern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub fn make_method_extern(&self) { }
+ //----------------------------------------------------------------------------
+ //--------------------------
+ //----------------------------------------------------------------------------
+ //--------------------------
+ pub fn make_method_extern(&self) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub extern "C" fn make_method_extern(&self) { }
}
// Change method calling convention --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
- pub extern "C" fn change_method_calling_convention(&self) { }
+ //----------------------------------------------------------------------------
+ //--------------------------
+ //----------------------------------------------------------------------------
+ //--------------------------
+ pub extern "C" fn change_method_calling_convention(&self) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub extern "system" fn change_method_calling_convention(&self) { }
}
// Add Lifetime Parameter to Method --------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
- pub fn add_lifetime_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ---------------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------
+ // -------------------------------------------------------
+ // --------------------------------------------------------
+ // ----------------------------------------------------------
+ // -----------------------------------------------------------
+ // ----------------------------------------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ pub fn add_lifetime_parameter_to_method (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
// Warning: Note that `typeck` are coming up clean here.
// The addition or removal of lifetime parameters that don't
// `typeck` appear dirty, that might be the cause. -nmatsakis
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_lifetime_parameter_to_method<'a>(&self) { }
}
// Add Type Parameter To Method ------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
- pub fn add_type_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ---------------------------------------------------------------
+ // -------------------------------------------------------------
+ // -----------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------
+ //
+ // -------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------
+ //
+ // -------------------------
+ pub fn add_type_parameter_to_method (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
// Warning: Note that `typeck` are coming up clean here.
// The addition or removal of type parameters that don't appear in
except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_type_parameter_to_method<T>(&self) { }
}
// Add Lifetime Bound to Lifetime Parameter of Method --------------------------
-#[cfg(cfail1)]
-impl Foo {
- pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //-----------------------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //-----------------------------------------------------------------------------
+ //
+ //--------------------------
+ pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(
cfg="cfail2",
except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
}
// Add Lifetime Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
- pub fn add_lifetime_bound_to_type_param_of_method<'a, T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------------
+ // -------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------------
+ //
+ // -------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------------
+ //
+ // -------------------------
+ pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
// Warning: Note that `typeck` are coming up clean here.
// The addition or removal of bounds that don't appear in the
// generics before the body, then the `HirId` for things in the
// body will be affected. So if you start to see `typeck`
// appear dirty, that might be the cause. -nmatsakis
- #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\
- type_of,fn_sig")]
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
}
// Add Trait Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
- pub fn add_trait_bound_to_type_param_of_method<T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------------
+ // -------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ pub fn add_trait_bound_to_type_param_of_method<T >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
// Warning: Note that `typeck` are coming up clean here.
// The addition or removal of bounds that don't appear in the
// appear dirty, that might be the cause. -nmatsakis
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
}
// Add #[no_mangle] to Method --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //----------
pub fn add_no_mangle_to_method(&self) { }
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
#[no_mangle]
pub fn add_no_mangle_to_method(&self) { }
}
struct Bar<T>(T);
// Add Type Parameter To Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Bar<u32> {
pub fn add_type_parameter_to_impl(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")]
+#[rustc_clean(cfg="cfail6")]
impl<T> Bar<T> {
#[rustc_clean(
cfg="cfail2",
except="generics_of,fn_sig,typeck,type_of,optimized_mir"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="generics_of,fn_sig,typeck,type_of,optimized_mir"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_type_parameter_to_impl(&self) { }
}
// Change Self Type of Impl ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl Bar<u32> {
pub fn change_impl_self_type(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
impl Bar<u64> {
#[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
pub fn change_impl_self_type(&self) { }
}
// Add Lifetime Bound to Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl<T> Bar<T> {
pub fn add_lifetime_bound_to_impl_parameter(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl<T: 'static> Bar<T> {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_lifetime_bound_to_impl_parameter(&self) { }
}
// Add Trait Bound to Impl Parameter -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl<T> Bar<T> {
pub fn add_trait_bound_to_impl_parameter(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
impl<T: Clone> Bar<T> {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
pub fn add_trait_bound_to_impl_parameter(&self) { }
}
pub fn instantiation_root() {
Foo::method_privacy();
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
{
Bar(0u32).change_impl_self_type();
}
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
{
Bar(0u64).change_impl_self_type();
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change template
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_template(a: i32) -> i32 {
let c: i32;
c
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_template(a: i32) -> i32 {
let c: i32;
// Change output
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_output(a: i32) -> i32 {
let mut _out1: i32 = 0;
_out1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_output(a: i32) -> i32 {
let mut _out1: i32 = 0;
// Change input
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input(_a: i32, _b: i32) -> i32 {
let _out;
_out
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input(_a: i32, _b: i32) -> i32 {
let _out;
// Change input constraint
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
let _out;
_out
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
let _out;
// Change clobber
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_clobber(_a: i32) -> i32 {
let _out;
llvm_asm!("add 1, $0"
: "=r"(_out)
: "0"(_a)
- :
+ :/*--*/
:
);
}
_out
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_clobber(_a: i32) -> i32 {
let _out;
// Change options
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_options(_a: i32) -> i32 {
let _out;
: "=r"(_out)
: "0"(_a)
:
- :
+ :/*-------*/
);
}
_out
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_options(_a: i32) -> i32 {
let _out;
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Change Name -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_name() {
let _x = 2u64;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_name() {
let _y = 2u64;
}
// Add Type --------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_type() {
- let _x = 2u32;
+ let _x = 2u32;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_type() {
let _x: u32 = 2u32;
}
// Change Type -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_type() {
let _x: u64 = 2;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_type() {
- let _x: u8 = 2;
+ let _x: u8 = 2;
}
// Change Mutability of Reference Type -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_mutability_of_reference_type() {
- let _x: &u64;
+ let _x: & u64;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_mutability_of_reference_type() {
let _x: &mut u64;
}
// Change Mutability of Slot ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_mutability_of_slot() {
let mut _x: u64 = 0;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_mutability_of_slot() {
- let _x: u64 = 0;
+ let _x: u64 = 0;
}
// Change Simple Binding to Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_simple_binding_to_pattern() {
- let _x = (0u8, 'x');
+ let _x = (0u8, 'x');
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_simple_binding_to_pattern() {
let (_a, _b) = (0u8, 'x');
}
// Change Name in Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_name_in_pattern() {
let (_a, _b) = (1u8, 'y');
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_name_in_pattern() {
let (_a, _c) = (1u8, 'y');
}
// Add `ref` in Pattern --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_ref_in_pattern() {
- let (_a, _b) = (1u8, 'y');
+ let ( _a, _b) = (1u8, 'y');
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_ref_in_pattern() {
let (ref _a, _b) = (1u8, 'y');
}
// Add `&` in Pattern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_amp_in_pattern() {
- let (_a, _b) = (&1u8, 'y');
+ let ( _a, _b) = (&1u8, 'y');
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_amp_in_pattern() {
let (&_a, _b) = (&1u8, 'y');
}
// Change Mutability of Binding in Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_mutability_of_binding_in_pattern() {
- let (_a, _b) = (99u8, 'q');
+ let ( _a, _b) = (99u8, 'q');
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_mutability_of_binding_in_pattern() {
let (mut _a, _b) = (99u8, 'q');
}
// Add Initializer -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_initializer() {
- let _x: i16;
+ let _x: i16 ;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_initializer() {
let _x: i16 = 3i16;
}
// Change Initializer ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_initializer() {
let _x = 4u16;
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_initializer() {
let _x = 5u16;
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_body() {
let mut _x = 0;
loop {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_body() {
let mut _x = 0;
loop {
// Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_break() {
let mut _x = 0;
loop {
_x = 1;
+ //----
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_break() {
let mut _x = 0;
loop {
// Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label() {
let mut _x = 0;
- loop {
+ /*---*/ loop {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label() {
let mut _x = 0;
'label: loop {
// Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: loop {
_x = 1;
- break;
+ break ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: loop {
// Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_break_label() {
let mut _x = 0;
'outer: loop {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
'outer: loop {
// Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: loop {
_x = 1;
- continue;
+ continue ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: loop {
// Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_label() {
let mut _x = 0;
'outer: loop {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
'outer: loop {
// Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_to_break() {
let mut _x = 0;
loop {
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_to_break() {
let mut _x = 0;
loop {
_x = 1;
- break;
+ break ;
}
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Add Arm ---------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_arm(x: u32) -> u32 {
match x {
0 => 0,
1 => 1,
+ /*---*/
_ => 100,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_arm(x: u32) -> u32 {
match x {
0 => 0,
// Change Order Of Arms --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_order_of_arms(x: u32) -> u32 {
match x {
0 => 0,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_order_of_arms(x: u32) -> u32 {
match x {
1 => 1,
// Add Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_guard_clause(x: u32, y: bool) -> u32 {
match x {
0 => 0,
- 1 => 1,
+ 1 => 1,
_ => 100,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_guard_clause(x: u32, y: bool) -> u32 {
match x {
0 => 0,
// Change Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_guard_clause(x: u32, y: bool) -> u32 {
match x {
0 => 0,
- 1 if y => 1,
+ 1 if y => 1,
_ => 100,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_guard_clause(x: u32, y: bool) -> u32 {
match x {
0 => 0,
// Add @-Binding ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_at_binding(x: u32) -> u32 {
match x {
0 => 0,
1 => 1,
- _ => x,
+ _ => x,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_at_binding(x: u32) -> u32 {
match x {
0 => 0,
// Change Name of @-Binding ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_name_of_at_binding(x: u32) -> u32 {
match x {
0 => 0,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_name_of_at_binding(x: u32) -> u32 {
match x {
0 => 0,
// Change Simple Binding To Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_simple_name_to_pattern(x: u32) -> u32 {
match (x, x & 1) {
(0, 0) => 0,
- a => 1,
+ a => 1,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_simple_name_to_pattern(x: u32) -> u32 {
match (x, x & 1) {
(0, 0) => 0,
// Change Name In Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_name_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
(a, 0) => 0,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_name_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
(b, 0) => 0,
// Change Mutability Of Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
- (a, 0) => 0,
+ ( a, 0) => 0,
_ => 1,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
(mut a, 0) => 0,
// Add `ref` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
- (a, 0) => 0,
+ ( a, 0) => 0,
_ => 1,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
match (x, x & 1) {
(ref a, 0) => 0,
// Add `&` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
match (&x, x & 1) {
- (a, 0) => 0,
+ ( a, 0) => 0,
_ => 1,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
match (&x, x & 1) {
(&a, 0) => 0,
// Change RHS Of Arm -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_rhs_of_arm(x: u32) -> u32 {
match x {
0 => 0,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_rhs_of_arm(x: u32) -> u32 {
match x {
0 => 0,
// Add Alternative To Arm ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_alternative_to_arm(x: u32) -> u32 {
match x {
- 0 => 0,
+ 0 => 0,
1 => 1,
_ => 2,
}
}
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
- except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_alternative_to_arm(x: u32) -> u32 {
match x {
0 | 7 => 0,
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change static visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_VISIBILITY: u8 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub static STATIC_VISIBILITY: u8 = 0;
// Change static mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_MUTABILITY: u8 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
static mut STATIC_MUTABILITY: u8 = 0;
// Add linkage attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_LINKAGE: u8 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[linkage="weak_odr"]
static STATIC_LINKAGE: u8 = 0;
// Add no_mangle attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_NO_MANGLE: u8 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[no_mangle]
static STATIC_NO_MANGLE: u8 = 0;
// Add thread_local attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_THREAD_LOCAL: u8 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[thread_local]
static STATIC_THREAD_LOCAL: u8 = 0;
// Change type from i16 to u64
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_CHANGE_TYPE_1: i16 = 0;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_TYPE_1: u64 = 0;
// Change type from Option<i8> to Option<u16>
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
static STATIC_CHANGE_TYPE_2: Option<i8> = None;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_TYPE_2: Option<u16> = None;
// Change value between simple literals
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_VALUE_1: i16 = {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
{ 1 }
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
{ 2 }
};
// Change value between expressions
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_VALUE_2: i16 = {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
{ 1 + 1 }
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
{ 1 + 2 }
};
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_VALUE_3: i16 = {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
{ 2 + 3 }
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
{ 2 * 3 }
};
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_VALUE_4: i16 = {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
{ 1 + 2 * 3 }
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
{ 1 + 2 * 4 }
};
struct ReferencedType2;
mod static_change_type_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as Type;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as Type;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail6")]
static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
}
// Change field value (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_value_regular_struct() -> RegularStruct {
RegularStruct {
x: 0,
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_value_regular_struct() -> RegularStruct {
RegularStruct {
x: 0,
// Change field order (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_order_regular_struct() -> RegularStruct {
RegularStruct {
x: 3,
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_order_regular_struct() -> RegularStruct {
RegularStruct {
y: 4,
// Add field (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_field_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
x: 3,
RegularStruct {
x: 7,
+ // --
.. struct1
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_field_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
x: 3,
// Change field label (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_label_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
x: 3,
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_label_regular_struct() -> RegularStruct {
let struct1 = RegularStruct {
x: 3,
}
// Change constructor path (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_path_regular_struct() {
- let _ = RegularStruct {
+ let _ = RegularStruct {
x: 0,
y: 1,
z: 2,
};
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_path_regular_struct() {
let _ = RegularStruct2 {
x: 0,
// Change constructor path indirectly (regular struct)
pub mod change_constructor_path_indirectly_regular_struct {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::RegularStruct as Struct;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::RegularStruct2 as Struct;
#[rustc_clean(
except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
pub fn function() -> Struct {
Struct {
x: 0,
pub struct TupleStruct(i32, i64, i16);
// Change field value (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_field_value_tuple_struct() -> TupleStruct {
TupleStruct(0, 1, 2)
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_field_value_tuple_struct() -> TupleStruct {
TupleStruct(0, 1, 3)
}
pub struct TupleStruct2(u16, u16, u16);
// Change constructor path (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_constructor_path_tuple_struct() {
- let _ = TupleStruct(0, 1, 2);
+ let _ = TupleStruct (0, 1, 2);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_constructor_path_tuple_struct() {
let _ = TupleStruct2(0, 1, 2);
}
// Change constructor path indirectly (tuple struct)
pub mod change_constructor_path_indirectly_tuple_struct {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::TupleStruct as Struct;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::TupleStruct2 as Struct;
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
#[rustc_clean(
cfg="cfail2",
except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
// the same between rev2 and rev3.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// Layout ----------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub struct LayoutPacked;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[repr(packed)]
pub struct LayoutPacked;
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct LayoutC;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
#[repr(C)]
struct LayoutC;
// Tuple Struct Change Field Type ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct TupleStructFieldType(i32);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
// Note that changing the type of a field does not change the type of the struct or enum, but
// adding/removing fields or changing a fields name or visibility does.
struct TupleStructFieldType(
// Tuple Struct Add Field ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct TupleStructAddField(i32);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct TupleStructAddField(
i32,
u32
// Tuple Struct Field Visibility -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct TupleStructFieldVisibility(char);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct TupleStructFieldVisibility(pub char);
// Record Struct Field Type ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct RecordStructFieldType { x: f32 }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
// Note that changing the type of a field does not change the type of the struct or enum, but
// adding/removing fields or changing a fields name or visibility does.
struct RecordStructFieldType {
// Record Struct Field Name ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct RecordStructFieldName { x: f32 }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct RecordStructFieldName { y: f32 }
// Record Struct Add Field -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct RecordStructAddField { x: f32 }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct RecordStructAddField {
x: f32,
y: () }
// Record Struct Field Visibility ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct RecordStructFieldVisibility { x: f32 }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct RecordStructFieldVisibility {
pub x: f32
}
// Add Lifetime Parameter ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
// Add Lifetime Parameter Bound ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddLifetimeParameterBound<'a, 'b: 'a>(
&'a f32,
&'b f64
);
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
&'a f32,
&'b f64)
// Add Type Parameter ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddTypeParameter<T1>(T1, T1);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddTypeParameter<T1, T2>(
// The field contains the parent's Generics, so it's dirty even though its
// type hasn't changed.
// Add Type Parameter Bound ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddTypeParameterBound<T>(T);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddTypeParameterBound<T: Send>(
T
);
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct AddTypeParameterBoundWhereClause<T>(T);
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
struct AddTypeParameterBoundWhereClause<T>(
T
) where T: Sync;
// Note: there is no #[cfg(...)], so this is ALWAYS compiled
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub struct EmptyStruct;
// Visibility ------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
struct Visibility;
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub struct Visibility;
struct ReferencedType1;
// Tuple Struct Change Field Type Indirectly -----------------------------------
mod tuple_struct_change_field_type_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as FieldType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as FieldType;
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
struct TupleStruct(
FieldType
);
// Record Struct Change Field Type Indirectly -----------------------------------
mod record_struct_change_field_type_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedType1 as FieldType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedType2 as FieldType;
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
struct RecordStruct {
_x: FieldType
}
// Change Trait Bound Indirectly -----------------------------------------------
mod change_trait_bound_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
struct Struct<T: Trait>(T);
}
// Change Trait Bound Indirectly In Where Clause -------------------------------
mod change_trait_bound_indirectly_in_where_clause {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait1 as Trait;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait2 as Trait;
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
struct Struct<T>(T) where T : Trait;
}
// the same between rev2 and rev3.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change trait visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitVisibility { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub trait TraitVisibility { }
// Change trait unsafety
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitUnsafety { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
unsafe trait TraitUnsafety { }
// Add method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddMethod {
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub trait TraitAddMethod {
fn method();
}
// Change name of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeMethodName {
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeMethodName {
fn methodChanged();
}
// Add return type to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddReturnType {
- fn method();
+ //-----------------------------------------------------
+ //--------------------------
+ //-----------------------------------------------------
+ //--------------------------
+ fn method() ;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddReturnType {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method() -> u32;
}
// Change return type of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeReturnType {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
fn method() -> u32;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeReturnType {
#[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method() -> u64;
}
// Add parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddParameterToMethod {
- fn method();
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ fn method( );
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddParameterToMethod {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(a: u32);
}
// Change name of method parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeMethodParameterName {
+ //------------------------------------------------------
+ //----------------------------------------------
+ //--------------------------
+ //----------------------------------------------
+ //--------------------------
fn method(a: u32);
+
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
fn with_default(x: i32) {}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeMethodParameterName {
// FIXME(#38501) This should preferably always be clean.
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(b: u32);
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn with_default(y: i32) {}
}
// Change type of method parameter (i32 => i64)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeMethodParameterType {
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
fn method(a: i32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeMethodParameterType {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(a: i64);
}
// Change type of method parameter (&i32 => &mut i32)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeMethodParameterTypeRef {
- fn method(a: &i32);
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ fn method(a: & i32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeMethodParameterTypeRef {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(a: &mut i32);
}
// Change order of method parameters
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeMethodParametersOrder {
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
fn method(a: i32, b: i64);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeMethodParametersOrder {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(b: i64, a: i32);
}
// Add default implementation to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddMethodAutoImplementation {
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddMethodAutoImplementation {
#[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method() { }
}
// Change order of methods
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeOrderOfMethods {
fn method0();
fn method1();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeOrderOfMethods {
fn method1();
fn method0();
// Change mode of self parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeModeSelfRefToMut {
- fn method(&self);
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ fn method(& self);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeModeSelfRefToMut {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(&mut self);
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeModeSelfOwnToMut: Sized {
- fn method(self) {}
+ // ----------------------------------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------------------------------
+ // -------------------------
+ fn method( self) {}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeModeSelfOwnToMut: Sized {
#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(mut self) {}
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeModeSelfOwnToRef {
- fn method(self);
+ // ----------------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------------
+ // -------------------------
+ fn method( self);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeModeSelfOwnToRef {
#[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method(&self);
}
// Add unsafe modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddUnsafeModifier {
- fn method();
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ fn method() ;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddUnsafeModifier {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
unsafe fn method();
}
// Add extern modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddExternModifier {
- fn method();
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ fn method() ;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddExternModifier {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
extern "C" fn method();
}
// Change extern "C" to extern "stdcall"
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeExternCToRustIntrinsic {
- extern "C" fn method();
+ // ----------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------
+ // -------------------------
+ extern "C" fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeExternCToRustIntrinsic {
#[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
extern "stdcall" fn method();
}
// Add type parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTypeParameterToMethod {
- fn method();
+ // -------------------------------------------------------------------------------
+ // -------------------------
+ // -------------------------------------------------------------------------------
+ // -------------------------
+ fn method ();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTypeParameterToMethod {
#[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T>();
}
// Add lifetime parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeParameterToMethod {
- fn method();
+ // ----------------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------------
+ // -------------------------
+ fn method ();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeParameterToMethod {
#[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<'a>();
}
trait ReferencedTrait1 { }
// Add trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitBoundToMethodTypeParameter {
- fn method<T>();
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T >();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitBoundToMethodTypeParameter {
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T: ReferencedTrait0>();
}
// Add builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltinBoundToMethodTypeParameter {
- fn method<T>();
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T >();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundToMethodTypeParameter {
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T: Sized>();
}
// Add lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToMethodLifetimeParameter {
- fn method<'a, 'b>(a: &'a u32, b: &'b u32);
-}
-
-#[cfg(not(cfail1))]
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ fn method<'a, 'b >(a: &'a u32, b: &'b u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToMethodLifetimeParameter {
#[rustc_clean(
except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
cfg="cfail2",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
}
// Add second trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondTraitBoundToMethodTypeParameter {
- fn method<T: ReferencedTrait0>();
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T: ReferencedTrait0 >();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondTraitBoundToMethodTypeParameter {
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T: ReferencedTrait0 + ReferencedTrait1>();
}
// Add second builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
- fn method<T: Sized>();
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T: Sized >();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T: Sized + Sync>();
}
// Add second lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
- fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32);
-}
-
-#[cfg(not(cfail1))]
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ fn method<'a, 'b, 'c: 'a >(a: &'a u32, b: &'b u32, c: &'c u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
#[rustc_clean(
except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
cfg="cfail2",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
}
// Add associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddAssociatedType {
-
- #[rustc_clean(except="hir_owner", cfg="cfail2")]
- #[rustc_clean(cfg="cfail3")]
+ //--------------------------
+ //--------------------------
+ // -------------
+
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddAssociatedType {
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
type Associated;
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method();
}
// Add trait bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitBoundToAssociatedType {
- type Associated;
+ // ---------------------------------------------
+ // -------------------------
+ // ---------------------------------------------
+ // -------------------------
+ type Associated ;
fn method();
}
// Apparently the type bound contributes to the predicates of the trait, but
// does not change the associated item itself.
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitBoundToAssociatedType {
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
type Associated: ReferencedTrait0;
fn method();
// Add lifetime bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToAssociatedType<'a> {
- type Associated;
+ // ---------------------------------------------
+ // -------------------------
+ // ---------------------------------------------
+ // -------------------------
+ type Associated ;
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToAssociatedType<'a> {
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
type Associated: 'a;
fn method();
// Add default to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddDefaultToAssociatedType {
type Associated;
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddDefaultToAssociatedType {
#[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
type Associated = ReferenceType0;
fn method();
// Add associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddAssociatedConstant {
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddAssociatedConstant {
const Value: u32;
// Add initializer to associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddInitializerToAssociatedConstant {
const Value: u32;
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddInitializerToAssociatedConstant {
#[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
const Value: u32 = 1;
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method();
}
// Change type of associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitChangeTypeOfAssociatedConstant {
+ // -----------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------
+ // -------------------------
const Value: u32;
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
fn method();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitChangeTypeOfAssociatedConstant {
#[rustc_clean(except="hir_owner,type_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,type_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
const Value: f64;
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method();
}
// Add super trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSuperTrait { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSuperTrait : ReferencedTrait0 { }
// Add builtin bound (Send or Copy)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltiBound { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltiBound : Send { }
// Add 'static lifetime bound to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddStaticLifetimeBound { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddStaticLifetimeBound : 'static { }
// Add super trait as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
// Add builtin bound as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
// Add 'static bounds as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
// Add type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTypeParameterToTrait { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTypeParameterToTrait<T> { }
// Add lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeParameterToTrait { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeParameterToTrait<'a> { }
// Add trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
// Add lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
// Add lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
// Add builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
// Add second type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondTypeParameterToTrait<T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondTypeParameterToTrait<T, S> { }
// Add second lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeParameterToTrait<'a> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
// Add second trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
// Add second lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
// Add second lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
// Add second builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
// Add trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
// Add lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
// Add lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
// Add builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
// Add second trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
where T: ReferencedTrait0 + ReferencedTrait1 { }
// Add second lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
// Add second lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
// Add second builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
// Change return type of method indirectly by modifying a use statement
mod change_return_type_of_method_indirectly_use {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferenceType0 as ReturnType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferenceType1 as ReturnType;
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
trait TraitChangeReturnType {
#[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method() -> ReturnType;
}
}
// Change type of method parameter indirectly by modifying a use statement
mod change_method_parameter_type_indirectly_by_use {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferenceType0 as ArgType;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferenceType1 as ArgType;
#[rustc_clean(cfg="cfail2")]
// Change trait bound of method type parameter indirectly by modifying a use statement
mod change_method_parameter_type_bound_indirectly_by_use {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait0 as Bound;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait1 as Bound;
#[rustc_clean(cfg="cfail2")]
// Change trait bound of method type parameter in where clause indirectly
// by modifying a use statement
mod change_method_parameter_type_bound_indirectly_by_use_where {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait0 as Bound;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait1 as Bound;
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
trait TraitChangeBoundOfMethodTypeParameterWhere {
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method<T>(a: T) where T: Bound;
}
}
// Change trait bound of trait type parameter indirectly by modifying a use statement
mod change_method_type_parameter_bound_indirectly {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait0 as Bound;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait1 as Bound;
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
// Change trait bound of trait type parameter in where clause indirectly
// by modifying a use statement
mod change_method_type_parameter_bound_indirectly_where {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1,cfail4))]
use super::ReferencedTrait0 as Bound;
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1,cfail4)))]
use super::ReferencedTrait1 as Bound;
#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
trait TraitChangeTraitBoundWhere<T> where T: Bound {
fn method(a: T);
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change Method Name -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeMethodNameTrait {
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeMethodNameTrait for Foo {
fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub trait ChangeMethodNameTrait {
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name2();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeMethodNameTrait for Foo {
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name2() { }
}
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeMethodBodyTrait for Foo {
- fn method_name() { }
+ // ----------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------
+ // -------------------------
+ fn method_name() {
+ //
+ }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeMethodBodyTrait for Foo {
#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name() {
()
}
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeMethodBodyTraitInlined for Foo {
+ // ------------------------------------------------------------------------
+ // -------------------------
+ // ------------------------------------------------------------------------
+ // -------------------------
#[inline]
- fn method_name() { }
+ fn method_name() {
+ // -----
+ }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeMethodBodyTraitInlined for Foo {
#[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
#[inline]
fn method_name() {
panic!()
// Change Method Selfness ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeMethodSelfnessTrait {
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeMethodSelfnessTrait for Foo {
fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait ChangeMethodSelfnessTrait {
fn method_name(&self);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeMethodSelfnessTrait for Foo {
#[rustc_clean(
except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
cfg="cfail2",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
fn method_name(&self) {
()
}
// Change Method Selfness -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait RemoveMethodSelfnessTrait {
fn method_name(&self);
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl RemoveMethodSelfnessTrait for Foo {
fn method_name(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait RemoveMethodSelfnessTrait {
fn method_name();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl RemoveMethodSelfnessTrait for Foo {
#[rustc_clean(
except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
cfg="cfail2",
)]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
fn method_name() {}
}
// Change Method Selfmutness -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeMethodSelfmutnessTrait {
fn method_name(&self);
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeMethodSelfmutnessTrait for Foo {
- fn method_name(&self) { }
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(& self) {}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait ChangeMethodSelfmutnessTrait {
fn method_name(&mut self);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeMethodSelfmutnessTrait for Foo {
#[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name(&mut self) {}
}
// Change item kind -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeItemKindTrait {
fn name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeItemKindTrait for Foo {
fn name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait ChangeItemKindTrait {
type name;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeItemKindTrait for Foo {
type name = ();
}
// Remove item -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait RemoveItemTrait {
type TypeName;
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl RemoveItemTrait for Foo {
type TypeName = ();
fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait RemoveItemTrait {
type TypeName;
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl RemoveItemTrait for Foo {
type TypeName = ();
}
// Add item -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait AddItemTrait {
type TypeName;
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl AddItemTrait for Foo {
type TypeName = ();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait AddItemTrait {
type TypeName;
fn method_name();
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl AddItemTrait for Foo {
type TypeName = ();
fn method_name() { }
// Change has-value -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeHasValueTrait {
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeHasValueTrait for Foo {
fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub trait ChangeHasValueTrait {
#[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeHasValueTrait for Foo {
fn method_name() { }
}
fn method_name();
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl AddDefaultTrait for Foo {
- fn method_name() { }
+ // -------------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name() { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl AddDefaultTrait for Foo {
#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
default fn method_name() { }
}
// Add arguments
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait AddArgumentTrait {
fn method_name(&self);
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl AddArgumentTrait for Foo {
- fn method_name(&self) { }
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(&self ) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait AddArgumentTrait {
fn method_name(&self, x: u32);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl AddArgumentTrait for Foo {
#[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name(&self, _x: u32) { }
}
// Change argument type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub trait ChangeArgumentTypeTrait {
fn method_name(&self, x: u32);
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeArgumentTypeTrait for Foo {
- fn method_name(&self, _x: u32) { }
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(&self, _x: u32 ) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
pub trait ChangeArgumentTypeTrait {
fn method_name(&self, x: char);
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeArgumentTypeTrait for Foo {
#[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn method_name(&self, _x: char) { }
}
fn id(t: T) -> T;
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl AddTypeParameterToImpl<u32> for Bar<u32> {
fn id(t: u32) -> u32 { t }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
-impl<T> AddTypeParameterToImpl<T> for Bar<T> {
+#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<TTT> AddTypeParameterToImpl<TTT> for Bar<TTT> {
#[rustc_clean(
except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
cfg="cfail2",
)]
#[rustc_clean(cfg="cfail3")]
- fn id(t: T) -> T { t }
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn id(t: TTT) -> TTT { t }
}
fn id(self) -> Self;
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl ChangeSelfTypeOfImpl for u32 {
fn id(self) -> Self { self }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl ChangeSelfTypeOfImpl for u64 {
#[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn id(self) -> Self { self }
}
fn id(self) -> Self;
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl<T> AddLifetimeBoundToImplParameter for T {
fn id(self) -> Self { self }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl<T: 'static> AddLifetimeBoundToImplParameter for T {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn id(self) -> Self { self }
}
fn id(self) -> Self;
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl<T> AddTraitBoundToImplParameter for T {
fn id(self) -> Self { self }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl<T: Clone> AddTraitBoundToImplParameter for T {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
fn id(self) -> Self { self }
}
fn add_no_mangle_to_method(&self) { }
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl AddNoMangleToMethod for Foo {
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // ---------
fn add_no_mangle_to_method(&self) { }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl AddNoMangleToMethod for Foo {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
#[no_mangle]
fn add_no_mangle_to_method(&self) { }
}
fn make_method_inline(&self) -> u8 { 0 }
}
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
impl MakeMethodInline for Foo {
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // ------
fn make_method_inline(&self) -> u8 { 0 }
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
impl MakeMethodInline for Foo {
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
#[inline]
fn make_method_inline(&self) -> u8 { 0 }
}
// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
#![allow(warnings)]
#![feature(rustc_attrs)]
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change constant operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn const_negation() -> i32 {
-10
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn const_negation() -> i32 {
- -1
+ -1
}
// Change constant operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn const_bitwise_not() -> i32 {
!100
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn const_bitwise_not() -> i32 {
- !99
+ !99
}
// Change variable operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn var_negation(x: i32, y: i32) -> i32 {
-x
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn var_negation(x: i32, y: i32) -> i32 {
-y
}
// Change variable operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
!x
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
!y
}
// Change variable operand of deref --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn var_deref(x: &i32, y: &i32) -> i32 {
*x
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn var_deref(x: &i32, y: &i32) -> i32 {
*y
}
// Change first constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn first_const_add() -> i32 {
1 + 3
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn first_const_add() -> i32 {
2 + 3
}
// Change second constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn second_const_add() -> i32 {
1 + 2
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn second_const_add() -> i32 {
1 + 3
}
// Change first variable operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn first_var_add(a: i32, b: i32) -> i32 {
a + 2
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn first_var_add(a: i32, b: i32) -> i32 {
b + 2
}
// Change second variable operand of addition ----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn second_var_add(a: i32, b: i32) -> i32 {
1 + a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn second_var_add(a: i32, b: i32) -> i32 {
1 + b
}
// Change operator from + to - -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn plus_to_minus(a: i32) -> i32 {
1 + a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn plus_to_minus(a: i32) -> i32 {
1 - a
}
// Change operator from + to * -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn plus_to_mult(a: i32) -> i32 {
1 + a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn plus_to_mult(a: i32) -> i32 {
1 * a
}
// Change operator from + to / -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn plus_to_div(a: i32) -> i32 {
1 + a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn plus_to_div(a: i32) -> i32 {
1 / a
}
// Change operator from + to % -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn plus_to_mod(a: i32) -> i32 {
1 + a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn plus_to_mod(a: i32) -> i32 {
1 % a
}
// Change operator from && to || -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn and_to_or(a: bool, b: bool) -> bool {
a && b
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn and_to_or(a: bool, b: bool) -> bool {
a || b
}
// Change operator from & to | -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
1 & a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
1 | a
}
// Change operator from & to ^ -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
1 & a
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
1 ^ a
}
// Change operator from & to << ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn bitwise_and_to_lshift(a: i32) -> i32 {
- a & 1
+ a & 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn bitwise_and_to_lshift(a: i32) -> i32 {
a << 1
}
// Change operator from & to >> ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn bitwise_and_to_rshift(a: i32) -> i32 {
- a & 1
+ a & 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn bitwise_and_to_rshift(a: i32) -> i32 {
a >> 1
}
// Change operator from == to != -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn eq_to_uneq(a: i32) -> bool {
a == 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn eq_to_uneq(a: i32) -> bool {
a != 1
}
// Change operator from == to < ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn eq_to_lt(a: i32) -> bool {
a == 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn eq_to_lt(a: i32) -> bool {
- a < 1
+ a < 1
}
// Change operator from == to > ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn eq_to_gt(a: i32) -> bool {
a == 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn eq_to_gt(a: i32) -> bool {
- a > 1
+ a > 1
}
// Change operator from == to <= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn eq_to_le(a: i32) -> bool {
a == 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn eq_to_le(a: i32) -> bool {
a <= 1
}
// Change operator from == to >= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn eq_to_ge(a: i32) -> bool {
a == 1
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn eq_to_ge(a: i32) -> bool {
a >= 1
}
// Change type in cast expression ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn type_cast(a: u8) -> u64 {
let b = a as i32;
let c = b as u64;
c
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn type_cast(a: u8) -> u64 {
let b = a as u32;
let c = b as u64;
// Change value in cast expression ---------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn value_cast(a: u32) -> i32 {
1 as i32
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn value_cast(a: u32) -> i32 {
2 as i32
}
// Change place in assignment --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn place() -> i32 {
let mut x = 10;
let mut y = 11;
x
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn place() -> i32 {
let mut x = 10;
let mut y = 11;
// Change r-value in assignment ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn rvalue() -> i32 {
let mut x = 10;
x = 9;
x
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn rvalue() -> i32 {
let mut x = 10;
x = 8;
// Change index into slice -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
s[i]
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
s[j]
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_body() {
let mut _x = 0;
while let Some(0u32) = None {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_body() {
let mut _x = 0;
while let Some(0u32) = None {
// Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_condition() {
let mut _x = 0;
while let Some(0u32) = None {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_condition() {
let mut _x = 0;
while let Some(1u32) = None {
// Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_break() {
let mut _x = 0;
while let Some(0u32) = None {
_x = 1;
+ // ---
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_break() {
let mut _x = 0;
while let Some(0u32) = None {
// Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label() {
let mut _x = 0;
- while let Some(0u32) = None {
+ while let Some(0u32) = None {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label() {
let mut _x = 0;
'label: while let Some(0u32) = None {
// Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: while let Some(0u32) = None {
_x = 1;
- break;
+ break ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: while let Some(0u32) = None {
// Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_break_label() {
let mut _x = 0;
'outer: while let Some(0u32) = None {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
'outer: while let Some(0u32) = None {
}
// Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: while let Some(0u32) = None {
_x = 1;
- continue;
+ continue ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: while let Some(0u32) = None {
// Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_label() {
let mut _x = 0;
'outer: while let Some(0u32) = None {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
'outer: while let Some(0u32) = None {
// Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_to_break() {
let mut _x = 0;
while let Some(0u32) = None {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_to_break() {
let mut _x = 0;
while let Some(0u32) = None {
_x = 1;
- break;
+ break ;
}
}
// rev3 and make sure that the hash has not changed.
// build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
#![allow(warnings)]
#![feature(rustc_attrs)]
// Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_body() {
let mut _x = 0;
while true {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_body() {
let mut _x = 0;
while true {
// Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_loop_condition() {
let mut _x = 0;
- while true {
+ while true {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_loop_condition() {
let mut _x = 0;
while false {
// Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_break() {
let mut _x = 0;
while true {
_x = 1;
+ // ---
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_break() {
let mut _x = 0;
while true {
// Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label() {
let mut _x = 0;
- while true {
+ while true {
_x = 1;
break;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label() {
let mut _x = 0;
'label: while true {
// Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: while true {
_x = 1;
- break;
+ break ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_break() {
let mut _x = 0;
'label: while true {
// Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_break_label() {
let mut _x = 0;
'outer: while true {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
'outer: while true {
// Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: while true {
_x = 1;
- continue;
+ continue ;
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
pub fn add_loop_label_to_continue() {
let mut _x = 0;
'label: while true {
// Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_label() {
let mut _x = 0;
'outer: while true {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
'outer: while true {
// Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
pub fn change_continue_to_break() {
let mut _x = 0;
while true {
}
}
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
pub fn change_continue_to_break() {
let mut _x = 0;
while true {
_x = 1;
- break;
+ break ;
}
}
// This test makes sure that just changing a definition's location in the
// source file also changes its incr. comp. hash, if debuginfo is enabled.
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
// ignore-asmjs wasm2js does not support source maps yet
// compile-flags: -g -Z query-dep-graph
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
#![feature(rustc_attrs)]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")]
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
pub fn main() {}
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
pub fn main() {}
// This test makes sure that just changing a definition's location in the
// source file also changes its incr. comp. hash, if debuginfo is enabled.
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
// compile-flags: -C overflow-checks=on -Z query-dep-graph
#![feature(rustc_attrs)]
+#![feature(bench_black_box)]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
pub fn main() {
- let _ = 0u8 + 1;
+ if std::hint::black_box(false) {
+ panic!()
+ }
}
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
pub fn main() {
- let _ = 0u8 + 1;
+ if std::hint::black_box(false) {
+ panic!()
+ }
}
-// revisions: cfail1 cfail2
+// revisions: cfail1 cfail2 cfail3 cfail4
// compile-flags: -Z query-dep-graph
+// [cfail3]compile-flags: -Zincremental-relative-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
// Therefore, the compiler deduces (correctly) that typeck is not
// needed even for callers of `x`.
-
pub mod x {
- #[cfg(cfail1)]
+ #[cfg(any(cfail1, cfail3))]
pub fn x() {
println!("{}", "1");
}
- #[cfg(cfail2)]
- #[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg="cfail2")]
+ #[cfg(any(cfail2, cfail4))]
+ #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")]
+ #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")]
pub fn x() {
println!("{}", "2");
}
pub mod y {
use x;
- #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail4")]
pub fn y() {
x::x();
}
pub mod z {
use y;
- #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail4")]
pub fn z() {
y::y();
}
// ends up with any spans in its LLVM bitecode, so LLVM is able to skip
// re-building any modules which import 'inlined_fn'
-// revisions: cfail1 cfail2 cfail3
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
// compile-flags: -Z query-dep-graph -O
// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
-#![crate_type="rlib"]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
- cfg="cfail2",
- kind="no")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
- cfg="cfail3",
- kind="post-lto")]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
- cfg="cfail2",
- kind="post-lto")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
- cfg="cfail3",
- kind="post-lto")]
+#![crate_type = "rlib"]
+#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail3",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail5",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail6",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail2",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail3",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail5",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail6",
+ kind = "post-lto"
+)]
mod foo {
// Trivial functions like this one are imported very reliably by ThinLTO.
- #[cfg(cfail1)]
+ #[cfg(any(cfail1, cfail4))]
pub fn inlined_fn() -> u32 {
1234
}
- #[cfg(not(cfail1))]
+ #[cfg(not(any(cfail1, cfail4)))]
pub fn inlined_fn() -> u32 {
1234
}
graph [fontname="Courier, monospace"];
node [fontname="Courier, monospace"];
edge [fontname="Courier, monospace"];
- bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/> 13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
- bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/> 12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb1 + 0) at 15:2-15:2<br/> 15:2-15:2: @3.Return: return</td></tr><tr><td align="left" balign="left">bb3: Return</td></tr></table>>];
- bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/> 11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb5]</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
- bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>];
- bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=<false>];
- bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<otherwise>];
+ bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br/> 13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>];
+ bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18<br/> 12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2<br/> 15:2-15:2: @4.Return: return</td></tr><tr><td align="left" balign="left">bb4: Return</td></tr></table>>];
+ bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br/> 11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
+ bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br/> </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
+ bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
+ bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
+ bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
+ bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
}
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
+ StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
+ _9 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
-+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22
++ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22
}
bb1: {
let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10
bb0: {
-+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
- falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
++ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 10:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+ goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
}
bb1: {
++ Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:11:5 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+ }
+
+ bb2: {
StorageLive(_2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
- _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+ _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
// mir::Constant
// + span: /the/src/instrument_coverage.rs:12:12: 12:15
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
}
- bb2: {
- switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+ bb3: {
+ switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
}
- bb3: {
-+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
-+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
+ bb4: {
++ Coverage::Expression(4294967293) = 4294967294 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
++ Coverage::Expression(4294967294) = 4294967295 - 2 for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
_0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
}
- bb4: {
-+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+ bb5: {
++ Coverage::Counter(2) for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
_1 = const (); // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
- goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+ goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
}
- bb5 (cleanup): {
+ bb6 (cleanup): {
resume; // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2
}
}
--- /dev/null
+- // MIR for `align_of` before LowerIntrinsics
++ // MIR for `align_of` after LowerIntrinsics
+
+ fn align_of() -> usize {
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:18:25: 18:30
+
+ bb0: {
+- _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+- // mir::Constant
+- // + span: $DIR/lower_intrinsics.rs:19:5: 19:40
+- // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(Scalar(<ZST>)) }
++ _0 = AlignOf(T); // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+ }
+
+ bb1: {
+ return; // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+ }
+
+ bb2 (cleanup): {
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+ }
+ }
+
+ // MIR for `discriminant` after LowerIntrinsics
fn discriminant(_1: T) -> () {
- debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:68:24: 68:25
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:68:30: 68:30
- let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
- let mut _3: &T; // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
- let _4: &T; // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
- let _5: u8; // in scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
- let mut _6: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- let _7: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- let _8: i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:43: 70:44
- let _9: u8; // in scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
- let mut _10: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- let _11: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- let _12: (); // in scope 0 at $DIR/lower_intrinsics.rs:71:43: 71:45
- let _13: isize; // in scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
- let mut _14: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- let _15: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- let _16: E; // in scope 0 at $DIR/lower_intrinsics.rs:72:43: 72:47
- let mut _17: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- let mut _18: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- let mut _19: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+ debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:73:24: 73:25
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:73:30: 73:30
+ let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+ let mut _3: &T; // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+ let _4: &T; // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+ let _5: u8; // in scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+ let mut _6: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+ let _7: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+ let _8: i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:43: 75:44
+ let _9: u8; // in scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+ let mut _10: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ let _11: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ let _12: (); // in scope 0 at $DIR/lower_intrinsics.rs:76:43: 76:45
+ let _13: isize; // in scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+ let mut _14: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ let _15: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ let _16: E; // in scope 0 at $DIR/lower_intrinsics.rs:77:43: 77:47
+ let mut _17: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ let mut _18: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ let mut _19: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
bb0: {
- StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
- StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
- StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
- _4 = &_1; // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
- _3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-- _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
+ StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+ StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+ StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+ _4 = &_1; // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+ _3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+- _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:69:5: 69:41
+- // + span: $DIR/lower_intrinsics.rs:74:5: 74:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<T>}, val: Value(Scalar(<ZST>)) }
-+ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
++ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
}
bb1: {
- StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:69:44: 69:45
- StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
- StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
- StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
- StorageLive(_6); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+ StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:74:44: 74:45
+ StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+ StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+ StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+ StorageLive(_6); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+ StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+ _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
// ty::Const
// + ty: &i32
// + val: Unevaluated(discriminant, [T], Some(promoted[2]))
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
- _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
+ // + span: $DIR/lower_intrinsics.rs:75:42: 75:44
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
+ _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+ _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:70:5: 70:41
+- // + span: $DIR/lower_intrinsics.rs:75:5: 75:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<i32>}, val: Value(Scalar(<ZST>)) }
-+ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-+ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
++ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
++ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
}
bb2: {
- StorageDead(_6); // scope 0 at $DIR/lower_intrinsics.rs:70:44: 70:45
- StorageDead(_7); // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
- StorageDead(_5); // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
- StorageLive(_9); // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
- StorageLive(_10); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
+ StorageDead(_6); // scope 0 at $DIR/lower_intrinsics.rs:75:44: 75:45
+ StorageDead(_7); // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+ StorageDead(_5); // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+ StorageLive(_9); // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+ StorageLive(_10); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
// ty::Const
// + ty: &()
// + val: Unevaluated(discriminant, [T], Some(promoted[1]))
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
- // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
- _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
+ // + span: $DIR/lower_intrinsics.rs:76:42: 76:45
+ // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
+ _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+ _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:71:5: 71:41
+- // + span: $DIR/lower_intrinsics.rs:76:5: 76:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<()>}, val: Value(Scalar(<ZST>)) }
-+ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-+ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
++ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
++ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
}
bb3: {
- StorageDead(_10); // scope 0 at $DIR/lower_intrinsics.rs:71:45: 71:46
- StorageDead(_11); // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
- StorageDead(_9); // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
- StorageLive(_13); // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
- StorageLive(_14); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
+ StorageDead(_10); // scope 0 at $DIR/lower_intrinsics.rs:76:45: 76:46
+ StorageDead(_11); // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+ StorageDead(_9); // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+ StorageLive(_13); // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+ StorageLive(_14); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
// ty::Const
// + ty: &E
// + val: Unevaluated(discriminant, [T], Some(promoted[0]))
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
- // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
- _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
+ // + span: $DIR/lower_intrinsics.rs:77:42: 77:47
+ // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
+ _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+ _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:72:5: 72:41
+- // + span: $DIR/lower_intrinsics.rs:77:5: 77:41
- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<E>}, val: Value(Scalar(<ZST>)) }
-+ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-+ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
++ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
++ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
}
bb4: {
- StorageDead(_14); // scope 0 at $DIR/lower_intrinsics.rs:72:47: 72:48
- StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
- StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
- _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:68:30: 73:2
- drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:73:1: 73:2
+ StorageDead(_14); // scope 0 at $DIR/lower_intrinsics.rs:77:47: 77:48
+ StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+ StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:73:30: 78:2
+ drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:78:1: 78:2
}
bb5: {
- return; // scope 0 at $DIR/lower_intrinsics.rs:73:2: 73:2
+ return; // scope 0 at $DIR/lower_intrinsics.rs:78:2: 78:2
}
bb6 (cleanup): {
- resume; // scope 0 at $DIR/lower_intrinsics.rs:68:1: 73:2
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:73:1: 78:2
}
}
// MIR for `f_u64` before PreCodegen
fn f_u64() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
- let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
- scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
- debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:39:16: 39:16
+ let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
+ debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
- _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
- StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:35:5: 35:21
+ // + span: $DIR/lower_intrinsics.rs:40:5: 40:21
// + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
- StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
- return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
+ StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+ return; // scope 0 at $DIR/lower_intrinsics.rs:41:2: 41:2
}
}
// MIR for `f_unit` before PreCodegen
fn f_unit() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:28:17: 28:17
- let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
- scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
- debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
- let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
- scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:33:17: 33:17
+ let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+ scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
+ debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+ let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+ scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
- StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
- _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
+ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+ StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+ _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:29:5: 29:19
+ // + span: $DIR/lower_intrinsics.rs:34:5: 34:19
// + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
- StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:29:18: 29:19
- return; // scope 0 at $DIR/lower_intrinsics.rs:30:2: 30:2
+ StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+ StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:34:18: 34:19
+ return; // scope 0 at $DIR/lower_intrinsics.rs:35:2: 35:2
}
}
+ // MIR for `forget` after LowerIntrinsics
fn forget(_1: T) -> () {
- debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:18:18: 18:19
- let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:18:24: 18:24
- let mut _2: T; // in scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
+ debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:23:18: 23:19
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:23:24: 23:24
+ let mut _2: T; // in scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
bb0: {
- StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
- _2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
-- _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
+ StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+ _2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+- _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:19:5: 19:29
+- // + span: $DIR/lower_intrinsics.rs:24:5: 24:29
- // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(Scalar(<ZST>)) }
-+ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
-+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
++ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
}
bb1: {
- StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:19:31: 19:32
- goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:20:1: 20:2
+ StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:31: 24:32
+ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:25:1: 25:2
}
bb2: {
- return; // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+ return; // scope 0 at $DIR/lower_intrinsics.rs:25:2: 25:2
}
bb3 (cleanup): {
- resume; // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
}
}
+ // MIR for `non_const` after LowerIntrinsics
fn non_const() -> usize {
- let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:55:26: 55:31
- let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
- let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:58:5: 58:14
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:60:26: 60:31
+ let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+ let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:63:5: 63:14
scope 1 {
- debug size_of_t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:57:9: 57:18
+ debug size_of_t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:62:9: 62:18
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
- _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:57:21: 57:51
+ StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+ _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:62:21: 62:51
// mir::Constant
- // + span: $DIR/lower_intrinsics.rs:57:21: 57:51
+ // + span: $DIR/lower_intrinsics.rs:62:21: 62:51
// + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(Scalar(<ZST>)) }
- StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
- _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
-- _0 = move _2() -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+ _0 = SizeOf(T); // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
+ StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+ _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+- _0 = move _2() -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++ _0 = SizeOf(T); // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
}
bb1: {
- StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:58:15: 58:16
- StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:59:1: 59:2
- return; // scope 0 at $DIR/lower_intrinsics.rs:59:2: 59:2
+ StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:63:15: 63:16
+ StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:64:1: 64:2
+ return; // scope 0 at $DIR/lower_intrinsics.rs:64:2: 64:2
}
bb2 (cleanup): {
- resume; // scope 0 at $DIR/lower_intrinsics.rs:55:1: 59:2
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:60:1: 64:2
}
}
core::intrinsics::size_of::<T>()
}
+// EMIT_MIR lower_intrinsics.align_of.LowerIntrinsics.diff
+pub fn align_of<T>() -> usize {
+ core::intrinsics::min_align_of::<T>()
+}
+
// EMIT_MIR lower_intrinsics.forget.LowerIntrinsics.diff
pub fn forget<T>(t: T) {
core::intrinsics::forget(t)
+ // MIR for `unreachable` after LowerIntrinsics
fn unreachable() -> ! {
- let mut _0: !; // return place in scope 0 at $DIR/lower_intrinsics.rs:23:25: 23:26
- let mut _1: !; // in scope 0 at $DIR/lower_intrinsics.rs:23:27: 25:2
- let _2: (); // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
- let mut _3: !; // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
+ let mut _0: !; // return place in scope 0 at $DIR/lower_intrinsics.rs:28:25: 28:26
+ let mut _1: !; // in scope 0 at $DIR/lower_intrinsics.rs:28:27: 30:2
+ let _2: (); // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
+ let mut _3: !; // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
scope 1 {
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:47
- StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
-- std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
+ StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:29:5: 29:47
+ StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
+- std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
- // mir::Constant
-- // + span: $DIR/lower_intrinsics.rs:24:14: 24:43
+- // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar(<ZST>)) }
-+ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
++ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
}
bb1 (cleanup): {
- resume; // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
+ resume; // scope 0 at $DIR/lower_intrinsics.rs:28:1: 30:2
}
}
- StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
- StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
- StorageDead(_4); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
-- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
+- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
- StorageDead(_1); // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2
return; // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
}
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
bb0: {
-- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ }
+
+ bb1: {
+- goto -> bb2; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
- }
-
-- bb1: {
+- bb2: {
StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
-- _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
-+ _2 = bar() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+- _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
++ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
// mir::Constant
// + span: $DIR/simplify_cfg.rs:9:12: 9:15
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
}
-- bb2: {
-- switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
-+ bb1: {
-+ switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
- }
-
- bb3: {
+- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+ bb2: {
++ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+ }
+
+- bb4: {
++ bb3: {
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
}
-- bb4: {
-+ bb3: {
+- bb5: {
++ bb4: {
_1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
- goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
}
-- bb5 (cleanup): {
-+ bb4 (cleanup): {
+- bb6 (cleanup): {
++ bb5 (cleanup): {
resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
}
}
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
bb0: {
-- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
-+ falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
}
bb1: {
- falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
-- }
--
-- bb2: {
++ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ }
+
+ bb2: {
StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
- _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
-+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
++ _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
// mir::Constant
// + span: $DIR/simplify_cfg.rs:9:12: 9:15
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
}
-- bb3: {
-- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
-+ bb2: {
-+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+ bb3: {
+ switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
}
-- bb4: {
-+ bb3: {
+ bb4: {
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
- goto -> bb10; // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
+ StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
+ return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
}
-- bb5: {
+ bb5: {
- goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
- }
-
- }
-
- bb8: {
-+ bb4: {
_1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
- goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
- }
-
- bb9: {
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
-- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
-+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+ goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
}
- bb10: {
- }
-
- bb11 (cleanup): {
-+ bb5 (cleanup): {
++ bb6 (cleanup): {
resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
}
}
let mut _5: bool; // in scope 0 at $DIR/while-storage.rs:11:21: 11:22
bb0: {
+ goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6
+ }
+
+ bb1: {
StorageLive(_2); // scope 0 at $DIR/while-storage.rs:10:11: 10:22
StorageLive(_3); // scope 0 at $DIR/while-storage.rs:10:20: 10:21
_3 = _1; // scope 0 at $DIR/while-storage.rs:10:20: 10:21
- _2 = get_bool(move _3) -> bb1; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
+ _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
// mir::Constant
// + span: $DIR/while-storage.rs:10:11: 10:19
// + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
}
- bb1: {
+ bb2: {
StorageDead(_3); // scope 0 at $DIR/while-storage.rs:10:21: 10:22
- switchInt(move _2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
+ switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
}
- bb2: {
+ bb3: {
StorageLive(_4); // scope 0 at $DIR/while-storage.rs:11:12: 11:23
StorageLive(_5); // scope 0 at $DIR/while-storage.rs:11:21: 11:22
_5 = _1; // scope 0 at $DIR/while-storage.rs:11:21: 11:22
- _4 = get_bool(move _5) -> bb3; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+ _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
// mir::Constant
// + span: $DIR/while-storage.rs:11:12: 11:20
// + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
}
- bb3: {
+ bb4: {
StorageDead(_5); // scope 0 at $DIR/while-storage.rs:11:22: 11:23
- switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+ switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
}
- bb4: {
+ bb5: {
StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10
- goto -> bb7; // scope 0 at no-location
+ goto -> bb8; // scope 0 at no-location
}
- bb5: {
+ bb6: {
StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10
StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6
- goto -> bb0; // scope 0 at $DIR/while-storage.rs:10:5: 14:6
+ goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6
}
- bb6: {
- goto -> bb7; // scope 0 at no-location
+ bb7: {
+ goto -> bb8; // scope 0 at no-location
}
- bb7: {
+ bb8: {
StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6
return; // scope 0 at $DIR/while-storage.rs:15:2: 15:2
}
+++ /dev/null
-// Test for issue 85480
-// Pretty print anonymous struct and union types
-
-// pp-exact
-// pretty-compare-only
-
-struct Foo {
- _: union {
- _: struct {
- a: u8,
- b: u16,
- },
- c: u32,
- },
- d: u64,
- e: f32,
-}
-
-type A =
- struct {
- field: u8,
- };
-
-fn main() { }
opt \
link_paths \
remap_paths \
- different_source_dirs \
+ different_source_dirs_rlib \
+ remap_cwd_rlib \
+ remap_cwd_to_empty \
extern_flags
+# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on
+# Windows.
+# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533
+# Issue: https://github.com/rust-lang/rust/issues/88982
+#
+# different_source_dirs_bin \
+# remap_cwd_bin \
+
smoke:
rm -rf $(TMPDIR) && mkdir $(TMPDIR)
$(RUSTC) linker.rs -O
$(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c
cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
-different_source_dirs:
+different_source_dirs_bin:
+ rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+ $(RUSTC) reproducible-build-aux.rs
+ mkdir $(TMPDIR)/test
+ cp reproducible-build.rs $(TMPDIR)/test
+ $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b
+ cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo
+ (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \
+ --remap-path-prefix=$(TMPDIR)/test=/b \
+ --crate-type bin)
+ cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1
+
+different_source_dirs_rlib:
rm -rf $(TMPDIR) && mkdir $(TMPDIR)
$(RUSTC) reproducible-build-aux.rs
mkdir $(TMPDIR)/test
--crate-type rlib)
cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
+remap_cwd_bin:
+ rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+ $(RUSTC) reproducible-build-aux.rs
+ mkdir $(TMPDIR)/test
+ cp reproducible-build.rs $(TMPDIR)/test
+ $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+ -Z remap-cwd-prefix=.
+ cp $(TMPDIR)/reproducible-build $(TMPDIR)/first
+ (cd $(TMPDIR)/test && \
+ $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+ -Z remap-cwd-prefix=.)
+ cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1
+
+remap_cwd_rlib:
+ rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+ $(RUSTC) reproducible-build-aux.rs
+ mkdir $(TMPDIR)/test
+ cp reproducible-build.rs $(TMPDIR)/test
+ $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+ -Z remap-cwd-prefix=.
+ cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+ (cd $(TMPDIR)/test && \
+ $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+ -Z remap-cwd-prefix=.)
+ cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
+remap_cwd_to_empty:
+ rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+ $(RUSTC) reproducible-build-aux.rs
+ mkdir $(TMPDIR)/test
+ cp reproducible-build.rs $(TMPDIR)/test
+ $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+ -Z remap-cwd-prefix=
+ cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+ (cd $(TMPDIR)/test && \
+ $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+ -Z remap-cwd-prefix=)
+ cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
extern_flags:
rm -rf $(TMPDIR) && mkdir $(TMPDIR)
$(RUSTC) reproducible-build-aux.rs
return s
+def set_ld_lib_path():
+ var = os.environ.get("LD_LIB_PATH_ENVVAR")
+ rpath = os.environ.get("HOST_RPATH_DIR")
+ if var and rpath:
+ path = os.environ.get(var)
+ if path:
+ os.environ[var] = rpath + os.pathsep + path
+ else:
+ os.environ[var] = rpath
+
+
def exec_command(command, to_input=None):
child = None
if to_input is None:
if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES]
+set_ld_lib_path()
sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '')
+assert sysroot, "Could not read the rustc sysroot!"
libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET'])))
ret = 0
goto: file://|DOC_PATH|/test_docs/index.html
click: ".srclink"
+wait-for: "#sidebar-toggle"
click: "#sidebar-toggle"
wait-for: 500
fail: true
assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
// However, since there is overflow in the <table>, its scroll width is bigger.
assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
+
+// Checking it works on other doc blocks as well...
+
+// Logically, the ".docblock" and the "<p>" should have the same scroll width.
+compare-elements-property: ("#implementations + details .docblock", "#implementations + details .docblock > p", ["scrollWidth"])
+assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"})
+// However, since there is overflow in the <table>, its scroll width is bigger.
+assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
--- /dev/null
+// We check the background color on the jump to definition links in the source code page.
+goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+
+// Set the theme to dark.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to ayu.
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to light.
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL)
///
/// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
pub struct Foo;
+
+ /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two |
+ /// | ----------- | ----------- | ----------- | ----------- |
+ /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two |
+ ///
+ /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
+ impl Foo {
+ pub fn foo(&self) {}
+ }
}
pub mod summary_table {
--- /dev/null
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "link_to_definition"
+version = "0.1.0"
--- /dev/null
+[package]
+name = "link_to_definition"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
--- /dev/null
+pub struct Bar {
+ pub a: String,
+ pub b: u32,
+}
+
+pub fn foo(_b: &Bar) {}
const EXPECTED = {
'others': [
- { 'path': 'std', 'name': 'str' },
- { 'path': 'std', 'name': 'u8' },
- { 'path': 'std::ffi', 'name': 'CStr' },
+ { 'path': 'std', 'name': 'str', 'href': '../std/primitive.str.html' },
+ { 'path': 'std', 'name': 'u8', 'href': '../std/primitive.u8.html' },
+ { 'path': 'std', 'name': 'str', 'href': '../std/str/index.html' },
+ { 'path': 'std', 'name': 'u8', 'href': '../std/u8/index.html' },
],
};
--- /dev/null
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+// The point of this test is to ensure that the number of "documented" items
+// is higher than in `enum-tuple.rs`.
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+ /// VarOne.
+ VarOne(
+ /// hello!
+ String,
+ ),
+ /// Var Two.
+ VarTwo(
+ /// Hello
+ String,
+ /// Bis repetita.
+ String,
+ ),
+}
+
+/// Struct.
+pub struct ThisStruct(
+ /// hello
+ u32,
+);
+
+/// Struct.
+pub struct ThisStruct2(
+ /// hello
+ u32,
+ /// Bis repetita.
+ u8,
+);
--- /dev/null
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...overage/enum-tuple-documented.rs | 9 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 9 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
--- /dev/null
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+ /// No need to document the field if there is only one in a tuple variant!
+ VarOne(String),
+ /// But if there is more than one... still fine!
+ VarTwo(String, String),
+}
+
+/// Struct.
+pub struct ThisStruct(u32);
+
+/// Struct.
+pub struct ThisStruct2(u32, u8);
--- /dev/null
++-------------------------------------+------------+------------+------------+------------+
+| File | Documented | Percentage | Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...ustdoc-ui/coverage/enum-tuple.rs | 6 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total | 6 | 100.0% | 0 | 0.0% |
++-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/enums.rs | 6 | 66.7% | 0 | 0.0% |
+| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
-| Total | 6 | 66.7% | 0 | 0.0% |
+| Total | 6 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
--- /dev/null
+// check-pass
+// compile-flags:-Zunstable-options --display-doctest-warnings --test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let x = 12;
+/// ```
+pub fn foo() {}
--- /dev/null
+
+running 1 test
+test $DIR/display-output.rs - foo (line 6) ... ok
+
+successes:
+
+---- $DIR/display-output.rs - foo (line 6) stdout ----
+warning: unused variable: `x`
+ --> $DIR/display-output.rs:7:5
+ |
+LL | let x = 12;
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+ |
+ = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+
+
+
+successes:
+ $DIR/display-output.rs - foo (line 6)
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
/// Damn enum's variants: [Enum::A#whatever].
//~^ ERROR `Enum::A#whatever` contains an anchor
pub fn enum_link() {}
-
-/// Primitives?
-///
-/// [u32#hello]
-//~^ ERROR `u32#hello` contains an anchor
-pub fn x() {}
-
-/// [prim@usize#x]
-//~^ ERROR `prim@usize#x` contains an anchor
-pub mod usize {}
-error: `prim@usize#x` contains an anchor, but links to builtin types are already anchored
- --> $DIR/anchors.rs:47:6
- |
-LL | /// [prim@usize#x]
- | ^^^^^^^^^^--
- | |
- | invalid anchor
- |
-note: the lint level is defined here
- --> $DIR/anchors.rs:1:9
- |
-LL | #![deny(rustdoc::broken_intra_doc_links)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this restriction may be lifted in a future release
- = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
error: `Foo::f#hola` contains an anchor, but links to fields are already anchored
--> $DIR/anchors.rs:25:15
|
| ^^^^^^-----
| |
| invalid anchor
+ |
+note: the lint level is defined here
+ --> $DIR/anchors.rs:1:9
+ |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `hello#people#!` contains multiple anchors
--> $DIR/anchors.rs:31:28
| |
| invalid anchor
-error: `u32#hello` contains an anchor, but links to builtin types are already anchored
- --> $DIR/anchors.rs:43:6
- |
-LL | /// [u32#hello]
- | ^^^------
- | |
- | invalid anchor
- |
- = note: this restriction may be lifted in a future release
- = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
- | ~~~~~~~
+ | ++++
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:9:5
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
- | ~~~~~~~
+ | ++++
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:21:5
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
- | ~~~~~~~
+ | ++++
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:35:5
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
- | ~~~~~~~
+ | ++++
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:92:9
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
- | ~~~~~~~
+ | ++++
warning: 12 warnings emitted
b: f32,
}
+// no code example and it's fine!
+impl Clone for Struct {
+ fn clone(&self) -> Self {
+ Self { field: self.field }
+ }
+}
+
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+#[derive(Clone)]
+pub struct NiceStruct;
#[doc(hidden)]
pub mod foo {
+// no-prefer-dynamic
// compile-flags: -Cmetadata=aux
-
+#![crate_type = "rlib"]
#![doc(html_root_url = "http://example.com/")]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
/// dox
#[doc(primitive = "pointer")]
// compile-flags: --crate-type lib --edition 2018
+#![feature(no_core)]
+#![no_core]
+
#[doc(primitive = "usize")]
/// This is the built-in type `usize`.
mod usize {
--- /dev/null
+// compile-flags: -Zunstable-options --generate-link-to-definition
+
+#![crate_name = "foo"]
+
+// @has 'src/foo/check-source-code-urls-to-def-std.rs.html'
+
+fn babar() {}
+
+// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str'
+// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar'
+pub fn foo(a: u32, b: &str, c: String) {
+ let x = 12;
+ let y: bool = true;
+ babar();
+}
fn babar() {}
// @has - '//a/@href' '/struct.String.html'
+// @has - '//a/@href' '/primitive.u32.html'
+// @has - '//a/@href' '/primitive.str.html'
// @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
// @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait'
// @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait'
-pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V) {
+pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {
}
+
+// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool'
+#[doc(primitive = "bool")]
+mod whatever {}
// aux-build:primitive-doc.rs
// compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
+// ignore-windows
-#![no_std]
+#![feature(no_core)]
+#![no_core]
extern crate primitive_doc;
// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize'
+// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link'
+/// [link](usize)
pub fn foo() -> usize { 0 }
///
/// To link to [Something#Anchor!]
pub struct SomeOtherType;
+
+/// Primitives?
+///
+/// [u32#hello]
+// @has anchors/fn.x.html
+// @has - '//a/@href' '{{channel}}/std/primitive.u32.html#hello'
+pub fn x() {}
+
+/// [prim@usize#x]
+// @has anchors/usize/index.html
+// @has - '//a/@href' '{{channel}}/std/primitive.usize.html#x'
+pub mod usize {}
#![no_core]
#![crate_type="rlib"]
+#[doc(primitive = "char")]
+/// Some char docs
+mod char {}
+
#[lang = "char"]
impl char {
pub fn len_utf8(self) -> usize {
#![crate_type = "rlib"]
// @has prim_methods_external_core/index.html
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
//! A [`char`] and its [`char::len_utf8`].
// @has prim_methods_local/index.html
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html#method.len_utf8"]' 'char::len_utf8'
-//! A [`char`] and its [`char::len_utf8`].
+//! A [prim@`char`] and its [`char::len_utf8`].
+
+#[doc(primitive = "char")]
+mod char {}
#[lang = "char"]
impl char {
/// [Self::f]
/// [Self::MAX]
// @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
impl usize {
/// Some docs
pub fn f() {}
// aux-build:issue-15318.rs
// ignore-cross-compile
+#![no_std]
extern crate issue_15318;
--- /dev/null
+// This test ensure that #[doc(hidden)] is applied correctly in enum variant fields.
+
+// Denotes a field which should be hidden.
+pub struct H;
+
+// Denotes a field which should not be hidden (shown).
+pub struct S;
+
+// @has issue_88600/enum.FooEnum.html
+pub enum FooEnum {
+ // @has - '//*[@id="variant.HiddenTupleItem"]//code' 'HiddenTupleItem(_)'
+ // @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0
+ HiddenTupleItem(#[doc(hidden)] H),
+ // @has - '//*[@id="variant.MultipleHidden"]//code' 'MultipleHidden(_, _)'
+ // @count - '//*[@id="variant.MultipleHidden.field.0"]' 0
+ // @count - '//*[@id="variant.MultipleHidden.field.1"]' 0
+ MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H),
+ // @has - '//*[@id="variant.MixedHiddenFirst"]//code' 'MixedHiddenFirst(_, S)'
+ // @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0
+ // @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S'
+ MixedHiddenFirst(#[doc(hidden)] H, S),
+ // @has - '//*[@id="variant.MixedHiddenLast"]//code' 'MixedHiddenLast(S, _)'
+ // @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S'
+ // @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0
+ MixedHiddenLast(S, #[doc(hidden)] H),
+ // @has - '//*[@id="variant.HiddenStruct"]//code' 'HiddenStruct'
+ // @count - '//*[@id="variant.HiddenStruct.field.h"]' 0
+ // @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S'
+ HiddenStruct {
+ #[doc(hidden)]
+ h: H,
+ s: S,
+ },
+}
--- /dev/null
+#![no_std]
+
+/// Link to [intra-doc link][u8]
+// @has 'no_std_primitive/fn.foo.html' '//a[@href="{{channel}}/core/primitive.u8.html"]' 'intra-doc link'
+// @has - '//a[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+pub fn foo() -> u8 {}
--- /dev/null
+#![no_std]
+#![deny(warnings)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link'
+/// Link to [primitive link][u8]
+pub fn foo() -> u8 {}
+
+// Test that all primitives can be linked to.
+/// [isize] [i8] [i16] [i32] [i64] [i128]
+/// [usize] [u8] [u16] [u32] [u64] [u128]
+/// [f32] [f64]
+/// [char] [bool] [str] [slice] [array] [tuple] [unit]
+/// [pointer] [reference] [fn] [never]
+pub fn bar() {}
// @has no_redundancy/struct.Outer.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Outer<T> where T: Copy + Send"
+// "impl<T> Send for Outer<T> where T: Send + Copy"
pub struct Outer<T> {
inner_field: Inner<T>,
}
--- /dev/null
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @count - '//*[@class="docblock"]/div/table' 2
+// @!has - '//*[@class="docblock"]/table'
+/// | hello | hello2 |
+/// | ----- | ------ |
+/// | data | data2 |
+pub struct Foo;
+
+impl Foo {
+ /// | hello | hello2 |
+ /// | ----- | ------ |
+ /// | data | data2 |
+ pub fn foo(&self) {}
+}
help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: i32);
- | ~~~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn foo(i32: TypeName);
- | ~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(_: i32);
- | ~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:9:29
help: if this is a `self` type, give it a parameter name
|
LL | fn foo_with_ref(self: &mut i32);
- | ~~~~~~~~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn foo_with_ref(i32: &mut TypeName);
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo_with_ref(_: &mut i32);
- | ~~~~~~~~~~~
+ | ++
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:12:47
help: if this is a `self` type, give it a parameter name
|
LL | fn bar_with_default_impl(self: String, String) {}
- | ~~~~~~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn bar_with_default_impl(String: TypeName, String) {}
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn bar_with_default_impl(_: String, String) {}
- | ~~~~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:22:44
help: if this is a parameter name, give it a type
|
LL | fn bar_with_default_impl(String, String: TypeName) {}
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn bar_with_default_impl(String, _: String) {}
- | ~~~~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `,`
--> $DIR/anon-params-denied-2018.rs:27:22
help: if this is a parameter name, give it a type
|
LL | fn baz(a:usize, b: TypeName, c: usize) -> usize {
- | ~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn baz(a:usize, _: b, c: usize) -> usize {
- | ~~~~
+ | ++
error: aborting due to 9 previous errors
// Test binary_search_by_key lifetime. Issue #34683
+#[allow(dead_code)]
#[derive(Debug)]
struct Assignment {
topic: String,
//~^ ERROR asm template must be a string literal
asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
//~^ ERROR asm template must be a string literal
+ asm!("{}", in(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inlateout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
}
}
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:79:28
+ |
+LL | asm!("{}", in(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:81:31
+ |
+LL | asm!("{}", inout(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:83:35
+ |
+LL | asm!("{}", inlateout(reg) _);
+ | ^
+
error: requires at least a template string argument
- --> $DIR/parse-error.rs:84:1
+ --> $DIR/parse-error.rs:90:1
|
LL | global_asm!();
| ^^^^^^^^^^^^^^
error: asm template must be a string literal
- --> $DIR/parse-error.rs:86:13
+ --> $DIR/parse-error.rs:92:13
|
LL | global_asm!(FOO);
| ^^^
error: expected token: `,`
- --> $DIR/parse-error.rs:88:18
+ --> $DIR/parse-error.rs:94:18
|
LL | global_asm!("{}" FOO);
| ^^^ expected `,`
error: expected operand, options, or additional template string
- --> $DIR/parse-error.rs:90:19
+ --> $DIR/parse-error.rs:96:19
|
LL | global_asm!("{}", FOO);
| ^^^ expected operand, options, or additional template string
error: expected expression, found end of macro arguments
- --> $DIR/parse-error.rs:92:24
+ --> $DIR/parse-error.rs:98:24
|
LL | global_asm!("{}", const);
| ^ expected expression
error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
- --> $DIR/parse-error.rs:94:30
+ --> $DIR/parse-error.rs:100:30
|
LL | global_asm!("{}", const(reg) FOO);
| ^^^ expected one of `,`, `.`, `?`, or an operator
error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
- --> $DIR/parse-error.rs:96:25
+ --> $DIR/parse-error.rs:102:25
|
LL | global_asm!("", options(FOO));
| ^^^ expected one of `)`, `att_syntax`, or `raw`
error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
- --> $DIR/parse-error.rs:98:25
+ --> $DIR/parse-error.rs:104:25
|
LL | global_asm!("", options(nomem FOO));
| ^^^^^ expected one of `)`, `att_syntax`, or `raw`
error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
- --> $DIR/parse-error.rs:100:25
+ --> $DIR/parse-error.rs:106:25
|
LL | global_asm!("", options(nomem, FOO));
| ^^^^^ expected one of `)`, `att_syntax`, or `raw`
error: arguments are not allowed after options
- --> $DIR/parse-error.rs:102:30
+ --> $DIR/parse-error.rs:108:30
|
LL | global_asm!("{}", options(), const FOO);
| --------- ^^^^^^^^^ argument
| previous options
error: expected string literal
- --> $DIR/parse-error.rs:104:29
+ --> $DIR/parse-error.rs:110:29
|
LL | global_asm!("", clobber_abi(FOO));
| ^^^ not a string literal
error: expected `)`, found `FOO`
- --> $DIR/parse-error.rs:106:33
+ --> $DIR/parse-error.rs:112:33
|
LL | global_asm!("", clobber_abi("C" FOO));
| ^^^ expected `)`
error: expected `)`, found `,`
- --> $DIR/parse-error.rs:108:32
+ --> $DIR/parse-error.rs:114:32
|
LL | global_asm!("", clobber_abi("C", FOO));
| ^ expected `)`
error: arguments are not allowed after clobber_abi
- --> $DIR/parse-error.rs:110:37
+ --> $DIR/parse-error.rs:116:37
|
LL | global_asm!("{}", clobber_abi("C"), const FOO);
| ---------------- ^^^^^^^^^ argument
| clobber_abi
error: `clobber_abi` cannot be used with `global_asm!`
- --> $DIR/parse-error.rs:110:19
+ --> $DIR/parse-error.rs:116:19
|
LL | global_asm!("{}", clobber_abi("C"), const FOO);
| ^^^^^^^^^^^^^^^^
error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:113:28
+ --> $DIR/parse-error.rs:119:28
|
LL | global_asm!("", options(), clobber_abi("C"));
| --------- ^^^^^^^^^^^^^^^^
| options
error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:115:30
+ --> $DIR/parse-error.rs:121:30
|
LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
| --------- ^^^^^^^^^^^^^^^^
| options
error: clobber_abi specified multiple times
- --> $DIR/parse-error.rs:117:35
+ --> $DIR/parse-error.rs:123:35
|
LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
| ---------------- ^^^^^^^^^^^^^^^^
| clobber_abi previously specified here
error: duplicate argument named `a`
- --> $DIR/parse-error.rs:119:35
+ --> $DIR/parse-error.rs:125:35
|
LL | global_asm!("{a}", a = const FOO, a = const BAR);
| ------------- ^^^^^^^^^^^^^ duplicate argument
| previously here
error: argument never used
- --> $DIR/parse-error.rs:119:35
+ --> $DIR/parse-error.rs:125:35
|
LL | global_asm!("{a}", a = const FOO, a = const BAR);
| ^^^^^^^^^^^^^ argument never used
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
error: expected one of `clobber_abi`, `const`, or `options`, found `""`
- --> $DIR/parse-error.rs:122:28
+ --> $DIR/parse-error.rs:128:28
|
LL | global_asm!("", options(), "");
| ^^ expected one of `clobber_abi`, `const`, or `options`
error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
- --> $DIR/parse-error.rs:124:30
+ --> $DIR/parse-error.rs:130:30
|
LL | global_asm!("{}", const FOO, "{}", const FOO);
| ^^^^ expected one of `clobber_abi`, `const`, or `options`
error: asm template must be a string literal
- --> $DIR/parse-error.rs:126:13
+ --> $DIR/parse-error.rs:132:13
|
LL | global_asm!(format!("{{{}}}", 0), const FOO);
| ^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error: asm template must be a string literal
- --> $DIR/parse-error.rs:128:20
+ --> $DIR/parse-error.rs:134:20
|
LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
| ^^^^^^^^^^^^^^^^^^^^
LL | asm!("{1}", in("eax") foo, const bar);
| ^^^ non-constant value
-error: aborting due to 63 previous errors
+error: aborting due to 66 previous errors
For more information about this error, try `rustc --explain E0435`.
LL | impl dyn Trait {
| ^^^^^^^^^ `Trait` cannot be made into an object
|
- = help: consider moving `N` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/associated-const-in-trait.rs:6:11
|
| ----- this trait cannot be made into an object...
LL | const N: usize;
| ^ ...because it contains this associated `const`
+ = help: consider moving `N` to another trait
error: aborting due to previous error
LL | impl dyn Bar {}
| ^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `X` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-48027.rs:2:11
|
| --- this trait cannot be made into an object...
LL | const X: usize;
| ^ ...because it contains this associated `const`
+ = help: consider moving `X` to another trait
error: aborting due to 2 previous errors
help: use fully qualified syntax to disambiguate
|
LL | fn a<C:Vehicle+Box>(_: <C as Box>::Color) {
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn a<C:Vehicle+Box>(_: <C as Vehicle>::Color) {
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Color` in bounds of `C`
--> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12
help: use fully qualified syntax to disambiguate
|
LL | fn b<C>(_: <C as Box>::Color) where C : Vehicle+Box {
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn b<C>(_: <C as Vehicle>::Color) where C : Vehicle+Box {
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Color` in bounds of `C`
--> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12
help: use fully qualified syntax to disambiguate
|
LL | fn c<C>(_: <C as Box>::Color) where C : Vehicle, C : Box {
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn c<C>(_: <C as Vehicle>::Color) where C : Vehicle, C : Box {
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Color` in bounds of `X`
--> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20
help: use fully qualified syntax to disambiguate
|
LL | fn e(&self, _: <X as Box>::Color) where X : Box;
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn e(&self, _: <X as Vehicle>::Color) where X : Box;
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Color` in bounds of `X`
--> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20
help: use fully qualified syntax to disambiguate
|
LL | fn f(&self, _: <X as Box>::Color) where X : Box { }
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn f(&self, _: <X as Vehicle>::Color) where X : Box { }
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Color` in bounds of `X`
--> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20
help: use fully qualified syntax to disambiguate
|
LL | fn d(&self, _: <X as Box>::Color) where X : Box { }
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn d(&self, _: <X as Vehicle>::Color) where X : Box { }
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors
help: use fully qualified syntax to disambiguate
|
LL | fn dent<C:BoxCar>(c: C, color: <C as Vehicle>::Color) {
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar`
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37
help: use fully qualified syntax to disambiguate
|
LL | fn paint<C:BoxCar>(c: C, d: <C as Vehicle>::Color) {
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32
--> $DIR/associated-types-bound-failure.rs:19:19
|
LL | ToInt::to_int(&g.get())
- | ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+ | ------------- ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+ | |
+ | required by a bound introduced by this call
|
note: required by `ToInt::to_int`
--> $DIR/associated-types-bound-failure.rs:6:5
help: use fully qualified syntax to disambiguate
|
LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Bar>::A) {}
- | ~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Foo>::A) {}
- | ~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~
error: aborting due to 2 previous errors
pub fn f1_uint_uint() {
f1(2u32, 4u32);
//~^ ERROR `u32: Foo` is not satisfied
- //~| ERROR `u32: Foo` is not satisfied
}
pub fn f1_uint_int() {
f1(2u32, 4i32);
//~^ ERROR `u32: Foo` is not satisfied
- //~| ERROR `u32: Foo` is not satisfied
}
pub fn f2_int() {
help: change the type of the numeric literal from `i32` to `u32`
|
LL | f1(2i32, 4u32);
- | ~~~~
+ | ~~~
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:29:5
+ --> $DIR/associated-types-path-2.rs:29:14
|
LL | f1(2u32, 4u32);
- | ^^ the trait `Foo` is not implemented for `u32`
+ | -- ^^^^ the trait `Foo` is not implemented for `u32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f1`
--> $DIR/associated-types-path-2.rs:13:14
| ^^^ required by this bound in `f1`
error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:29:5
- |
-LL | f1(2u32, 4u32);
- | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
-error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:5
+ --> $DIR/associated-types-path-2.rs:34:14
|
LL | f1(2u32, 4i32);
- | ^^ the trait `Foo` is not implemented for `u32`
+ | -- ^^^^ the trait `Foo` is not implemented for `u32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f1`
--> $DIR/associated-types-path-2.rs:13:14
LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
| ^^^ required by this bound in `f1`
-error[E0277]: the trait bound `u32: Foo` is not satisfied
- --> $DIR/associated-types-path-2.rs:35:5
- |
-LL | f1(2u32, 4i32);
- | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
error[E0308]: mismatched types
- --> $DIR/associated-types-path-2.rs:41:18
+ --> $DIR/associated-types-path-2.rs:39:18
|
LL | let _: i32 = f2(2i32);
| --- ^^^^^^^^ expected `i32`, found `u32`
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | let _: i32 = f2(2i32).try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
--> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8
|
LL | x: I::A)
- | ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+ | ^^^^
+ |
+help: use a fully qualified path with inferred lifetimes
+ |
+LL | x: <I as Foo<&isize>>::A)
+ | ~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
--> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32
|
LL | fn some_method(&self, arg: I::A);
- | ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+ | ^^^^
+ |
+help: use a fully qualified path with inferred lifetimes
+ |
+LL | fn some_method(&self, arg: <I as Foo<&isize>>::A);
+ | ~~~~~~~~~~~~~~~~~~~~
error[E0212]: cannot use the associated type of a trait with uninferred generic parameters
--> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24
|
LL | fn mango(&self) -> X::Assoc {
- | ^^^^^^^^ help: use a fully qualified path with inferred lifetimes: `<X as Banana<'_>>::Assoc`
+ | ^^^^^^^^
+ |
+help: use a fully qualified path with inferred lifetimes
+ |
+LL | fn mango(&self) -> <X as Banana<'_>>::Assoc {
+ | ~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
--- /dev/null
+trait From<Src> {
+ type Output;
+
+ fn from(src: Src) -> <Self as From<Src>>::Output;
+}
+
+trait To: Sized {
+ fn to<Dst: From<Self>>(self) ->
+ <Dst as From<Self>>::Dst
+ //~^ ERROR cannot find associated type `Dst` in trait `From`
+ {
+ From::from(self)
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0576]: cannot find associated type `Dst` in trait `From`
+ --> $DIR/issue-19883.rs:9:30
+ |
+LL | type Output;
+ | ------------ associated type `Output` defined here
+...
+LL | <Dst as From<Self>>::Dst
+ | ^^^
+ | |
+ | not found in `From`
+ | help: maybe you meant this associated type: `Output`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0576`.
--- /dev/null
+// check-pass
+// pretty-expanded FIXME #23616
+
+#![no_implicit_prelude]
+
+trait Iterator {
+ type Item;
+ fn dummy(&self) { }
+}
+
+impl<'a, T> Iterator for &'a mut (dyn Iterator<Item=T> + 'a) {
+ type Item = T;
+}
+
+fn main() {}
--> $DIR/issue-27675-unchecked-bounds.rs:15:31
|
LL | copy::<dyn Setup<From=T>>(t)
- | ^ the trait `Copy` is not implemented for `T`
+ | ------------------------- ^ the trait `Copy` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `copy`
--> $DIR/issue-27675-unchecked-bounds.rs:10:12
--- /dev/null
+// compile-flags: -C opt-level=3
+// edition:2018
+
+use std::future::Future;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::sync::atomic::AtomicUsize;
+use std::sync::Arc;
+use std::task::Poll::{Pending, Ready};
+use std::task::Waker;
+use std::task::{Context, Poll};
+use std::{
+ ptr,
+ task::{RawWaker, RawWakerVTable},
+};
+
+/// Future for the [`poll_fn`] function.
+pub struct PollFn<F> {
+ f: F,
+}
+
+impl<F> Unpin for PollFn<F> {}
+
+/// Creates a new future wrapping around a function returning [`Poll`].
+pub fn poll_fn<T, F>(f: F) -> PollFn<F>
+where
+ F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+ PollFn { f }
+}
+
+impl<T, F> Future for PollFn<F>
+where
+ F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+ type Output = T;
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
+ (&mut self.f)(cx)
+ }
+}
+pub fn run<F: Future>(future: F) -> F::Output {
+ BasicScheduler.block_on(future)
+}
+
+pub(crate) struct BasicScheduler;
+
+impl BasicScheduler {
+ pub(crate) fn block_on<F>(&mut self, mut future: F) -> F::Output
+ where
+ F: Future,
+ {
+ let waker = unsafe { Waker::from_raw(raw_waker()) };
+ let mut cx = std::task::Context::from_waker(&waker);
+
+ let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+ loop {
+ if let Ready(v) = future.as_mut().poll(&mut cx) {
+ return v;
+ }
+ }
+ }
+}
+
+// ===== impl Spawner =====
+
+fn raw_waker() -> RawWaker {
+ RawWaker::new(ptr::null(), waker_vtable())
+}
+
+fn waker_vtable() -> &'static RawWakerVTable {
+ &RawWakerVTable::new(
+ clone_arc_raw,
+ wake_arc_raw,
+ wake_by_ref_arc_raw,
+ drop_arc_raw,
+ )
+}
+
+unsafe fn clone_arc_raw(_: *const ()) -> RawWaker {
+ raw_waker()
+}
+
+unsafe fn wake_arc_raw(_: *const ()) {}
+
+unsafe fn wake_by_ref_arc_raw(_: *const ()) {}
+
+unsafe fn drop_arc_raw(_: *const ()) {}
+
+struct AtomicWaker {}
+
+impl AtomicWaker {
+ /// Create an `AtomicWaker`
+ fn new() -> AtomicWaker {
+ AtomicWaker {}
+ }
+
+ fn register_by_ref(&self, _waker: &Waker) {}
+}
+
+#[allow(dead_code)]
+struct Tx<T> {
+ inner: Arc<Chan<T>>,
+}
+
+struct Rx<T> {
+ inner: Arc<Chan<T>>,
+}
+
+#[allow(dead_code)]
+struct Chan<T> {
+ tx: PhantomData<T>,
+ semaphore: Sema,
+ rx_waker: AtomicWaker,
+ rx_closed: bool,
+}
+
+fn channel<T>() -> (Tx<T>, Rx<T>) {
+ let chan = Arc::new(Chan {
+ tx: PhantomData,
+ semaphore: Sema(AtomicUsize::new(0)),
+ rx_waker: AtomicWaker::new(),
+ rx_closed: false,
+ });
+
+ (
+ Tx {
+ inner: chan.clone(),
+ },
+ Rx { inner: chan },
+ )
+}
+
+// ===== impl Rx =====
+
+impl<T> Rx<T> {
+ /// Receive the next value
+ fn recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
+ self.inner.rx_waker.register_by_ref(cx.waker());
+
+ if self.inner.rx_closed && self.inner.semaphore.is_idle() {
+ Ready(None)
+ } else {
+ Pending
+ }
+ }
+}
+
+struct Sema(AtomicUsize);
+
+impl Sema {
+ fn is_idle(&self) -> bool {
+ false
+ }
+}
+
+pub struct UnboundedReceiver<T> {
+ chan: Rx<T>,
+}
+
+pub fn unbounded_channel<T>() -> UnboundedReceiver<T> {
+ let (tx, rx) = channel();
+
+ drop(tx);
+ let rx = UnboundedReceiver { chan: rx };
+
+ rx
+}
+
+impl<T> UnboundedReceiver<T> {
+ pub async fn recv(&mut self) -> Option<T> {
+ poll_fn(|cx| self.chan.recv(cx)).await
+ }
+}
--> $DIR/issue-72442.rs:12:36
|
LL | let mut f = File::open(path.to_str())?;
- | ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+ | ---------- ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `File::open`
--> $SRC_DIR/std/src/fs.rs:LL:COL
--- /dev/null
+// compile-flags: -C opt-level=3
+// aux-build: issue-72470-lib.rs
+// edition:2018
+// build-pass
+
+// Regression test for issue #72470, using the minimization
+// in https://github.com/jonas-schievink/llvm-error
+
+extern crate issue_72470_lib;
+
+use std::future::Future;
+use std::pin::Pin;
+use std::sync::Mutex;
+use std::task::Poll::{Pending, Ready};
+
+#[allow(dead_code)]
+enum Msg {
+ A(Vec<()>),
+ B,
+}
+
+#[allow(dead_code)]
+enum Out {
+ _0(Option<Msg>),
+ Disabled,
+}
+
+#[allow(unused_must_use)]
+fn main() {
+ let mut rx = issue_72470_lib::unbounded_channel::<Msg>();
+ let entity = Mutex::new(());
+ issue_72470_lib::run(async move {
+ {
+ let output = {
+ let mut fut = rx.recv();
+ issue_72470_lib::poll_fn(|cx| {
+ loop {
+ let fut = unsafe { Pin::new_unchecked(&mut fut) };
+ let out = match fut.poll(cx) {
+ Ready(out) => out,
+ Pending => {
+ break;
+ }
+ };
+ #[allow(unused_variables)]
+ match &out {
+ Some(_msg) => {}
+ _ => break,
+ }
+ return Ready(Out::_0(out));
+ }
+ Ready(Out::_0(None))
+ })
+ .await
+ };
+ match output {
+ Out::_0(Some(_msg)) => {
+ entity.lock();
+ }
+ Out::_0(None) => unreachable!(),
+ _ => unreachable!(),
+ }
+ }
+ entity.lock();
+ });
+}
error: lifetime may not live long enough
- --> $DIR/issue-76547.rs:19:14
+ --> $DIR/issue-76547.rs:20:13
|
LL | async fn fut(bufs: &mut [&mut [u8]]) {
- | ^^^^ - - let's call the lifetime of this reference `'2`
- | | |
- | | let's call the lifetime of this reference `'1`
- | assignment requires that `'1` must outlive `'2`
+ | - - let's call the lifetime of this reference `'2`
+ | |
+ | let's call the lifetime of this reference `'1`
+LL | ListFut(bufs).await
+ | ^^^^ this usage requires that `'1` must outlive `'2`
error: lifetime may not live long enough
- --> $DIR/issue-76547.rs:33:15
+ --> $DIR/issue-76547.rs:34:14
|
LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
- | ^^^^ - - let's call the lifetime of this reference `'2`
- | | |
- | | let's call the lifetime of this reference `'1`
- | assignment requires that `'1` must outlive `'2`
+ | - - let's call the lifetime of this reference `'2`
+ | |
+ | let's call the lifetime of this reference `'1`
+LL | ListFut2(bufs).await
+ | ^^^^ this usage requires that `'1` must outlive `'2`
error: aborting due to 2 previous errors
--> $DIR/issue-54752-async-block.rs:6:22
|
LL | fn main() { let _a = (async { }); }
- | ^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
= note: `#[warn(unused_parens)]` on by default
+help: remove these parentheses
+ |
+LL - fn main() { let _a = (async { }); }
+LL + fn main() { let _a = async { }; }
+ |
warning: 1 warning emitted
//~^ ERROR this enum takes 2 generic arguments
{
Ok(())
- //~^ ERROR type annotations needed
}
fn main() { }
LL | async fn copy() -> Result<(), E>
| +++
-error[E0282]: type annotations needed
- --> $DIR/issue-65159.rs:8:5
- |
-LL | Ok(())
- | ^^ cannot infer type for type parameter `E` declared on the enum `Result`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0107, E0282.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
+++ /dev/null
-#[macro_export]
-macro_rules! define_macro {
- ($i:ident) => {
- macro_rules! $i { () => {} }
- }
-}
+++ /dev/null
-// compile-flags: -C opt-level=3
-// edition:2018
-
-use std::future::Future;
-use std::marker::PhantomData;
-use std::pin::Pin;
-use std::sync::atomic::AtomicUsize;
-use std::sync::Arc;
-use std::task::Poll::{Pending, Ready};
-use std::task::Waker;
-use std::task::{Context, Poll};
-use std::{
- ptr,
- task::{RawWaker, RawWakerVTable},
-};
-
-/// Future for the [`poll_fn`] function.
-pub struct PollFn<F> {
- f: F,
-}
-
-impl<F> Unpin for PollFn<F> {}
-
-/// Creates a new future wrapping around a function returning [`Poll`].
-pub fn poll_fn<T, F>(f: F) -> PollFn<F>
-where
- F: FnMut(&mut Context<'_>) -> Poll<T>,
-{
- PollFn { f }
-}
-
-impl<T, F> Future for PollFn<F>
-where
- F: FnMut(&mut Context<'_>) -> Poll<T>,
-{
- type Output = T;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
- (&mut self.f)(cx)
- }
-}
-pub fn run<F: Future>(future: F) -> F::Output {
- BasicScheduler.block_on(future)
-}
-
-pub(crate) struct BasicScheduler;
-
-impl BasicScheduler {
- pub(crate) fn block_on<F>(&mut self, mut future: F) -> F::Output
- where
- F: Future,
- {
- let waker = unsafe { Waker::from_raw(raw_waker()) };
- let mut cx = std::task::Context::from_waker(&waker);
-
- let mut future = unsafe { Pin::new_unchecked(&mut future) };
-
- loop {
- if let Ready(v) = future.as_mut().poll(&mut cx) {
- return v;
- }
- }
- }
-}
-
-// ===== impl Spawner =====
-
-fn raw_waker() -> RawWaker {
- RawWaker::new(ptr::null(), waker_vtable())
-}
-
-fn waker_vtable() -> &'static RawWakerVTable {
- &RawWakerVTable::new(
- clone_arc_raw,
- wake_arc_raw,
- wake_by_ref_arc_raw,
- drop_arc_raw,
- )
-}
-
-unsafe fn clone_arc_raw(_: *const ()) -> RawWaker {
- raw_waker()
-}
-
-unsafe fn wake_arc_raw(_: *const ()) {}
-
-unsafe fn wake_by_ref_arc_raw(_: *const ()) {}
-
-unsafe fn drop_arc_raw(_: *const ()) {}
-
-struct AtomicWaker {}
-
-impl AtomicWaker {
- /// Create an `AtomicWaker`
- fn new() -> AtomicWaker {
- AtomicWaker {}
- }
-
- fn register_by_ref(&self, _waker: &Waker) {}
-}
-
-#[allow(dead_code)]
-struct Tx<T> {
- inner: Arc<Chan<T>>,
-}
-
-struct Rx<T> {
- inner: Arc<Chan<T>>,
-}
-
-#[allow(dead_code)]
-struct Chan<T> {
- tx: PhantomData<T>,
- semaphore: Sema,
- rx_waker: AtomicWaker,
- rx_closed: bool,
-}
-
-fn channel<T>() -> (Tx<T>, Rx<T>) {
- let chan = Arc::new(Chan {
- tx: PhantomData,
- semaphore: Sema(AtomicUsize::new(0)),
- rx_waker: AtomicWaker::new(),
- rx_closed: false,
- });
-
- (
- Tx {
- inner: chan.clone(),
- },
- Rx { inner: chan },
- )
-}
-
-// ===== impl Rx =====
-
-impl<T> Rx<T> {
- /// Receive the next value
- fn recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
- self.inner.rx_waker.register_by_ref(cx.waker());
-
- if self.inner.rx_closed && self.inner.semaphore.is_idle() {
- Ready(None)
- } else {
- Pending
- }
- }
-}
-
-struct Sema(AtomicUsize);
-
-impl Sema {
- fn is_idle(&self) -> bool {
- false
- }
-}
-
-pub struct UnboundedReceiver<T> {
- chan: Rx<T>,
-}
-
-pub fn unbounded_channel<T>() -> UnboundedReceiver<T> {
- let (tx, rx) = channel();
-
- drop(tx);
- let rx = UnboundedReceiver { chan: rx };
-
- rx
-}
-
-impl<T> UnboundedReceiver<T> {
- pub async fn recv(&mut self) -> Option<T> {
- poll_fn(|cx| self.chan.recv(cx)).await
- }
-}
LL | let x = Box::new(0);
| - captured outer variable
LL | Box::new(|| x)
- | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | ---^
+ | | |
+ | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | captured by this `Fn` closure
error: aborting due to previous error
error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
--> $DIR/borrowck-move-by-capture.rs:9:29
|
-LL | let bar: Box<_> = box 3;
- | --- captured outer variable
-LL | let _g = to_fn_mut(|| {
-LL | let _h = to_fn_once(move || -> isize { *bar });
- | ^^^^^^^^^^^^^^^^ ----
- | | |
- | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
- | | move occurs due to use in closure
- | move out of `bar` occurs here
+LL | let bar: Box<_> = box 3;
+ | --- captured outer variable
+LL | let _g = to_fn_mut(|| {
+ | ________________________-
+LL | | let _h = to_fn_once(move || -> isize { *bar });
+ | | ^^^^^^^^^^^^^^^^ ----
+ | | | |
+ | | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
+ | | | move occurs due to use in closure
+ | | move out of `bar` occurs here
+LL | | });
+ | |_____- captured by this `FnMut` closure
error: aborting due to previous error
// run-pass
+#![allow(dead_code)]
#![deny(unused_mut)]
#[derive(Debug)]
//~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
//~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
LockedMarket(generator.lock().unwrap().buy())
- //~^ ERROR cannot return value referencing temporary value
}
struct LockedMarket<T>(T);
| expected 0 lifetime arguments
|
note: struct defined here, with 0 lifetime parameters
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+ --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
|
LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^
| ^^^^^^^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `T`
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+ --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
|
LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^ -
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
| +++
-error[E0515]: cannot return value referencing temporary value
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
- |
-LL | LockedMarket(generator.lock().unwrap().buy())
- | ^^^^^^^^^^^^^-------------------------^^^^^^^
- | | |
- | | temporary value created here
- | returns a value referencing data owned by the current function
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0107, E0515.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
--- /dev/null
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+ --> $DIR/issue-82462.rs:18:9
+ |
+LL | for x in DroppingSlice(&*v).iter() {
+ | ------------------
+ | | |
+ | | immutable borrow occurs here
+ | a temporary with access to the immutable borrow is created here ...
+LL | v.push(*x);
+ | ^ mutable borrow occurs here
+LL | break;
+LL | }
+ | - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+ |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+ |
+LL | };
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
--- /dev/null
+struct DroppingSlice<'a>(&'a [i32]);
+
+impl Drop for DroppingSlice<'_> {
+ fn drop(&mut self) {
+ println!("hi from slice");
+ }
+}
+
+impl DroppingSlice<'_> {
+ fn iter(&self) -> std::slice::Iter<'_, i32> {
+ self.0.iter()
+ }
+}
+
+fn main() {
+ let mut v = vec![1, 2, 3, 4];
+ for x in DroppingSlice(&*v).iter() {
+ v.push(*x); //~ERROR
+ break;
+ }
+}
--- /dev/null
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+ --> $DIR/issue-82462.rs:18:9
+ |
+LL | for x in DroppingSlice(&*v).iter() {
+ | ------------------
+ | | |
+ | | immutable borrow occurs here
+ | a temporary with access to the immutable borrow is created here ...
+LL | v.push(*x);
+ | ^^^^^^^^^^ mutable borrow occurs here
+LL | break;
+LL | }
+ | - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+ |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+ |
+LL | };
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
--- /dev/null
+// Regression test for #87456.
+
+fn take_mut(_val: impl FnMut()) {}
+
+fn main() {
+ let val = String::new();
+ //~^ NOTE: captured outer variable
+ take_mut(|| {
+ //~^ NOTE: captured by this `FnMut` closure
+ let _foo: String = val;
+ //~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507]
+ //~| NOTE: move occurs because
+ })
+}
--- /dev/null
+error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure
+ --> $DIR/issue-87456-point-to-closure.rs:10:28
+ |
+LL | let val = String::new();
+ | --- captured outer variable
+LL |
+LL | take_mut(|| {
+ | ______________-
+LL | |
+LL | | let _foo: String = val;
+ | | ^^^
+ | | |
+ | | move occurs because `val` has type `String`, which does not implement the `Copy` trait
+ | | help: consider borrowing here: `&val`
+LL | |
+LL | |
+LL | | })
+ | |_____- captured by this `FnMut` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
|
-LL | let y = vec![format!("World")];
- | - captured outer variable
-LL | call(|| {
-LL | y.into_iter();
- | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
+LL | let y = vec![format!("World")];
+ | - captured outer variable
+LL | call(|| {
+ | __________-
+LL | | y.into_iter();
+ | | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
+LL | |
+LL | | });
+ | |_____- captured by this `Fn` closure
error: aborting due to previous error
--> $DIR/into-boxed-slice-fail.rs:7:35
|
LL | let _ = Box::into_boxed_slice(boxed_slice);
- | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by `Box::<T, A>::into_boxed_slice`
--> $DIR/into-boxed-slice-fail.rs:11:35
|
LL | let _ = Box::into_boxed_slice(boxed_trait);
- | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Debug`
note: required by `Box::<T, A>::into_boxed_slice`
+++ /dev/null
-// run-pass
-
-trait Speak : Sized {
- fn say(&self, s:&str) -> String;
- fn hi(&self) -> String { hello(self) }
-}
-
-fn hello<S:Speak>(s:&S) -> String{
- s.say("hello")
-}
-
-impl Speak for isize {
- fn say(&self, s:&str) -> String {
- format!("{}: {}", s, *self)
- }
-}
-
-impl<T: Speak> Speak for Option<T> {
- fn say(&self, s:&str) -> String {
- match *self {
- None => format!("{} - none", s),
- Some(ref x) => { format!("something!{}", x.say(s)) }
- }
- }
-}
-
-
-pub fn main() {
- assert_eq!(3.hi(), "hello: 3".to_string());
- assert_eq!(Some(Some(3)).hi(),
- "something!something!hello: 3".to_string());
- assert_eq!(None::<isize>.hi(), "hello - none".to_string());
-
- assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string());
- assert_eq!(Some(3).hi(), "something!hello: 3".to_string());
-}
--> $DIR/type_inference.rs:27:14
|
LL | only_bar(x);
- | ^ the trait `Bar` is not implemented for `{float}`
+ | -------- ^ the trait `Bar` is not implemented for `{float}`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<i32 as Bar>
--> $DIR/closure-expected.rs:3:23
|
LL | let y = x.or_else(4);
- | ^ expected an `FnOnce<()>` closure, found `{integer}`
+ | ------- ^ expected an `FnOnce<()>` closure, found `{integer}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnOnce<()>` is not implemented for `{integer}`
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
// check-pass
#![allow(unreachable_code)]
#![warn(unused)]
+#![allow(dead_code)]
#[derive(Debug)]
struct Point {
warning: value captured by `a` is never read
- --> $DIR/liveness.rs:23:9
+ --> $DIR/liveness.rs:24:9
|
LL | a = 1;
| ^
= help: did you mean to capture by reference instead?
warning: unused variable: `a`
- --> $DIR/liveness.rs:32:9
+ --> $DIR/liveness.rs:33:9
|
LL | a += 1;
| ^
= help: did you mean to capture by reference instead?
warning: value assigned to `a` is never read
- --> $DIR/liveness.rs:52:9
+ --> $DIR/liveness.rs:53:9
|
LL | a += 1;
| ^
= help: maybe it is overwritten before being read?
warning: value assigned to `a` is never read
- --> $DIR/liveness.rs:76:13
+ --> $DIR/liveness.rs:77:13
|
LL | a = Some("d1");
| ^
= help: maybe it is overwritten before being read?
warning: value assigned to `b` is never read
- --> $DIR/liveness.rs:84:13
+ --> $DIR/liveness.rs:85:13
|
LL | b = Some("e1");
| ^
= help: maybe it is overwritten before being read?
warning: value assigned to `b` is never read
- --> $DIR/liveness.rs:86:13
+ --> $DIR/liveness.rs:87:13
|
LL | b = Some("e2");
| ^
= help: maybe it is overwritten before being read?
warning: unused variable: `b`
- --> $DIR/liveness.rs:84:13
+ --> $DIR/liveness.rs:85:13
|
LL | b = Some("e1");
| ^
// check-pass
#![warn(unused)]
+#![allow(dead_code)]
#[derive(Debug)]
struct MyStruct {
warning: value assigned to `a` is never read
- --> $DIR/liveness_unintentional_copy.rs:19:9
+ --> $DIR/liveness_unintentional_copy.rs:20:9
|
LL | a = s;
| ^
= help: maybe it is overwritten before being read?
warning: unused variable: `a`
- --> $DIR/liveness_unintentional_copy.rs:19:9
+ --> $DIR/liveness_unintentional_copy.rs:20:9
|
LL | a = s;
| ^
= help: did you mean to capture by reference instead?
warning: unused variable: `a`
- --> $DIR/liveness_unintentional_copy.rs:35:9
+ --> $DIR/liveness_unintentional_copy.rs:36:9
|
LL | a += x;
| ^
// edition:2021
//check-pass
#![warn(unused)]
+#![allow(dead_code)]
#![feature(rustc_attrs)]
#[derive(Debug, Clone, Copy)]
// Test that we can use raw ptrs when using `capture_disjoint_fields`.
+#![allow(dead_code)]
+
#[derive(Debug)]
struct S {
s: String,
--> $DIR/closure-bounds-subtype.rs:13:22
|
LL | take_const_owned(f);
- | ^ `F` cannot be shared between threads safely
+ | ---------------- ^ `F` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `take_const_owned`
--> $DIR/closure-bounds-subtype.rs:4:50
--> $DIR/coerce-unsafe-to-closure.rs:2:44
|
LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
- | ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ | --- ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
--- /dev/null
+fn server() -> impl {
+//~^ ERROR at least one trait must be specified
+ ().map2(|| "")
+}
+
+trait FilterBase2 {
+ fn map2<F>(self, f: F) -> Map2<F> {}
+ //~^ ERROR mismatched types
+ //~^^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+struct Map2<Segment2> {
+ _func: F,
+ //~^ ERROR cannot find type `F` in this scope
+}
+
+impl<F> FilterBase2 for F {}
+
+fn main() {}
--- /dev/null
+error: at least one trait must be specified
+ --> $DIR/issue-78720.rs:1:16
+ |
+LL | fn server() -> impl {
+ | ^^^^
+
+error[E0412]: cannot find type `F` in this scope
+ --> $DIR/issue-78720.rs:13:12
+ |
+LL | _func: F,
+ | ^
+ |
+ ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | pub trait Fn<Args>: FnMut<Args> {
+ | ------------------------------- similarly named trait `Fn` defined here
+ |
+help: a trait with a similar name exists
+ |
+LL | _func: Fn,
+ | ~~
+help: you might be missing a type parameter
+ |
+LL | struct Map2<Segment2, F> {
+ | +++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-78720.rs:7:39
+ |
+LL | fn map2<F>(self, f: F) -> Map2<F> {}
+ | ^^ expected struct `Map2`, found `()`
+ |
+ = note: expected struct `Map2<F>`
+ found unit type `()`
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+ --> $DIR/issue-78720.rs:7:16
+ |
+LL | fn map2<F>(self, f: F) -> Map2<F> {}
+ | ^^^^ doesn't have a size known at compile-time
+ |
+ = help: unsized fn params are gated as an unstable feature
+help: consider further restricting `Self`
+ |
+LL | fn map2<F>(self, f: F) -> Map2<F> where Self: Sized {}
+ | +++++++++++++++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn map2<F>(&self, f: F) -> Map2<F> {}
+ | +
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0412.
+For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+// In #88097, the compiler attempted to coerce a closure type to itself via
+// a function pointer, which caused an unnecessary error. Check that this
+// behavior has been fixed.
+
+// check-pass
+
+fn peculiar() -> impl Fn(u8) -> u8 {
+ return |x| x + 1
+}
+
+fn peculiar2() -> impl Fn(u8) -> u8 {
+ return |x| x + 1;
+}
+
+fn peculiar3() -> impl Fn(u8) -> u8 {
+ let f = |x| x + 1;
+ return f
+}
+
+fn peculiar4() -> impl Fn(u8) -> u8 {
+ let f = |x| x + 1;
+ f
+}
+
+fn peculiar5() -> impl Fn(u8) -> u8 {
+ let f = |x| x + 1;
+ let g = |x| x + 2;
+ return if true { f } else { g }
+}
+
+fn main() {}
LL | impl NotObjectSafe for dyn NotObjectSafe { }
| ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object
|
- = help: consider moving `eq` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43
|
| ------------- ^^^^ ...because method `eq` references the `Self` type in this parameter
| |
| this trait cannot be made into an object...
+ = help: consider moving `eq` to another trait
error: aborting due to previous error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
--> $DIR/coherence-unsafe-trait-object-impl.rs:15:13
|
LL | takes_t(t);
- | ^ the trait `Trait` is not implemented for `&dyn Trait`
+ | ------- ^ the trait `Trait` is not implemented for `&dyn Trait`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `takes_t`
--> $DIR/coherence-unsafe-trait-object-impl.rs:10:15
// run-pass
+
+#![allow(dead_code)]
+
use std::fmt::Debug;
#[derive(Debug)]
--- /dev/null
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: u8>(a: [(); N as usize]) {
+ bar::<{ N as usize as usize }>();
+ //~^ error: unconstrained generic constant
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
--- /dev/null
+error: unconstrained generic constant
+ --> $DIR/abstract-consts-as-cast-5.rs:5:11
+ |
+LL | bar::<{ N as usize as usize }>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:`
+
+error: aborting due to previous error
+
--> $DIR/array-size-in-generic-struct-param.rs:19:15
|
LL | arr: [u8; CFG.arr_size],
- | ^^^^^^^^^^^^ unsupported projection
+ | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
| ^^^^-------^^
| |
- | unsupported rvalue
+ | unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/let-bindings.rs:6:68
|
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
- | ^^^^^^-^^^^^^^^^^^^^
- | |
- | unsupported statement
+ | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/let-bindings.rs:6:35
|
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
- | ^^^^^^-^^^^^^^^^^^^^
- | |
- | unsupported statement
+ | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
LL | fn use_dyn(v: &dyn Foo) {
| ^^^^^^^ `Foo` cannot be made into an object
|
- = help: consider moving `test` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-err-ret.rs:8:23
|
| --- this trait cannot be made into an object...
LL | fn test(&self) -> [u8; bar::<Self>()];
| ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type
+ = help: consider moving `test` to another trait
error: aborting due to previous error
--- /dev/null
+#![feature(generic_const_exprs, adt_const_params, const_trait_impl)]
+#![allow(incomplete_features)]
+
+// test `N + N` unifies with explicit function calls for non-builtin-types
+#[derive(PartialEq, Eq)]
+struct Foo(u8);
+
+impl const std::ops::Add for Foo {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self::Output {
+ self
+ }
+}
+
+struct Evaluatable<const N: Foo>;
+
+fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
+ bar::<{ std::ops::Add::add(N, N) }>();
+}
+
+fn bar<const N: Foo>() {}
+
+// test that `N + N` unifies with explicit function calls for builin-types
+struct Evaluatable2<const N: usize>;
+
+fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) {
+ bar2::<{ std::ops::Add::add(N, N) }>();
+ //~^ error: unconstrained generic constant
+ // FIXME(generic_const_exprs) make this not an error
+}
+
+fn bar2<const N: usize>() {}
+
+fn main() {}
--- /dev/null
+error: unconstrained generic constant
+ --> $DIR/unify-op-with-fn-call.rs:28:12
+ |
+LL | bar2::<{ std::ops::Add::add(N, N) }>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:`
+
+error: aborting due to previous error
+
--> $DIR/unused_expr.rs:4:34
|
LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
- | ^^-----^^^^^
- | |
- | dead code
+ | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/unused_expr.rs:9:34
|
LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
- | ^^-----^^^^^
- | |
- | dead code
+ | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/unused_expr.rs:16:38
|
LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
- | ^^------^^^^^
- | |
- | dead code
+ | ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/issue-67375.rs:7:17
|
LL | inner: [(); { [|_: &T| {}; 0].len() }],
- | ^^^----------^^^^^^^^^^^^
- | |
- | unsupported rvalue
+ | ^^---------------^^^^^^^^
+ | |
+ | unsupported operation in generic constant
|
= help: consider moving this anonymous constant into a `const` function
| _____________^
LL | |
LL | | let x: Option<Box<Self>> = None;
- | | ---- unsupported rvalue
LL | |
LL | | 0
LL | | }],
- | |_____^
+ | |_____^ unsupported operation in generic constant, this may be supported in the future
|
= help: consider moving this anonymous constant into a `const` function
--> $DIR/issue-86530.rs:16:7
|
LL | z(" ");
- | ^^^ the trait `X` is not implemented for `&str`
+ | - ^^^ the trait `X` is not implemented for `&str`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `z`
--> $DIR/issue-86530.rs:10:8
--- /dev/null
+pub trait MyTrait {
+ type Assoc;
+}
+
+pub fn foo<S, T>(_s: S, _t: T)
+where
+ S: MyTrait,
+ T: MyTrait<Assoc == S::Assoc>,
+ //~^ ERROR: expected one of `,` or `>`, found `==`
+ //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied
+{
+}
+
+fn main() {}
--- /dev/null
+error: expected one of `,` or `>`, found `==`
+ --> $DIR/issue-87493.rs:8:22
+ |
+LL | T: MyTrait<Assoc == S::Assoc>,
+ | ^^ expected one of `,` or `>`
+ |
+help: if you meant to use an associated type binding, replace `==` with `=`
+ |
+LL | T: MyTrait<Assoc = S::Assoc>,
+ | ~
+
+error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-87493.rs:8:8
+ |
+LL | T: MyTrait<Assoc == S::Assoc>,
+ | ^^^^^^^------------------- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/issue-87493.rs:1:11
+ |
+LL | pub trait MyTrait {
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
help: change the type of the numeric literal from `u16` to `u8`
|
LL | assert_eq!(R.method::<1u8>(), 1);
- | ~~~
+ | ~~
error: aborting due to previous error
help: change the type of the numeric literal from `u16` to `u8`
|
LL | assert_eq!(R.method::<1u8>(), 1);
- | ~~~
+ | ~~
error: aborting due to previous error
--> $DIR/unused_braces.rs:9:14
|
LL | let _: A<{ 7 }>;
- | ^^^^^ help: remove these braces
+ | ^^ ^^
|
note: the lint level is defined here
--> $DIR/unused_braces.rs:3:9
|
LL | #![warn(unused_braces)]
| ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - let _: A<{ 7 }>;
+LL + let _: A<7>;
+ |
warning: 1 warning emitted
const X: () = std::unimplemented!();
//~^ ERROR evaluation of constant value failed
-//
+
const W: () = std::panic!(MSG);
//~^ ERROR evaluation of constant value failed
+const W2: () = std::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
+
const Z_CORE: () = core::panic!("cheese");
//~^ ERROR evaluation of constant value failed
const W_CORE: () = core::panic!(MSG);
//~^ ERROR evaluation of constant value failed
+
+const W2_CORE: () = core::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic.rs:22:20
+ --> $DIR/const_panic.rs:22:16
+ |
+LL | const W2: () = std::panic!("{}", MSG);
+ | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:16
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_panic.rs:25:20
|
LL | const Z_CORE: () = core::panic!("cheese");
- | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
+ | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:25:20
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic.rs:25:21
+ --> $DIR/const_panic.rs:28:21
|
LL | const Z2_CORE: () = core::panic!();
- | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
+ | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:28:21
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic.rs:28:20
+ --> $DIR/const_panic.rs:31:20
|
LL | const Y_CORE: () = core::unreachable!();
- | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
+ | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:31:20
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic.rs:31:20
+ --> $DIR/const_panic.rs:34:20
|
LL | const X_CORE: () = core::unimplemented!();
- | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
+ | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:34:20
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic.rs:34:20
+ --> $DIR/const_panic.rs:37:20
|
LL | const W_CORE: () = core::panic!(MSG);
- | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
+ | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:37:20
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_panic.rs:40:21
+ |
+LL | const W2_CORE: () = core::panic!("{}", MSG);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:40:21
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 10 previous errors
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0080`.
#![feature(const_panic)]
#![crate_type = "lib"]
+const MSG: &str = "hello";
+
const A: () = std::panic!("blåhaj");
//~^ ERROR evaluation of constant value failed
const D: () = std::unimplemented!();
//~^ ERROR evaluation of constant value failed
-const E: () = core::panic!("shark");
+const E: () = std::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
+
+const A_CORE: () = core::panic!("shark");
+//~^ ERROR evaluation of constant value failed
+
+const B_CORE: () = core::panic!();
//~^ ERROR evaluation of constant value failed
-const F: () = core::panic!();
+const C_CORE: () = core::unreachable!();
//~^ ERROR evaluation of constant value failed
-const G: () = core::unreachable!();
+const D_CORE: () = core::unimplemented!();
//~^ ERROR evaluation of constant value failed
-const H: () = core::unimplemented!();
+const E_CORE: () = core::panic!("{}", MSG);
//~^ ERROR evaluation of constant value failed
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:5:15
+ --> $DIR/const_panic_2021.rs:7:15
|
LL | const A: () = std::panic!("blåhaj");
- | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:5:15
+ | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:7:15
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:8:15
+ --> $DIR/const_panic_2021.rs:10:15
|
LL | const B: () = std::panic!();
- | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15
+ | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:10:15
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:11:15
+ --> $DIR/const_panic_2021.rs:13:15
|
LL | const C: () = std::unreachable!();
- | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15
+ | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:13:15
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:14:15
+ --> $DIR/const_panic_2021.rs:16:15
|
LL | const D: () = std::unimplemented!();
- | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15
+ | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:16:15
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:17:15
+ --> $DIR/const_panic_2021.rs:19:15
|
-LL | const E: () = core::panic!("shark");
- | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15
+LL | const E: () = std::panic!("{}", MSG);
+ | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:19:15
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:20:15
+ --> $DIR/const_panic_2021.rs:22:20
|
-LL | const F: () = core::panic!();
- | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15
+LL | const A_CORE: () = core::panic!("shark");
+ | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:22:20
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:23:15
+ --> $DIR/const_panic_2021.rs:25:20
|
-LL | const G: () = core::unreachable!();
- | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15
+LL | const B_CORE: () = core::panic!();
+ | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:25:20
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_panic_2021.rs:28:20
+ |
+LL | const C_CORE: () = core::unreachable!();
+ | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:28:20
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
- --> $DIR/const_panic_2021.rs:26:15
+ --> $DIR/const_panic_2021.rs:31:20
|
-LL | const H: () = core::unimplemented!();
- | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15
+LL | const D_CORE: () = core::unimplemented!();
+ | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:31:20
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 8 previous errors
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_panic_2021.rs:34:20
+ |
+LL | const E_CORE: () = core::panic!("{}", MSG);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:34:20
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0080`.
const fn test1<T: std::ops::Add>() {}
//[stock]~^ trait bounds
const fn test2(_x: &dyn Send) {}
-//[stock]~^ trait bounds
+//[stock]~^ trait objects in const fn are unstable
const fn test3() -> &'static dyn Send { loop {} }
-//[stock]~^ trait bounds
+//[stock]~^ trait objects in const fn are unstable
#[rustc_error]
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/const_fn_trait_bound.rs:10:16
|
LL | const fn test2(_x: &dyn Send) {}
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/const_fn_trait_bound.rs:12:21
|
LL | const fn test3() -> &'static dyn Send { loop {} }
--- /dev/null
+// run-pass
+#![allow(unused_imports)]
+use std::fmt;
+
+const A_I8_T
+ : [u32; (i8::MAX as i8 - 1i8) as usize]
+ = [0; (i8::MAX as usize) - 1];
+
+fn main() {
+ foo(&A_I8_T[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+ println!("{:?}", x);
+}
--- /dev/null
+// run-pass
+
+#![warn(pointer_structural_match)]
+#![allow(dead_code)]
+const C: *const u8 = &0;
+
+fn foo(x: *const u8) {
+ match x {
+ C => {}
+ _ => {}
+ }
+}
+
+const D: *const [u8; 4] = b"abcd";
+
+fn main() {
+ match D {
+ D => {}
+ _ => {}
+ }
+}
--- /dev/null
+// Regression test for the ICE described in #89088.
+
+// check-pass
+
+#![allow(indirect_structural_match)]
+use std::borrow::Cow;
+
+const FOO: &A = &A::Field(Cow::Borrowed("foo"));
+
+#[derive(PartialEq, Eq)]
+enum A {
+ Field(Cow<'static, str>)
+}
+
+fn main() {
+ let var = A::Field(Cow::Borrowed("bar"));
+
+ match &var {
+ FOO => todo!(),
+ _ => todo!()
+ }
+}
//~^ ERROR trait bounds other than `Sized`
//~| ERROR destructor
const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
const fn no_unsafe() { unsafe {} }
const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-//~^ ERROR trait bounds other than `Sized`
-//~| ERROR trait bounds other than `Sized`
-//~| ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
+//~| ERROR trait objects in const fn are unstable
+//~| ERROR trait objects in const fn are unstable
const fn no_fn_ptrs(_x: fn()) {}
//~^ ERROR function pointer
|
LL | impl<T: std::fmt::Debug> Foo<T> {
| ^
+LL |
+LL | const fn foo(&self) {}
+ | ------------------- function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
|
LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
| ^
+LL |
+LL | const fn foo2(&self) {}
+ | -------------------- function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
|
LL | impl<T: Sync + Sized> Foo<T> {
| ^
+LL |
+LL | const fn foo3(&self) {}
+ | -------------------- function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
| |
| constant functions cannot evaluate destructors
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn.rs:132:23
|
LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn.rs:134:32
|
LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn.rs:139:41
|
LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn.rs:139:42
|
LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn.rs:139:42
|
LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
const fn no_inner_dyn_trait(_x: Hide) {}
const fn no_inner_dyn_trait2(x: Hide) {
x.0.field;
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
}
const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
fn main() {}
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn_dyn.rs:9:5
|
+LL | const fn no_inner_dyn_trait2(x: Hide) {
+ | ------------------------------------- function declared as const here
LL | x.0.field;
| ^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
--> $DIR/min_const_fn_dyn.rs:12:66
|
LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
- | ^^
+ | ----------------------------------------- ^^
+ | |
+ | function declared as const here
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
--- /dev/null
+// check-pass
+
+#![feature(fn_traits)]
+#![feature(adt_const_params)]
+//~^ WARNING the feature `adt_const_params` is incomplete
+
+#[derive(PartialEq, Eq)]
+struct CompileTimeSettings{
+ hooks: &'static[fn()],
+}
+
+struct Foo<const T: CompileTimeSettings>;
+
+impl<const T: CompileTimeSettings> Foo<T> {
+ fn call_hooks(){
+ }
+}
+
+fn main(){
+ const SETTINGS: CompileTimeSettings = CompileTimeSettings{
+ hooks: &[],
+ };
+
+ Foo::<SETTINGS>::call_hooks();
+}
--- /dev/null
+warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/refs_check_const_eq-issue-88384.rs:4:12
+ |
+LL | #![feature(adt_const_params)]
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+warning: 1 warning emitted
+
--- /dev/null
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(adt_const_params)]
+
+struct FooConst<const ARRAY: &'static [&'static str]> {}
+
+const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"];
+
+fn main() {
+ let _ = FooConst::<FOO_ARR> {};
+}
--- /dev/null
+// Checks that derived implementations of Clone and Debug do not
+// contribute to dead code analysis (issue #84647).
+
+#![forbid(dead_code)]
+
+struct A { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Clone)]
+struct B { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug)]
+struct C { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug,Clone)]
+struct D { f: () }
+//~^ ERROR: field is never read: `f`
+
+struct E { f: () }
+//~^ ERROR: field is never read: `f`
+// Custom impl, still doesn't read f
+impl Clone for E {
+ fn clone(&self) -> Self {
+ Self { f: () }
+ }
+}
+
+struct F { f: () }
+// Custom impl that actually reads f
+impl Clone for F {
+ fn clone(&self) -> Self {
+ Self { f: self.f }
+ }
+}
+
+fn main() {
+ let _ = A { f: () };
+ let _ = B { f: () };
+ let _ = C { f: () };
+ let _ = D { f: () };
+ let _ = E { f: () };
+ let _ = F { f: () };
+}
--- /dev/null
+error: field is never read: `f`
+ --> $DIR/clone-debug-dead-code.rs:6:12
+ |
+LL | struct A { f: () }
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/clone-debug-dead-code.rs:4:11
+ |
+LL | #![forbid(dead_code)]
+ | ^^^^^^^^^
+
+error: field is never read: `f`
+ --> $DIR/clone-debug-dead-code.rs:10:12
+ |
+LL | struct B { f: () }
+ | ^^^^^
+
+error: field is never read: `f`
+ --> $DIR/clone-debug-dead-code.rs:14:12
+ |
+LL | struct C { f: () }
+ | ^^^^^
+
+error: field is never read: `f`
+ --> $DIR/clone-debug-dead-code.rs:18:12
+ |
+LL | struct D { f: () }
+ | ^^^^^
+
+error: field is never read: `f`
+ --> $DIR/clone-debug-dead-code.rs:21:12
+ |
+LL | struct E { f: () }
+ | ^^^^^
+
+error: aborting due to 5 previous errors
+
--> $DIR/deriving-copyclone.rs:31:13
|
LL | is_copy(B { a: 1, b: C });
- | ^^^^^^^^^^^^^^^^
- | |
- | expected an implementor of trait `Copy`
- | help: consider borrowing here: `&B { a: 1, b: C }`
+ | ------- ^^^^^^^^^^^^^^^^
+ | | |
+ | | expected an implementor of trait `Copy`
+ | | help: consider borrowing here: `&B { a: 1, b: C }`
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Copy` for `B<C>`
--> $DIR/deriving-copyclone.rs:9:10
--> $DIR/deriving-copyclone.rs:32:14
|
LL | is_clone(B { a: 1, b: C });
- | ^^^^^^^^^^^^^^^^
- | |
- | expected an implementor of trait `Clone`
- | help: consider borrowing here: `&B { a: 1, b: C }`
+ | -------- ^^^^^^^^^^^^^^^^
+ | | |
+ | | expected an implementor of trait `Clone`
+ | | help: consider borrowing here: `&B { a: 1, b: C }`
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Clone` for `B<C>`
--> $DIR/deriving-copyclone.rs:9:16
--> $DIR/deriving-copyclone.rs:35:13
|
LL | is_copy(B { a: 1, b: D });
- | ^^^^^^^^^^^^^^^^
- | |
- | expected an implementor of trait `Copy`
- | help: consider borrowing here: `&B { a: 1, b: D }`
+ | ------- ^^^^^^^^^^^^^^^^
+ | | |
+ | | expected an implementor of trait `Copy`
+ | | help: consider borrowing here: `&B { a: 1, b: D }`
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Copy` for `B<D>`
--> $DIR/deriving-copyclone.rs:9:10
// run-pass
// pretty-expanded FIXME #23616
+#![allow(dead_code)]
+
#[derive(Clone)]
struct S<T> {
foo: (),
// run-pass
// pretty-expanded FIXME #23616
+#![allow(dead_code)]
+
#[derive(Clone)]
struct S {
_int: isize,
// run-pass
// pretty-expanded FIXME #23616
+#![allow(dead_code)]
+
#[derive(Clone)]
struct S((), ());
// run-pass
+
+#![allow(dead_code)]
+
pub fn main() {
#[derive(Debug)]
struct Foo {
--- /dev/null
+// run-pass
+
+#[derive(PartialEq)]
+struct Bike {
+ name: String,
+}
+
+pub fn main() {
+ let town_bike = Bike { name: "schwinn".to_string() };
+ let my_bike = Bike { name: "surly".to_string() };
+
+ assert!(town_bike != my_bike);
+}
--> $DIR/issue-39802-show-5-trait-impls.rs:24:21
|
LL | Foo::<i32>::bar(&1i8);
- | ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+ | --------------- ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<i8 as Foo<bool>>
--> $DIR/issue-39802-show-5-trait-impls.rs:25:21
|
LL | Foo::<i32>::bar(&1u8);
- | ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+ | --------------- ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<u8 as Foo<bool>>
--> $DIR/issue-39802-show-5-trait-impls.rs:26:21
|
LL | Foo::<i32>::bar(&true);
- | ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+ | --------------- ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<bool as Foo<bool>>
--- /dev/null
+fn main() {}
+
+const FOO: [u8; 3] = { //~ ERROR this code is interpreted as a block expression
+ 1, 2, 3
+};
+
+const BAR: [&str; 3] = {"one", "two", "three"};
+//~^ ERROR this code is interpreted as a block expression
+
+fn foo() {
+ {1, 2, 3};
+ //~^ ERROR this code is interpreted as a block expression
+}
+
+fn bar() {
+ 1, 2, 3 //~ ERROR expected one of
+}
--- /dev/null
+error: this code is interpreted as a block expression, not an array
+ --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22
+ |
+LL | const FOO: [u8; 3] = {
+ | ______________________^
+LL | | 1, 2, 3
+LL | | };
+ | |_^
+ |
+ = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+ |
+LL ~ const FOO: [u8; 3] = [
+LL | 1, 2, 3
+LL ~ ];
+ |
+
+error: this code is interpreted as a block expression, not an array
+ --> $DIR/issue-87830-try-brackets-for-arrays.rs:7:24
+ |
+LL | const BAR: [&str; 3] = {"one", "two", "three"};
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+ |
+LL | const BAR: [&str; 3] = ["one", "two", "three"];
+ | ~ ~
+
+error: this code is interpreted as a block expression, not an array
+ --> $DIR/issue-87830-try-brackets-for-arrays.rs:11:5
+ |
+LL | {1, 2, 3};
+ | ^^^^^^^^^
+ |
+ = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+ |
+LL | [1, 2, 3];
+ | ~ ~
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+ --> $DIR/issue-87830-try-brackets-for-arrays.rs:16:6
+ |
+LL | 1, 2, 3
+ | ^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: aborting due to 4 previous errors
+
help: change the type of the numeric literal from `u8` to `i8`
|
LL | OhNo = 0_i8,
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:28:16
help: change the type of the numeric literal from `i8` to `u8`
|
LL | OhNo = 0_u8,
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:41:16
help: change the type of the numeric literal from `u16` to `i16`
|
LL | OhNo = 0_i16,
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:54:16
help: change the type of the numeric literal from `i16` to `u16`
|
LL | OhNo = 0_u16,
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:67:16
help: change the type of the numeric literal from `u32` to `i32`
|
LL | OhNo = 0_i32,
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:80:16
help: change the type of the numeric literal from `i32` to `u32`
|
LL | OhNo = 0_u32,
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:93:16
help: change the type of the numeric literal from `u64` to `i64`
|
LL | OhNo = 0_i64,
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/discrim-ill-typed.rs:106:16
help: change the type of the numeric literal from `i64` to `u64`
|
LL | OhNo = 0_u64,
- | ~~~~~
+ | ~~~
error: aborting due to 8 previous errors
+++ /dev/null
-// Test that enabling an unstable feature disables warnings
-
-// aux-build:stability-cfg2.rs
-
-#![feature(unstable_test_feature)]
-#![deny(non_snake_case)] // To trigger a hard error
-
-// Shouldn't generate a warning about unstable features
-extern crate stability_cfg2;
-
-pub fn BOGUS() { } //~ ERROR
-
-pub fn main() { }
+++ /dev/null
-error: function `BOGUS` should have a snake case name
- --> $DIR/enable-unstable-lib-feature.rs:11:8
- |
-LL | pub fn BOGUS() { }
- | ^^^^^ help: convert the identifier to snake case: `bogus`
- |
-note: the lint level is defined here
- --> $DIR/enable-unstable-lib-feature.rs:6:9
- |
-LL | #![deny(non_snake_case)] // To trigger a hard error
- | ^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
--- /dev/null
+// Check that niche selection prefers zero.
+// See https://github.com/rust-lang/rust/pull/87794
+// run-pass
+#[repr(u8)]
+pub enum Size {
+ One = 1,
+ Two = 2,
+ Three = 3,
+}
+
+fn main() {
+ // check that `None` is zero
+ assert_eq!(0, unsafe { std::mem::transmute::<Option<Size>, u8>(None) });
+}
LL | fn call_foo(x: Box<dyn Trait>) {
| ^^^^^^^^^ `Trait` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/E0038.rs:2:22
|
| ----- this trait cannot be made into an object...
LL | fn foo(&self) -> Self;
| ^^^^ ...because method `foo` references the `Self` type in its return type
+ = help: consider moving `foo` to another trait
error: aborting due to previous error
help: use fully qualified syntax to disambiguate
|
LL | let _: <Self as Foo>::A;
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~
help: use fully qualified syntax to disambiguate
|
LL | let _: <Self as Bar>::A;
- | ~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~~~~~~~
error[E0221]: ambiguous associated type `Err` in bounds of `Self`
--> $DIR/E0221.rs:21:16
| ------------- ambiguous `Err` from `My`
LL | fn test() {
LL | let _: Self::Err;
- | ^^^^^^^^^
- | |
- | ambiguous associated type `Err`
- | help: use fully qualified syntax to disambiguate: `<Self as My>::Err`
+ | ^^^^^^^^^ ambiguous associated type `Err`
|
= note: associated type `Self` could derive from `FromStr`
+help: use fully qualified syntax to disambiguate
+ |
+LL | let _: <Self as My>::Err;
+ | ~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
--> $DIR/E0277.rs:15:15
|
LL | some_func(5i32);
- | ^^^^ the trait `Foo` is not implemented for `i32`
+ | --------- ^^^^ the trait `Foo` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `some_func`
--> $DIR/E0277.rs:7:17
+++ /dev/null
-#![feature(platform_intrinsics)]
-
-extern "platform-intrinsic" {
- fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
-}
-
-fn main () {
-}
+++ /dev/null
-error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle`
- --> $DIR/E0439.rs:4:5
- |
-LL | fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0439`.
--> $DIR/error-should-say-copy-not-pod.rs:6:17
|
LL | check_bound("nocopy".to_string());
- | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check_bound`
--> $DIR/error-should-say-copy-not-pod.rs:3:18
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-// Issue #521
-
-// pretty-expanded FIXME #23616
-
-fn f() {
- let _x = match true {
- true => { 10 }
- false => { return }
- };
-}
-
-pub fn main() { }
--- /dev/null
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+ let num = 5;
+ (1..num).reduce(|a, b| {
+ //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+ println!("{}", a);
+ a * b
+ }).unwrap();
+}
--- /dev/null
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+ let num = 5;
+ (1..num).reduce(|a, b|
+ //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+ println!("{}", a);
+ a * b
+ ).unwrap();
+}
--- /dev/null
+error: closure bodies that contain statements must be surrounded by braces
+ --> $DIR/missing_braces_around_block.rs:14:26
+ |
+LL | (1..num).reduce(|a, b|
+ | ^
+...
+LL | ).unwrap();
+ | ^
+ |
+note: statement found outside of a block
+ --> $DIR/missing_braces_around_block.rs:16:26
+ |
+LL | println!("{}", a);
+ | -----------------^ this `;` turns the preceding closure into a statement
+ | |
+ | this expression is a statement because of the trailing semicolon
+note: the closure body may be incorrectly delimited
+ --> $DIR/missing_braces_around_block.rs:14:21
+ |
+LL | (1..num).reduce(|a, b|
+ | _____________________^
+LL | |
+LL | | println!("{}", a);
+ | |_________________________^ this is the parsed closure...
+LL | a * b
+LL | ).unwrap();
+ | - ...but likely you meant the closure to end here
+help: try adding braces
+ |
+LL ~ (1..num).reduce(|a, b| {
+LL |
+LL | println!("{}", a);
+LL | a * b
+LL ~ }).unwrap();
+ |
+
+error: aborting due to previous error
+
--- /dev/null
+// Part of issue #27300.
+// The problem here is that ruby-style closures are parsed as blocks whose
+// first statement is a closure. See the issue for more details:
+// https://github.com/rust-lang/rust/issues/27300
+
+// Note: this test represents what the compiler currently emits. The error
+// message will be improved later.
+
+fn main() {
+ let p = Some(45).and_then({
+ //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+ |x| println!("doubling {}", x);
+ Some(x * 2)
+ //~^ ERROR: cannot find value `x` in this scope
+ });
+}
--- /dev/null
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/ruby_style_closure.rs:13:14
+ |
+LL | Some(x * 2)
+ | ^ not found in this scope
+
+error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+ --> $DIR/ruby_style_closure.rs:10:31
+ |
+LL | let p = Some(45).and_then({
+ | ______________________--------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | | |x| println!("doubling {}", x);
+LL | | Some(x * 2)
+ | | -----------
+LL | |
+LL | | });
+ | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
+ |
+ = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
--> $DIR/extern-wrong-value-type.rs:9:11
|
LL | is_fn(f);
- | ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+ | ----- ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
= note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
| ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8
|
| -------------- this trait cannot be made into an object...
LL | fn foo<T>(&self);
| ^^^ ...because method `foo` has generic type parameters
+ = help: consider moving `foo` to another trait
error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
--> $DIR/feature-gate-object_safe_for_dispatch.rs:31:35
LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22
|
| -------------- this trait cannot be made into an object...
LL | fn foo(&self, s: &Self);
| ^^^^^ ...because method `foo` references the `Self` type in this parameter
+ = help: consider moving `foo` to another trait
error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
--> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16
+++ /dev/null
-struct Foo {
- foo: u8,
- _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658]
- //~^ ERROR unnamed fields are not yet fully implemented [E0658]
- //~| ERROR anonymous unions are unimplemented
- bar: u8,
- baz: u16
- }
-}
-
-union Bar {
- foobar: u8,
- _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658]
- //~^ ERROR unnamed fields are not yet fully implemented [E0658]
- //~| ERROR anonymous structs are unimplemented
- //~| ERROR unions may not contain fields that need dropping [E0740]
- foobaz: u8,
- barbaz: u16
- }
-}
-
-struct S;
-struct Baz {
- _: S //~ ERROR unnamed fields are not yet fully implemented [E0658]
-}
-
-fn main(){}
+++ /dev/null
-error[E0658]: unnamed fields are not yet fully implemented
- --> $DIR/feature-gate-unnamed_fields.rs:3:5
- |
-LL | _: union {
- | ^
- |
- = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
- = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
- --> $DIR/feature-gate-unnamed_fields.rs:3:8
- |
-LL | _: union {
- | ________^
-LL | |
-LL | |
-LL | | bar: u8,
-LL | | baz: u16
-LL | | }
- | |_____^
- |
- = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
- = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
- --> $DIR/feature-gate-unnamed_fields.rs:13:5
- |
-LL | _: struct {
- | ^
- |
- = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
- = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
- --> $DIR/feature-gate-unnamed_fields.rs:13:8
- |
-LL | _: struct {
- | ________^
-LL | |
-LL | |
-LL | |
-LL | | foobaz: u8,
-LL | | barbaz: u16
-LL | | }
- | |_____^
- |
- = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
- = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
- --> $DIR/feature-gate-unnamed_fields.rs:24:5
- |
-LL | _: S
- | ^
- |
- = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
- = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error: anonymous unions are unimplemented
- --> $DIR/feature-gate-unnamed_fields.rs:3:8
- |
-LL | _: union {
- | ________^
-LL | |
-LL | |
-LL | | bar: u8,
-LL | | baz: u16
-LL | | }
- | |_____^
-
-error: anonymous structs are unimplemented
- --> $DIR/feature-gate-unnamed_fields.rs:13:8
- |
-LL | _: struct {
- | ________^
-LL | |
-LL | |
-LL | |
-LL | | foobaz: u8,
-LL | | barbaz: u16
-LL | | }
- | |_____^
-
-error[E0740]: unions may not contain fields that need dropping
- --> $DIR/feature-gate-unnamed_fields.rs:13:5
- |
-LL | / _: struct {
-LL | |
-LL | |
-LL | |
-LL | | foobaz: u8,
-LL | | barbaz: u16
-LL | | }
- | |_____^
- |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
- --> $DIR/feature-gate-unnamed_fields.rs:13:5
- |
-LL | / _: struct {
-LL | |
-LL | |
-LL | |
-LL | | foobaz: u8,
-LL | | barbaz: u16
-LL | | }
- | |_____^
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0658, E0740.
-For more information about an error, try `rustc --explain E0658`.
| +
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
- --> $DIR/feature-gate-unsized_fn_params.rs:24:5
+ --> $DIR/feature-gate-unsized_fn_params.rs:24:9
|
LL | foo(*x);
- | ^^^ doesn't have a size known at compile-time
+ | ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
= note: all function arguments must have a statically known size
help: change the type of the numeric literal from `f64` to `f32`
|
LL | let y: f32 = 1f32;
- | ~~~~
+ | ~~~
error: aborting due to 2 previous errors
--> $DIR/fn-trait-formatting.rs:19:14
|
LL | needs_fn(1);
- | ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+ | -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
note: required by a bound in `needs_fn`
--- /dev/null
+// Regression test for #88653, where a confusing warning about a
+// type mismatch in generator arguments was issued.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn foo(bar: bool) -> impl Generator<(bool,)> {
+//~^ ERROR: type mismatch in generator arguments [E0631]
+//~| NOTE: expected signature of `fn((bool,)) -> _`
+ |bar| {
+ //~^ NOTE: found signature of `fn(bool) -> _`
+ if bar {
+ yield bar;
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0631]: type mismatch in generator arguments
+ --> $DIR/issue-88653.rs:8:22
+ |
+LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _`
+...
+LL | |bar| {
+ | ----- found signature of `fn(bool) -> _`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
--> $DIR/static-not-unpin.rs:14:18
|
LL | assert_unpin(generator);
- | ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+ | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+ | |
+ | required by a bound introduced by this call
|
= note: consider using `Box::pin`
note: required by a bound in `assert_unpin`
LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
- = help: consider moving `A` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/gat-in-trait-path.rs:5:10
|
| --- this trait cannot be made into an object...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
+ = help: consider moving `A` to another trait
error: aborting due to previous error
type A<'a> where Self: 'static = (&'a ());
//~^ ERROR the parameter type `T` may not live long enough
type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
- //~^ ERROR lifetime bound not satisfied
+ //~^ ERROR `impl` associated type
//~| ERROR lifetime bound not satisfied
type C where Self: Copy = String;
//~^ ERROR the trait bound `T: Copy` is not satisfied
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'static`...
- = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
+ = note: ...so that the definition in impl matches the definition from the trait
-error[E0478]: lifetime bound not satisfied
+error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
--> $DIR/impl_bounds.rs:17:5
|
+LL | type B<'a, 'b> where 'a: 'b;
+ | ---------------------------- expected
+...
LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
- --> $DIR/impl_bounds.rs:17:16
- |
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
- | ^^
-note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
- --> $DIR/impl_bounds.rs:17:12
- |
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
- | ^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
error[E0478]: lifetime bound not satisfied
--> $DIR/impl_bounds.rs:17:5
LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
|
- = help: consider moving `Y` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-67510-pass.rs:4:10
|
| - this trait cannot be made into an object...
LL | type Y<'a>;
| ^ ...because it contains the generic associated type `Y`
+ = help: consider moving `Y` to another trait
error: aborting due to previous error
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
- = help: consider moving `SubType` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-76535.rs:6:10
|
| ---------- this trait cannot be made into an object...
LL | type SubType<'a>: SubTrait;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
+ = help: consider moving `SubType` to another trait
error[E0038]: the trait `SuperTrait` cannot be made into an object
--> $DIR/issue-76535.rs:36:57
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
|
- = help: consider moving `SubType` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-76535.rs:6:10
|
| ---------- this trait cannot be made into an object...
LL | type SubType<'a>: SubTrait;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
+ = help: consider moving `SubType` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
= note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
|
- = help: consider moving `Member` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-78671.rs:4:10
|
| ---------------- this trait cannot be made into an object...
LL | type Member<T>;
| ^^^^^^ ...because it contains the generic associated type `Member`
+ = help: consider moving `Member` to another trait
error: aborting due to 2 previous errors
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
- = help: consider moving `VRefCont` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-79422.rs:20:10
|
| ------- this trait cannot be made into an object...
LL | type VRefCont<'a>: RefCont<'a, V>;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+ = help: consider moving `VRefCont` to another trait
error[E0038]: the trait `MapLike` cannot be made into an object
--> $DIR/issue-79422.rs:41:13
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
|
- = help: consider moving `VRefCont` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-79422.rs:20:10
|
| ------- this trait cannot be made into an object...
LL | type VRefCont<'a>: RefCont<'a, V>;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+ = help: consider moving `VRefCont` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
= note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
LL | | <Right as HasChildrenOf>::T: 'a
| | - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
LL | | = Either<&'a Left::T, &'a Right::T>;
- | |________________________________________^ ...so that the type `<Left as HasChildrenOf>::T` will meet its required lifetime bounds
+ | |________________________________________^ ...so that the definition in impl matches the definition from the trait
error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
--> $DIR/issue-86787.rs:23:5
LL | | <Right as HasChildrenOf>::T: 'a
| | - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
LL | | = Either<&'a Left::T, &'a Right::T>;
- | |________________________________________^ ...so that the type `<Right as HasChildrenOf>::T` will meet its required lifetime bounds
+ | |________________________________________^ ...so that the definition in impl matches the definition from the trait
error: aborting due to 2 previous errors
--- /dev/null
+// check-fail
+
+#![feature(generic_associated_types)]
+
+trait Foo {
+ type Assoc<'a, 'b>;
+}
+impl Foo for () {
+ type Assoc<'a, 'b> where 'a: 'b = ();
+ //~^ `impl` associated type
+}
+
+fn main() {}
--- /dev/null
+error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
+ --> $DIR/missing-where-clause-on-trait.rs:9:5
+ |
+LL | type Assoc<'a, 'b>;
+ | ------------------- expected
+...
+LL | type Assoc<'a, 'b> where 'a: 'b = ();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
+
+error: aborting due to previous error
+
LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
|
- = help: consider moving `Item` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/trait-objects.rs:4:10
|
| ----------------- this trait cannot be made into an object...
LL | type Item<'a> where Self: 'a;
| ^^^^ ...because it contains the generic associated type `Item`
+ = help: consider moving `Item` to another trait
error: aborting due to previous error
--- /dev/null
+// run-pass
+
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct S<T> {
+ contents: T,
+}
+
+impl<T> S<T> {
+ fn new<U>(x: T, _: U) -> S<T> {
+ S {
+ contents: x,
+ }
+ }
+}
+
+trait Trait<T> {
+ fn new<U>(x: T, y: U) -> Self;
+}
+
+struct S2 {
+ contents: isize,
+}
+
+impl Trait<isize> for S2 {
+ fn new<U>(x: isize, _: U) -> S2 {
+ S2 {
+ contents: x,
+ }
+ }
+}
+
+pub fn main() {
+ let _ = S::<isize>::new::<f64>(1, 1.0);
+ let _: S2 = Trait::<isize>::new::<f64>(1, 1.0);
+}
+++ /dev/null
-// run-pass
-
-#![allow(non_shorthand_field_patterns)]
-
-#[derive(Copy, Clone)]
-struct Pair { x: isize, y: isize }
-
-pub fn main() {
- let a: isize =
- match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } };
- assert_eq!(a, 2);
-
- let b: isize =
- match (Pair {x: 10, y: 20}) {
- x if x.x < 5 && x.y < 5 => { 1 }
- Pair {x: x, y: y} if x == 10 && y == 20 => { 2 }
- Pair {x: _x, y: _y} => { 3 }
- };
- assert_eq!(b, 2);
-}
error[E0631]: type mismatch in closure arguments
--> $DIR/issue-62529-1.rs:80:10
|
-LL | task(annotate(
- | ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
-...
-LL | |value: &mut usize| {
- | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+LL | task(annotate(
+ | _____----_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | | Annotate::<RefMutFamily<usize>>::new(),
+LL | | |value: &mut usize| {
+ | | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+LL | | *value = 2;
+LL | | }
+LL | | ));
+ | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
|
note: required by a bound in `annotate`
--> $DIR/issue-62529-1.rs:44:8
--> $DIR/issue-62529-1.rs:80:10
|
LL | task(annotate(
- | __________^
+ | _____----_^
+ | | |
+ | | required by a bound introduced by this call
LL | |
LL | |
LL | | Annotate::<RefMutFamily<usize>>::new(),
--> $DIR/issue-62529-1.rs:80:10
|
LL | task(annotate(
- | __________^
+ | _____----_^
+ | | |
+ | | required by a bound introduced by this call
LL | |
LL | |
LL | | Annotate::<RefMutFamily<usize>>::new(),
--> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
|
LL | want_bar_for_any_ccx(b);
- | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `want_bar_for_any_ccx`
--> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
--> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
|
LL | want_foo_for_any_tcx(f);
- | ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+ | -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `want_foo_for_any_tcx`
--> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
--> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
|
LL | want_bar_for_any_ccx(b);
- | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `want_bar_for_any_ccx`
--> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
--- /dev/null
+// check-pass
+
+trait Yokeable<'a> {
+ type Output: 'a;
+}
+impl<'a> Yokeable<'a> for () {
+ type Output = ();
+}
+
+trait DataMarker<'data> {
+ type Yokeable: for<'a> Yokeable<'a>;
+}
+impl<'data> DataMarker<'data> for () {
+ type Yokeable = ();
+}
+
+struct DataPayload<'data, M>(&'data M);
+
+impl DataPayload<'static, ()> {
+ pub fn map_project_with_capture<M2, T>(
+ _: for<'a> fn(
+ capture: T,
+ std::marker::PhantomData<&'a ()>,
+ ) -> <M2::Yokeable as Yokeable<'a>>::Output,
+ ) -> DataPayload<'static, M2>
+ where
+ M2: DataMarker<'static>,
+ {
+ todo!()
+ }
+}
+
+fn main() {
+ let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!());
+}
--- /dev/null
+trait Foo {
+ type T;
+ fn foo(&self, t: Self::T);
+//~^ NOTE expected 0 type parameters
+}
+
+impl Foo for u32 {
+ type T = ();
+
+ fn foo(&self, t: impl Clone) {}
+//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+//~| NOTE found 1 type parameter
+//~| NOTE `impl Trait` introduces an implicit type parameter
+}
+
+fn main() {}
--- /dev/null
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+ --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
+ |
+LL | fn foo(&self, t: Self::T);
+ | - expected 0 type parameters
+...
+LL | fn foo(&self, t: impl Clone) {}
+ | ^^^^^^^^^^
+ | |
+ | found 1 type parameter
+ | `impl Trait` introduces an implicit type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
LL | bar::<isize>(i.try_into().unwrap()); // i should not be re-coerced back to an isize
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 2 previous errors
--- /dev/null
+fn foo(x: Result<i32, ()>) -> Result<(), ()> {
+ let y: u32 = x?;
+ //~^ ERROR: `?` operator has incompatible types
+ Ok(())
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: `?` operator has incompatible types
+ --> $DIR/issue-71309.rs:2:18
+ |
+LL | let y: u32 = x?;
+ | ^^ expected `u32`, found `i32`
+ |
+ = note: `?` operator cannot convert from `i32` to `u32`
+help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+ |
+LL | let y: u32 = x?.try_into().unwrap();
+ | ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:41:11
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:44:11
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:47:11
help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(asize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:51:12
|
LL | id_i16(a8);
- | ^^
- | |
- | expected `i16`, found `i8`
- | help: you can convert an `i8` to an `i16`: `a8.into()`
+ | ^^ expected `i16`, found `i8`
+ |
+help: you can convert an `i8` to an `i16`
+ |
+LL | id_i16(a8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:55:12
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(a32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:58:12
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(a64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:61:12
help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(asize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:65:12
|
LL | id_i32(a8);
- | ^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `a8.into()`
+ | ^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | id_i32(a8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:68:12
|
LL | id_i32(a16);
- | ^^^
- | |
- | expected `i32`, found `i16`
- | help: you can convert an `i16` to an `i32`: `a16.into()`
+ | ^^^ expected `i32`, found `i16`
+ |
+help: you can convert an `i16` to an `i32`
+ |
+LL | id_i32(a16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:72:12
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(a64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:75:12
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(asize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:79:12
|
LL | id_i64(a8);
- | ^^
- | |
- | expected `i64`, found `i8`
- | help: you can convert an `i8` to an `i64`: `a8.into()`
+ | ^^ expected `i64`, found `i8`
+ |
+help: you can convert an `i8` to an `i64`
+ |
+LL | id_i64(a8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:82:12
|
LL | id_i64(a16);
- | ^^^
- | |
- | expected `i64`, found `i16`
- | help: you can convert an `i16` to an `i64`: `a16.into()`
+ | ^^^ expected `i64`, found `i16`
+ |
+help: you can convert an `i16` to an `i64`
+ |
+LL | id_i64(a16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:85:12
|
LL | id_i64(a32);
- | ^^^
- | |
- | expected `i64`, found `i32`
- | help: you can convert an `i32` to an `i64`: `a32.into()`
+ | ^^^ expected `i64`, found `i32`
+ |
+help: you can convert an `i32` to an `i64`
+ |
+LL | id_i64(a32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:89:12
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
LL | id_i64(asize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:93:14
|
LL | id_isize(a8);
- | ^^
- | |
- | expected `isize`, found `i8`
- | help: you can convert an `i8` to an `isize`: `a8.into()`
+ | ^^ expected `isize`, found `i8`
+ |
+help: you can convert an `i8` to an `isize`
+ |
+LL | id_isize(a8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:96:14
|
LL | id_isize(a16);
- | ^^^
- | |
- | expected `isize`, found `i16`
- | help: you can convert an `i16` to an `isize`: `a16.into()`
+ | ^^^ expected `isize`, found `i16`
+ |
+help: you can convert an `i16` to an `isize`
+ |
+LL | id_isize(a16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:99:14
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
LL | id_isize(a32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:102:14
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
LL | id_isize(a64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:108:11
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:111:11
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:114:11
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:118:12
|
LL | id_i16(c8);
- | ^^
- | |
- | expected `i16`, found `i8`
- | help: you can convert an `i8` to an `i16`: `c8.into()`
+ | ^^ expected `i16`, found `i8`
+ |
+help: you can convert an `i8` to an `i16`
+ |
+LL | id_i16(c8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:122:12
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(c32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:125:12
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(c64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:129:12
|
LL | id_i32(c8);
- | ^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `c8.into()`
+ | ^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | id_i32(c8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:132:12
|
LL | id_i32(c16);
- | ^^^
- | |
- | expected `i32`, found `i16`
- | help: you can convert an `i16` to an `i32`: `c16.into()`
+ | ^^^ expected `i32`, found `i16`
+ |
+help: you can convert an `i16` to an `i32`
+ |
+LL | id_i32(c16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:136:12
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(c64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:140:12
|
LL | id_i64(a8);
- | ^^
- | |
- | expected `i64`, found `i8`
- | help: you can convert an `i8` to an `i64`: `a8.into()`
+ | ^^ expected `i64`, found `i8`
+ |
+help: you can convert an `i8` to an `i64`
+ |
+LL | id_i64(a8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:143:12
|
LL | id_i64(a16);
- | ^^^
- | |
- | expected `i64`, found `i16`
- | help: you can convert an `i16` to an `i64`: `a16.into()`
+ | ^^^ expected `i64`, found `i16`
+ |
+help: you can convert an `i16` to an `i64`
+ |
+LL | id_i64(a16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:146:12
|
LL | id_i64(a32);
- | ^^^
- | |
- | expected `i64`, found `i32`
- | help: you can convert an `i32` to an `i64`: `a32.into()`
+ | ^^^ expected `i64`, found `i32`
+ |
+help: you can convert an `i32` to an `i64`
+ |
+LL | id_i64(a32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:152:11
help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:155:11
help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:158:11
help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:161:11
help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(bsize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:165:12
|
LL | id_u16(b8);
- | ^^
- | |
- | expected `u16`, found `u8`
- | help: you can convert a `u8` to a `u16`: `b8.into()`
+ | ^^ expected `u16`, found `u8`
+ |
+help: you can convert a `u8` to a `u16`
+ |
+LL | id_u16(b8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:169:12
help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(b32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:172:12
help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(b64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:175:12
help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(bsize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:179:12
|
LL | id_u32(b8);
- | ^^
- | |
- | expected `u32`, found `u8`
- | help: you can convert a `u8` to a `u32`: `b8.into()`
+ | ^^ expected `u32`, found `u8`
+ |
+help: you can convert a `u8` to a `u32`
+ |
+LL | id_u32(b8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:182:12
|
LL | id_u32(b16);
- | ^^^
- | |
- | expected `u32`, found `u16`
- | help: you can convert a `u16` to a `u32`: `b16.into()`
+ | ^^^ expected `u32`, found `u16`
+ |
+help: you can convert a `u16` to a `u32`
+ |
+LL | id_u32(b16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:186:12
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
|
LL | id_u32(b64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:189:12
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | id_u32(bsize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:193:12
|
LL | id_u64(b8);
- | ^^
- | |
- | expected `u64`, found `u8`
- | help: you can convert a `u8` to a `u64`: `b8.into()`
+ | ^^ expected `u64`, found `u8`
+ |
+help: you can convert a `u8` to a `u64`
+ |
+LL | id_u64(b8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:196:12
|
LL | id_u64(b16);
- | ^^^
- | |
- | expected `u64`, found `u16`
- | help: you can convert a `u16` to a `u64`: `b16.into()`
+ | ^^^ expected `u64`, found `u16`
+ |
+help: you can convert a `u16` to a `u64`
+ |
+LL | id_u64(b16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:199:12
|
LL | id_u64(b32);
- | ^^^
- | |
- | expected `u64`, found `u32`
- | help: you can convert a `u32` to a `u64`: `b32.into()`
+ | ^^^ expected `u64`, found `u32`
+ |
+help: you can convert a `u32` to a `u64`
+ |
+LL | id_u64(b32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:203:12
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | id_u64(bsize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:207:14
|
LL | id_usize(b8);
- | ^^
- | |
- | expected `usize`, found `u8`
- | help: you can convert a `u8` to a `usize`: `b8.into()`
+ | ^^ expected `usize`, found `u8`
+ |
+help: you can convert a `u8` to a `usize`
+ |
+LL | id_usize(b8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:210:14
|
LL | id_usize(b16);
- | ^^^
- | |
- | expected `usize`, found `u16`
- | help: you can convert a `u16` to a `usize`: `b16.into()`
+ | ^^^ expected `usize`, found `u16`
+ |
+help: you can convert a `u16` to a `usize`
+ |
+LL | id_usize(b16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:213:14
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
LL | id_usize(b32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/integer-literal-suffix-inference.rs:216:14
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
LL | id_usize(b64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 52 previous errors
+++ /dev/null
-// compile-flags: -C opt-level=3
-// aux-build: issue-72470-lib.rs
-// edition:2018
-// build-pass
-
-// Regression test for issue #72470, using the minimization
-// in https://github.com/jonas-schievink/llvm-error
-
-extern crate issue_72470_lib;
-
-use std::future::Future;
-use std::pin::Pin;
-use std::sync::Mutex;
-use std::task::Poll::{Pending, Ready};
-
-#[allow(dead_code)]
-enum Msg {
- A(Vec<()>),
- B,
-}
-
-#[allow(dead_code)]
-enum Out {
- _0(Option<Msg>),
- Disabled,
-}
-
-#[allow(unused_must_use)]
-fn main() {
- let mut rx = issue_72470_lib::unbounded_channel::<Msg>();
- let entity = Mutex::new(());
- issue_72470_lib::run(async move {
- {
- let output = {
- let mut fut = rx.recv();
- issue_72470_lib::poll_fn(|cx| {
- loop {
- let fut = unsafe { Pin::new_unchecked(&mut fut) };
- let out = match fut.poll(cx) {
- Ready(out) => out,
- Pending => {
- break;
- }
- };
- #[allow(unused_variables)]
- match &out {
- Some(_msg) => {}
- _ => break,
- }
- return Ready(Out::_0(out));
- }
- Ready(Out::_0(None))
- })
- .await
- };
- match output {
- Out::_0(Some(_msg)) => {
- entity.lock();
- }
- Out::_0(None) => unreachable!(),
- _ => unreachable!(),
- }
- }
- entity.lock();
- });
-}
help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
|
LL | foo((1*(1 as isize)).try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | + +++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/issue-13359.rs:10:9
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | bar((1*(1 as usize)).try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | + +++++++++++++++++++++
error: aborting due to 2 previous errors
help: change the type of the numeric literal from `i32` to `u32`
|
LL | let x: u32 = 20u32;
- | ~~~~~
+ | ~~~
error: aborting due to previous error
help: change the type of the numeric literal from `i32` to `u32`
|
LL | println!("{}", foo(10u32));
- | ~~~~~
+ | ~~~
error: aborting due to previous error
fn main() {
(|| Box::new(*(&[0][..])))();
//~^ ERROR the size for values of type
- //~| ERROR the size for values of type
}
--> $DIR/issue-17651.rs:5:18
|
LL | (|| Box::new(*(&[0][..])))();
- | ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | -------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `[{integer}]`
note: required by `Box::<T>::new`
LL | pub fn new(x: T) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
- --> $DIR/issue-17651.rs:5:9
- |
-LL | (|| Box::new(*(&[0][..])))();
- | ^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `[{integer}]`
- = note: all function arguments must have a statically known size
- = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
LL | fn foo(b: &dyn Bar) {
| ^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-18959.rs:1:20
|
| ^^^ ...because method `foo` has generic type parameters
LL | pub trait Bar: Foo { }
| --- this trait cannot be made into an object...
+ = help: consider moving `foo` to another trait
error: aborting due to previous error
// run-pass
+
+#![allow(dead_code)]
+
trait Trait { fn dummy(&self) { } }
#[derive(Debug)]
LL | let test: &mut dyn Bar = &mut thing;
| ^^^^^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-19538.rs:2:8
|
...
LL | trait Bar: Foo { }
| --- this trait cannot be made into an object...
+ = help: consider moving `foo` to another trait
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-19538.rs:17:30
LL | let test: &mut dyn Bar = &mut thing;
| ^^^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-19538.rs:2:8
|
...
LL | trait Bar: Foo { }
| --- this trait cannot be made into an object...
+ = help: consider moving `foo` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
= note: required by cast to type `&mut dyn Bar`
+++ /dev/null
-trait From<Src> {
- type Output;
-
- fn from(src: Src) -> <Self as From<Src>>::Output;
-}
-
-trait To: Sized {
- fn to<Dst: From<Self>>(self) ->
- <Dst as From<Self>>::Dst
- //~^ ERROR cannot find associated type `Dst` in trait `From`
- {
- From::from(self)
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0576]: cannot find associated type `Dst` in trait `From`
- --> $DIR/issue-19883.rs:9:30
- |
-LL | type Output;
- | ------------ associated type `Output` defined here
-...
-LL | <Dst as From<Self>>::Dst
- | ^^^
- | |
- | not found in `From`
- | help: maybe you meant this associated type: `Output`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0576`.
--> $DIR/issue-20605.rs:2:17
|
LL | for item in *things { *item = 0 }
- | ^^^^^^^ doesn't have a size known at compile-time
+ | ^^^^^^^
+ | |
+ | expected an implementor of trait `IntoIterator`
+ | help: consider mutably borrowing here: `&mut *things`
|
- = help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+ = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
note: required by `into_iter`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+++ /dev/null
-trait Array: Sized + Copy {}
-
-fn f<T: Array>(x: &T) {
- let _ = x
- //~^ ERROR `Array` cannot be made into an object
- as
- &dyn Array;
- //~^ ERROR `Array` cannot be made into an object
-}
-
-fn main() {}
+++ /dev/null
-error[E0038]: the trait `Array` cannot be made into an object
- --> $DIR/issue-20692.rs:7:5
- |
-LL | &dyn Array;
- | ^^^^^^^^^^ `Array` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-20692.rs:1:14
- |
-LL | trait Array: Sized + Copy {}
- | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
- | | |
- | | ...because it requires `Self: Sized`
- | this trait cannot be made into an object...
-
-error[E0038]: the trait `Array` cannot be made into an object
- --> $DIR/issue-20692.rs:4:13
- |
-LL | let _ = x
- | ^ `Array` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-20692.rs:1:14
- |
-LL | trait Array: Sized + Copy {}
- | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
- | | |
- | | ...because it requires `Self: Sized`
- | this trait cannot be made into an object...
- = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Array>` for `&T`
- = note: required by cast to type `&dyn Array`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
+++ /dev/null
-// check-pass
-// pretty-expanded FIXME #23616
-
-#![no_implicit_prelude]
-
-trait Iterator {
- type Item;
- fn dummy(&self) { }
-}
-
-impl<'a, T> Iterator for &'a mut (dyn Iterator<Item=T> + 'a) {
- type Item = T;
-}
-
-fn main() {}
+++ /dev/null
-// run-pass
-trait Stringify {
- fn to_string(&self) -> String;
-}
-
-impl Stringify for u32 {
- fn to_string(&self) -> String { format!("u32: {}", *self) }
-}
-
-impl Stringify for f32 {
- fn to_string(&self) -> String { format!("f32: {}", *self) }
-}
-
-fn print<T: Stringify>(x: T) -> String {
- x.to_string()
-}
-
-fn main() {
- assert_eq!(&print(5), "u32: 5");
- assert_eq!(&print(5.0), "f32: 5");
-}
+++ /dev/null
-// run-pass
-#![allow(unused_imports)]
-use std::fmt;
-
-const A_I8_T
- : [u32; (i8::MAX as i8 - 1i8) as usize]
- = [0; (i8::MAX as usize) - 1];
-
-fn main() {
- foo(&A_I8_T[..]);
-}
-
-fn foo<T:fmt::Debug>(x: T) {
- println!("{:?}", x);
-}
--> $DIR/issue-23966.rs:2:32
|
LL | "".chars().fold(|_, _| (), ());
- | ^^ expected an `FnMut<(_, char)>` closure, found `()`
+ | ---- ^^ expected an `FnMut<(_, char)>` closure, found `()`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnMut<(_, char)>` is not implemented for `()`
--> $DIR/issue-25076.rs:10:20
|
LL | do_fold(bot(), ());
- | ^^ the trait `InOut<_>` is not implemented for `()`
+ | ------- ^^ the trait `InOut<_>` is not implemented for `()`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `do_fold`
--> $DIR/issue-25076.rs:5:18
--> $DIR/issue-28098.rs:2:28
|
LL | let _ = Iterator::next(&mut ());
- | ^^^^^^^ `()` is not an iterator
+ | -------------- ^^^^^^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Iterator` is not implemented for `()`
note: required by `std::iter::Iterator::next`
--> $DIR/issue-28098.rs:9:28
|
LL | let _ = Iterator::next(&mut ());
- | ^^^^^^^ `()` is not an iterator
+ | -------------- ^^^^^^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Iterator` is not implemented for `()`
note: required by `std::iter::Iterator::next`
--> $DIR/issue-28098.rs:18:28
|
LL | let _ = Iterator::next(&mut ());
- | ^^^^^^^ `()` is not an iterator
+ | -------------- ^^^^^^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Iterator` is not implemented for `()`
note: required by `std::iter::Iterator::next`
--> $DIR/issue-28098.rs:22:28
|
LL | let _ = Iterator::next(&mut ());
- | ^^^^^^^ `()` is not an iterator
+ | -------------- ^^^^^^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Iterator` is not implemented for `()`
note: required by `std::iter::Iterator::next`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
- --> $DIR/issue-30355.rs:5:6
+ --> $DIR/issue-30355.rs:5:8
|
LL | &X(*Y)
- | ^ doesn't have a size known at compile-time
+ | ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: all function arguments must have a statically known size
+++ /dev/null
-// run-pass
-#![allow(unused_variables)]
-pub fn main() {
- let x = (0, 2);
-
- match x {
- (0, ref y) => {}
- (y, 0) => {}
- _ => (),
- }
-}
+++ /dev/null
-// build-pass
-#![allow(dead_code)]
-
-struct A {
- a: &'static (),
-}
-
-static B: &'static A = &A { a: &() };
-static C: &'static A = &B;
-
-fn main() {}
fn main() {
Test::Drill(field: 42);
- //~^ ERROR expected type, found
+ //~^ ERROR invalid `struct` delimiters or `fn` call arguments
}
-error: expected type, found `42`
- --> $DIR/issue-34255-1.rs:8:24
+error: invalid `struct` delimiters or `fn` call arguments
+ --> $DIR/issue-34255-1.rs:8:5
|
LL | Test::Drill(field: 42);
- | - ^^ expected type
- | |
- | tried to parse a type due to this type ascription
+ | ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
- = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Test::Drill` is a struct, use braces as delimiters
+ |
+LL | Test::Drill { field: 42 };
+ | ~ ~
+help: if `Test::Drill` is a function, use the arguments directly
+ |
+LL - Test::Drill(field: 42);
+LL + Test::Drill(42);
+ |
error: aborting due to previous error
+++ /dev/null
-// run-pass
-
-#![warn(pointer_structural_match)]
-#![allow(dead_code)]
-const C: *const u8 = &0;
-
-fn foo(x: *const u8) {
- match x {
- C => {}
- _ => {}
- }
-}
-
-const D: *const [u8; 4] = b"abcd";
-
-fn main() {
- match D {
- D => {}
- _ => {}
- }
-}
+++ /dev/null
-// check-pass
-#![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
-
-fn main() {}
-
-pub trait Alpha<T> { }
-
-pub trait Beta {
- type Event;
-}
-
-pub trait Delta {
- type Handle;
- fn process(&self);
-}
-
-pub struct Parent<A, T>(A, T);
-
-impl<A, T> Delta for Parent<A, T>
-where A: Alpha<T::Handle>,
- T: Delta,
- T::Handle: Beta<Event = <Handle as Beta>::Event> {
- type Handle = Handle;
- default fn process(&self) {
- unimplemented!()
- }
-}
-
-impl<A, T> Delta for Parent<A, T>
-where A: Alpha<T::Handle> + Alpha<Handle>,
- T: Delta,
- T::Handle: Beta<Event = <Handle as Beta>::Event> {
- fn process(&self) {
- unimplemented!()
- }
-}
-
-pub struct Handle;
-
-impl Beta for Handle {
- type Event = ();
-}
+++ /dev/null
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/issue-35376.rs:2:12
- |
-LL | #![feature(specialization)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
- = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
+++ /dev/null
-// run-pass
-// compile-flags:--test
-#![deny(private_in_public)]
-
-#[test] fn foo() {}
-mod foo {}
-
-#[test] fn core() {}
-extern crate core;
+++ /dev/null
-// build-fail
-// ignore-emscripten no llvm_asm! support
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-fn main() {
- unsafe {
- llvm_asm!("" :: "r"(""));
- //~^ ERROR: invalid value for constraint in inline assembly
- }
-}
+++ /dev/null
-error[E0669]: invalid value for constraint in inline assembly
- --> $DIR/issue-37433.rs:9:29
- |
-LL | llvm_asm!("" :: "r"(""));
- | ^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0669`.
// run-pass
#![feature(box_syntax)]
+#![allow(dead_code)]
trait T {
fn print(&self);
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-// Check that constant ADTs are codegened OK, part k of N.
-
-enum Bar {
- C
-}
-
-enum Foo {
- A {},
- B {
- y: usize,
- z: Bar
- },
-}
-
-const LIST: [(usize, Foo); 2] = [
- (51, Foo::B { y: 42, z: Bar::C }),
- (52, Foo::B { y: 45, z: Bar::C }),
-];
-
-pub fn main() {
- match LIST {
- [
- (51, Foo::B { y: 42, z: Bar::C }),
- (52, Foo::B { y: 45, z: Bar::C })
- ] => {}
- _ => {
- // I would want to print the enum here, but if
- // the discriminant is garbage this causes an
- // `unreachable` and silent process exit.
- panic!("trivial match failed")
- }
- }
-}
+++ /dev/null
-// run-pass
-
-#[derive(PartialEq)]
-struct Bike {
- name: String,
-}
-
-pub fn main() {
- let town_bike = Bike { name: "schwinn".to_string() };
- let my_bike = Bike { name: "surly".to_string() };
-
- assert!(town_bike != my_bike);
-}
+++ /dev/null
-// Matching against float literals should result in a linter error
-
-#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
-#![allow(unused)]
-#![forbid(illegal_floating_point_literal_pattern)]
-
-fn main() {
- let x = 42.0;
- match x {
- 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- //~| WARNING hard error
-
- ..71.0 => {}
- //~^ ERROR floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted by the compiler
- ..=72.0 => {}
- //~^ ERROR floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted by the compiler
- 71.0.. => {}
- //~^ ERROR floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted by the compiler
- _ => {},
- };
- let y = 5.0;
- // Same for tuples
- match (x, 5) {
- (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
- //~| WARNING hard error
- _ => {},
- }
- // Or structs
- struct Foo { x: f32 };
- match (Foo { x }) {
- Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
- //~| WARNING hard error
- _ => {},
- }
-}
+++ /dev/null
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:11:9
- |
-LL | 5.0 => {},
- | ^^^
- |
-note: the lint level is defined here
- --> $DIR/issue-41255.rs:6:11
- |
-LL | #![forbid(illegal_floating_point_literal_pattern)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:13:9
- |
-LL | 5.0f32 => {},
- | ^^^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:15:10
- |
-LL | -5.0 => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:17:9
- |
-LL | 1.0 .. 33.0 => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:17:16
- |
-LL | 1.0 .. 33.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:21:9
- |
-LL | 39.0 ..= 70.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:21:18
- |
-LL | 39.0 ..= 70.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:26:11
- |
-LL | ..71.0 => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:29:12
- |
-LL | ..=72.0 => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:32:9
- |
-LL | 71.0.. => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:40:10
- |
-LL | (3.14, 1) => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:47:18
- |
-LL | Foo { x: 2.0 } => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 12 previous errors
-
+++ /dev/null
-mod foo {
- pub struct Bx(());
-}
-
-mod bar {
- use foo::Bx;
-
- fn foo() {
- Bx(());
- //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
- }
-}
-
-mod baz {
- fn foo() {
- Bx(());
- //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425]
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0423]: cannot initialize a tuple struct which contains private fields
- --> $DIR/issue-42944.rs:9:9
- |
-LL | Bx(());
- | ^^
- |
-note: constructor is not visible here due to private fields
- --> $DIR/issue-42944.rs:2:19
- |
-LL | pub struct Bx(());
- | ^^ private field
-
-error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
- --> $DIR/issue-42944.rs:16:9
- |
-LL | Bx(());
- | ^^ not found in this scope
- |
-help: consider importing this tuple struct
- |
-LL | use foo::Bx;
- |
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0423, E0425.
-For more information about an error, try `rustc --explain E0423`.
LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
| - captured outer variable
LL | id(Box::new(|| *v))
- | ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait
+ | ---^^
+ | | |
+ | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait
+ | captured by this `FnMut` closure
error: aborting due to previous error
+++ /dev/null
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-LL | let f = |v: &mut Vec<_>| {
-LL | unsafe {
- | ^^^^^^ unnecessary `unsafe` block
- |
-note: the lint level is defined here
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
- |
-LL | #[deny(unused_unsafe)]
- | ^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-...
-LL | |w: &mut Vec<u32>| { unsafe {
- | ^^^^^^ unnecessary `unsafe` block
-
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-...
-LL | |x: &mut Vec<u32>| { unsafe {
- | ^^^^^^ unnecessary `unsafe` block
-
-error: aborting due to 3 previous errors
-
+++ /dev/null
-// revisions: mir thir
-// [thir]compile-flags: -Zthir-unsafeck
-
-#[deny(unused_unsafe)]
-fn main() {
- let mut v = Vec::<i32>::with_capacity(24);
-
- unsafe {
- let f = |v: &mut Vec<_>| {
- unsafe { //~ ERROR unnecessary `unsafe`
- v.set_len(24);
- |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
- w.set_len(32);
- } };
- }
- |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
- x.set_len(40);
- } };
- };
-
- v.set_len(0);
- f(&mut v);
- }
-
- |y: &mut Vec<u32>| { unsafe {
- y.set_len(48);
- } };
-}
+++ /dev/null
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-LL | let f = |v: &mut Vec<_>| {
-LL | unsafe {
- | ^^^^^^ unnecessary `unsafe` block
- |
-note: the lint level is defined here
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
- |
-LL | #[deny(unused_unsafe)]
- | ^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-...
-LL | |w: &mut Vec<u32>| { unsafe {
- | ^^^^^^ unnecessary `unsafe` block
-
-error: unnecessary `unsafe` block
- --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
- |
-LL | unsafe {
- | ------ because it's nested under this `unsafe` block
-...
-LL | |x: &mut Vec<u32>| { unsafe {
- | ^^^^^^ unnecessary `unsafe` block
-
-error: aborting due to 3 previous errors
-
LL | fn f(&self, _: ()) {
| ------------------ takes 2 distinct arguments
LL | None::<()>.map(Self::f);
- | ^^^^^^^ expected function that takes a single 0-tuple as argument
+ | --- ^^^^^^^ expected function that takes a single 0-tuple as argument
+ | |
+ | required by a bound introduced by this call
error: aborting due to previous error
| ------------------------------------------ takes 2 arguments
...
LL | self.foo.map(Foo::new)
- | ^^^^^^^^ expected function that takes 1 argument
+ | --- ^^^^^^^^ expected function that takes 1 argument
+ | |
+ | required by a bound introduced by this call
error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
--> $DIR/issue-47706.rs:27:9
| -------- takes 1 argument
...
LL | foo(Qux::Bar);
- | ^^^^^^^^ expected function that takes 0 arguments
+ | --- ^^^^^^^^ expected function that takes 0 arguments
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/issue-47706.rs:22:8
--> $DIR/issue-51102.rs:13:17
|
LL | state: 0,
- | ^^^^^ struct `SimpleStruct` does not have this field
+ | ^^^^^
+ | |
+ | struct `SimpleStruct` does not have this field
+ | help: `SimpleStruct` has a field named `no_state_here`
error[E0025]: field `no_state_here` bound multiple times in the pattern
--> $DIR/issue-51102.rs:24:17
fn forbidden_narratives() -> Result<isize, ()> {
missing_discourses()?
- //~^ ERROR try expression alternatives have incompatible types
+ //~^ ERROR: `?` operator has incompatible types
}
fn main() {}
-error[E0308]: try expression alternatives have incompatible types
+error[E0308]: `?` operator has incompatible types
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
| ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
|
+ = note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
= note: expected enum `Result<isize, ()>`
found type `isize`
help: try removing this `?`
+++ /dev/null
-// build-pass
-
-// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
-// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
-// symbol mangling fix produces the correct result.
-
-fn dummy() {}
-
-mod llvm {
- pub(crate) struct Foo;
-}
-mod foo {
- pub(crate) struct Foo<T>(T);
-
- impl Foo<::llvm::Foo> {
- pub(crate) fn foo() {
- for _ in 0..0 {
- for _ in &[::dummy()] {
- ::dummy();
- ::dummy();
- ::dummy();
- }
- }
- }
- }
-
- pub(crate) fn foo() {
- Foo::foo();
- Foo::foo();
- }
-}
-
-pub fn foo() {
- foo::foo();
-}
-
-fn main() {}
LL | Box::new(self.out_edges(u).map(|e| e.target()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/issue-55796.rs:18:9
|
LL | Box::new(self.out_edges(u).map(|e| e.target()))
LL | Box::new(self.in_edges(u).map(|e| e.target()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/issue-55796.rs:23:9
|
LL | Box::new(self.in_edges(u).map(|e| e.target()))
|
LL | impl for T {}
| ^
+ |
+help: add a trait here
+ |
+LL | impl Trait for T {}
+ | +++++
+help: for an inherent impl, drop this `for`
+ |
+LL - impl for T {}
+LL + impl T {}
+ |
error: aborting due to previous error
+++ /dev/null
-#![allow(dead_code)]
-#![deny(unused_variables)]
-
-// This test aims to check that unused variable suggestions update bindings in all
-// match arms.
-
-fn main() {
- enum E {
- A(i32,),
- B(i32,),
- }
-
- match E::A(1) {
- E::A(x) | E::B(x) => {}
- //~^ ERROR unused variable: `x`
- }
-
- enum F {
- A(i32, i32,),
- B(i32, i32,),
- C(i32, i32,),
- }
-
- let _ = match F::A(1, 2) {
- F::A(x, y) | F::B(x, y) => { y },
- //~^ ERROR unused variable: `x`
- F::C(a, b) => { 3 }
- //~^ ERROR unused variable: `a`
- //~^^ ERROR unused variable: `b`
- };
-
- let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
- //~^ ERROR unused variable: `x`
- y
- } else {
- 3
- };
-
- while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
- //~^ ERROR unused variable: `x`
- let _ = y;
- break;
- }
-}
+++ /dev/null
-error: unused variable: `x`
- --> $DIR/issue-56685.rs:14:14
- |
-LL | E::A(x) | E::B(x) => {}
- | ^ ^
- |
-note: the lint level is defined here
- --> $DIR/issue-56685.rs:2:9
- |
-LL | #![deny(unused_variables)]
- | ^^^^^^^^^^^^^^^^
-help: if this is intentional, prefix it with an underscore
- |
-LL | E::A(_x) | E::B(_x) => {}
- | ~~ ~~
-
-error: unused variable: `x`
- --> $DIR/issue-56685.rs:25:14
- |
-LL | F::A(x, y) | F::B(x, y) => { y },
- | ^ ^
- |
-help: if this is intentional, prefix it with an underscore
- |
-LL | F::A(_x, y) | F::B(_x, y) => { y },
- | ~~ ~~
-
-error: unused variable: `a`
- --> $DIR/issue-56685.rs:27:14
- |
-LL | F::C(a, b) => { 3 }
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
- --> $DIR/issue-56685.rs:27:17
- |
-LL | F::C(a, b) => { 3 }
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `x`
- --> $DIR/issue-56685.rs:32:25
- |
-LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
- | ^ ^
- |
-help: if this is intentional, prefix it with an underscore
- |
-LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
- | ~~ ~~
-
-error: unused variable: `x`
- --> $DIR/issue-56685.rs:39:20
- |
-LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
- | ^ ^
- |
-help: if this is intentional, prefix it with an underscore
- |
-LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
- | ~~ ~~
-
-error: aborting due to 6 previous errors
-
+++ /dev/null
-// check-pass
-
-// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
-
-#![deny(unreachable_pub)]
-
-mod m {
- mod imp {
- pub fn f() {}
- }
-
- pub use self::imp::f;
-}
-
-pub use self::m::f;
-
-fn main() {}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-#![warn(clashing_extern_declarations)]
-// pretty-expanded FIXME #23616
-
-extern "C" {
- #[link_name = "malloc"]
- fn malloc1(len: i32) -> *const u8;
- #[link_name = "malloc"]
- //~^ WARN `malloc2` redeclares `malloc` with a different signature
- fn malloc2(len: i32, foo: i32) -> *const u8;
-}
-
-pub fn main() {}
+++ /dev/null
-warning: `malloc2` redeclares `malloc` with a different signature
- --> $DIR/issue-5791.rs:9:5
- |
-LL | / #[link_name = "malloc"]
-LL | | fn malloc1(len: i32) -> *const u8;
- | |______________________________________- `malloc` previously declared here
-LL | / #[link_name = "malloc"]
-LL | |
-LL | | fn malloc2(len: i32, foo: i32) -> *const u8;
- | |________________________________________________^ this signature doesn't match the previous declaration
- |
-note: the lint level is defined here
- --> $DIR/issue-5791.rs:3:9
- |
-LL | #![warn(clashing_extern_declarations)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn(i32) -> *const u8`
- found `unsafe extern "C" fn(i32, i32) -> *const u8`
-
-warning: 1 warning emitted
-
--> $DIR/issue-59494.rs:21:22
|
LL | let t8 = t8n(t7, t7p(f, g));
- | ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+ | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>`
note: required by a bound in `t8n`
error[E0277]: the trait bound `&u32: Foo` is not satisfied
- --> $DIR/issue-60218.rs:18:5
+ --> $DIR/issue-60218.rs:18:27
|
LL | trigger_error(vec![], |x: &u32| x)
- | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+ | ------------- ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `trigger_error`
--> $DIR/issue-60218.rs:13:72
--> $DIR/issue-60283.rs:17:13
|
LL | foo((), drop)
- | ^^^^
- | |
- | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
- | found signature of `fn(()) -> _`
+ | --- ^^^^
+ | | |
+ | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+ | | found signature of `fn(()) -> _`
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/issue-60283.rs:12:16
--> $DIR/issue-60283.rs:17:13
|
LL | foo((), drop)
- | ^^^^ doesn't have a size known at compile-time
+ | --- ^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
note: required by a bound in `std::mem::drop`
| ^^
| |
| borrowed value does not live long enough
- | requires that `x` is borrowed for `'static`
+ | this usage requires that `x` is borrowed for `'static`
LL |
LL | }
| - `x` dropped here while still borrowed
--> $DIR/issue-66353.rs:12:41
|
LL | _Func::< <() as _A>::AssocT >::func(());
- | ^^ the trait `_Func<_>` is not implemented for `()`
+ | ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()`
+ | |
+ | required by a bound introduced by this call
|
note: required by `_Func::func`
--> $DIR/issue-66353.rs:4:5
+++ /dev/null
-// compile-flags:-Zpolymorphize=on
-// build-pass
-
-fn test<T>() {
- std::mem::size_of::<T>();
-}
-
-pub fn foo<T>(_: T) -> &'static fn() {
- &(test::<T> as fn())
-}
-
-fn outer<T>() {
- foo(|| ());
-}
-
-fn main() {
- outer::<u8>();
-}
= note: expected `(Pin<Box<dyn Future<Output = A> + Send>>,)`
found `(Pin<Box<(dyn Future<Output = A> + Send + 'a)>>,)`
= note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/issue-75777.rs:13:5
|
LL | Box::new(move |_| fut)
+++ /dev/null
-fn server() -> impl {
-//~^ ERROR at least one trait must be specified
- ().map2(|| "")
-}
-
-trait FilterBase2 {
- fn map2<F>(self, f: F) -> Map2<F> {}
- //~^ ERROR mismatched types
- //~^^ ERROR the size for values of type `Self` cannot be known at compilation time
-}
-
-struct Map2<Segment2> {
- _func: F,
- //~^ ERROR cannot find type `F` in this scope
-}
-
-impl<F> FilterBase2 for F {}
-
-fn main() {}
+++ /dev/null
-error: at least one trait must be specified
- --> $DIR/issue-78720.rs:1:16
- |
-LL | fn server() -> impl {
- | ^^^^
-
-error[E0412]: cannot find type `F` in this scope
- --> $DIR/issue-78720.rs:13:12
- |
-LL | _func: F,
- | ^
- |
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args>: FnMut<Args> {
- | ------------------------------- similarly named trait `Fn` defined here
- |
-help: a trait with a similar name exists
- |
-LL | _func: Fn,
- | ~~
-help: you might be missing a type parameter
- |
-LL | struct Map2<Segment2, F> {
- | +++
-
-error[E0308]: mismatched types
- --> $DIR/issue-78720.rs:7:39
- |
-LL | fn map2<F>(self, f: F) -> Map2<F> {}
- | ^^ expected struct `Map2`, found `()`
- |
- = note: expected struct `Map2<F>`
- found unit type `()`
-
-error[E0277]: the size for values of type `Self` cannot be known at compilation time
- --> $DIR/issue-78720.rs:7:16
- |
-LL | fn map2<F>(self, f: F) -> Map2<F> {}
- | ^^^^ doesn't have a size known at compile-time
- |
- = help: unsized fn params are gated as an unstable feature
-help: consider further restricting `Self`
- |
-LL | fn map2<F>(self, f: F) -> Map2<F> where Self: Sized {}
- | +++++++++++++++++
-help: function arguments must have a statically known size, borrowed types always have a known size
- |
-LL | fn map2<F>(&self, f: F) -> Map2<F> {}
- | +
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0412.
-For more information about an error, try `rustc --explain E0277`.
+++ /dev/null
-mod foo {
- pub struct Pub { private: () }
-
- pub enum Enum {
- Variant { x: (), y: () },
- Other
- }
-
- fn correct() {
- Pub {};
- //~^ ERROR missing field `private` in initializer of `Pub`
- Enum::Variant { x: () };
- //~^ ERROR missing field `y` in initializer of `Enum`
- }
-}
-
-fn correct() {
- foo::Pub {};
- //~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
-}
-
-fn wrong() {
- foo::Enum::Variant { x: () };
- //~^ ERROR missing field `y` in initializer of `Enum`
- foo::Enum::Variant { };
- //~^ ERROR missing fields `x` and `y` in initializer of `Enum`
-}
-
-fn main() {}
+++ /dev/null
-error[E0063]: missing field `private` in initializer of `Pub`
- --> $DIR/issue-79593.rs:10:9
- |
-LL | Pub {};
- | ^^^ missing `private`
-
-error[E0063]: missing field `y` in initializer of `Enum`
- --> $DIR/issue-79593.rs:12:9
- |
-LL | Enum::Variant { x: () };
- | ^^^^^^^^^^^^^ missing `y`
-
-error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
- --> $DIR/issue-79593.rs:18:5
- |
-LL | foo::Pub {};
- | ^^^^^^^^
-
-error[E0063]: missing field `y` in initializer of `Enum`
- --> $DIR/issue-79593.rs:23:5
- |
-LL | foo::Enum::Variant { x: () };
- | ^^^^^^^^^^^^^^^^^^ missing `y`
-
-error[E0063]: missing fields `x` and `y` in initializer of `Enum`
- --> $DIR/issue-79593.rs:25:5
- |
-LL | foo::Enum::Variant { };
- | ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0063`.
+++ /dev/null
-fn main() {
- let elem = 6i8;
- let e2 = 230;
- //~^ ERROR literal out of range for `i8`
- //~| HELP consider using the type `u8` instead
-
- let mut vec = Vec::new();
-
- vec.push(e2);
- vec.push(elem);
-
- println!("{:?}", vec);
-}
+++ /dev/null
-error: literal out of range for `i8`
- --> $DIR/issue-79744.rs:3:14
- |
-LL | let e2 = 230;
- | ^^^
- |
- = note: `#[deny(overflowing_literals)]` on by default
- = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
-
-error: aborting due to previous error
-
--- /dev/null
+use std::fmt::Write;
+
+fn main() {
+ println!(b"foo");
+ //~^ ERROR format argument must be a string literal
+ //~| HELP consider removing the leading `b`
+ let mut s = String::new();
+ write!(s, b"foo{}", "bar");
+ //~^ ERROR format argument must be a string literal
+ //~| HELP consider removing the leading `b`
+}
--- /dev/null
+error: format argument must be a string literal
+ --> $DIR/issue-86865.rs:4:14
+ |
+LL | println!(b"foo");
+ | -^^^^^
+ | |
+ | help: consider removing the leading `b`
+
+error: format argument must be a string literal
+ --> $DIR/issue-86865.rs:8:15
+ |
+LL | write!(s, b"foo{}", "bar");
+ | -^^^^^^^
+ | |
+ | help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
--> $DIR/issue-87199.rs:18:22
|
LL | ref_arg::<[i32]>(&[5]);
- | ^^^^ doesn't have a size known at compile-time
+ | ---------------- ^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `[i32]`
note: required by a bound in `ref_arg`
help: change the type of the numeric literal from `i64` to `isize`
|
LL | A = 1isize,
- | ~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/issue-8761.rs:5:9
help: change the type of the numeric literal from `u8` to `isize`
|
LL | B = 2isize
- | ~~~~~~
+ | ~~~~~
error: aborting due to 2 previous errors
+++ /dev/null
-trait Foo {
- type T;
- fn foo(&self, t: Self::T);
-//~^ NOTE expected 0 type parameters
-}
-
-impl Foo for u32 {
- type T = ();
-
- fn foo(&self, t: impl Clone) {}
-//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-//~| NOTE found 1 type parameter
-//~| NOTE `impl Trait` introduces an implicit type parameter
-}
-
-fn main() {}
+++ /dev/null
-error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
- --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
- |
-LL | fn foo(&self, t: Self::T);
- | - expected 0 type parameters
-...
-LL | fn foo(&self, t: impl Clone) {}
- | ^^^^^^^^^^
- | |
- | found 1 type parameter
- | `impl Trait` introduces an implicit type parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0049`.
--> $DIR/kindck-impl-type-params-2.rs:13:16
|
LL | take_param(&x);
- | ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | |
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
--> $DIR/kindck-impl-type-params-2.rs:6:14
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
LL | take_param(&x);
- | ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | |
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
--> $DIR/kindck-inherited-copy-bound.rs:14:14
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
LL | take_param(&x);
- | ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+ | |
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
--> $DIR/kindck-inherited-copy-bound.rs:14:14
--- /dev/null
+#[deny(single_use_lifetimes)]
+// edition:2018
+// check-pass
+
+// Prior to the fix, the compiler complained that the 'a lifetime was only used
+// once. This was obviously wrong since the lifetime is used twice: For the s3
+// parameter and the return type. The issue was caused by the compiler
+// desugaring the async function into a generator that uses only a single
+// lifetime, which then the validator complained about becauase of the
+// single_use_lifetimes constraints.
+async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str {
+ s3
+}
+
+fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str {
+ s3
+}
+
+fn main() {}
|
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
+ |
+LL | #[derive(Eq, PartialEq)]
+ | -- lifetime `'b` is missing in item created through this procedural macro
+LL | struct Test {
+LL | a: &'b str,
+ | ^^ undeclared lifetime
+ |
+ = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13
|
LL | fn foo<'b>(&'b self) {}
| ++++
-error[E0261]: use of undeclared lifetime name `'b`
- --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
- |
-LL | #[derive(Eq, PartialEq)]
- | -- lifetime `'b` is missing in item created through this procedural macro
-LL | struct Test {
-LL | a: &'b str,
- | ^^ undeclared lifetime
- |
- = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0261`.
--- /dev/null
+// Test that enabling an unstable feature disables warnings
+
+// aux-build:stability-cfg2.rs
+
+#![feature(unstable_test_feature)]
+#![deny(non_snake_case)] // To trigger a hard error
+
+// Shouldn't generate a warning about unstable features
+extern crate stability_cfg2;
+
+pub fn BOGUS() { } //~ ERROR
+
+pub fn main() { }
--- /dev/null
+error: function `BOGUS` should have a snake case name
+ --> $DIR/enable-unstable-lib-feature.rs:11:8
+ |
+LL | pub fn BOGUS() { }
+ | ^^^^^ help: convert the identifier to snake case: `bogus`
+ |
+note: the lint level is defined here
+ --> $DIR/enable-unstable-lib-feature.rs:6:9
+ |
+LL | #![deny(non_snake_case)] // To trigger a hard error
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// check-pass
+
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
+
+#![deny(unreachable_pub)]
+
+mod m {
+ mod imp {
+ pub fn f() {}
+ }
+
+ pub use self::imp::f;
+}
+
+pub use self::m::f;
+
+fn main() {}
--- /dev/null
+fn main() {
+ let elem = 6i8;
+ let e2 = 230;
+ //~^ ERROR literal out of range for `i8`
+ //~| HELP consider using the type `u8` instead
+
+ let mut vec = Vec::new();
+
+ vec.push(e2);
+ vec.push(elem);
+
+ println!("{:?}", vec);
+}
--- /dev/null
+error: literal out of range for `i8`
+ --> $DIR/issue-79744.rs:3:14
+ |
+LL | let e2 = 230;
+ | ^^^
+ |
+ = note: `#[deny(overflowing_literals)]` on by default
+ = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
+
+error: aborting due to previous error
+
--> $DIR/lint-unnecessary-parens.rs:13:12
|
LL | return (1);
- | ^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/lint-unnecessary-parens.rs:3:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - return (1);
+LL + return 1;
+ |
error: unnecessary parentheses around `return` value
--> $DIR/lint-unnecessary-parens.rs:16:12
|
LL | return (X { y });
- | ^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - return (X { y });
+LL + return X { y };
+ |
error: unnecessary parentheses around type
--> $DIR/lint-unnecessary-parens.rs:19:46
|
LL | pub fn unused_parens_around_return_type() -> (u32) {
- | ^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - pub fn unused_parens_around_return_type() -> (u32) {
+LL + pub fn unused_parens_around_return_type() -> u32 {
+ |
error: unnecessary parentheses around block return value
--> $DIR/lint-unnecessary-parens.rs:25:9
|
LL | (5)
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (5)
+LL + 5
+ |
error: unnecessary parentheses around block return value
--> $DIR/lint-unnecessary-parens.rs:27:5
|
LL | (5)
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (5)
+LL + 5
+ |
error: unnecessary parentheses around assigned value
--> $DIR/lint-unnecessary-parens.rs:44:31
|
LL | pub const CONST_ITEM: usize = (10);
- | ^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - pub const CONST_ITEM: usize = (10);
+LL + pub const CONST_ITEM: usize = 10;
+ |
error: unnecessary parentheses around assigned value
--> $DIR/lint-unnecessary-parens.rs:45:33
|
LL | pub static STATIC_ITEM: usize = (10);
- | ^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - pub static STATIC_ITEM: usize = (10);
+LL + pub static STATIC_ITEM: usize = 10;
+ |
error: unnecessary parentheses around function argument
--> $DIR/lint-unnecessary-parens.rs:49:9
|
LL | bar((true));
- | ^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - bar((true));
+LL + bar(true);
+ |
error: unnecessary parentheses around `if` condition
--> $DIR/lint-unnecessary-parens.rs:51:8
|
LL | if (true) {}
- | ^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if (true) {}
+LL + if true {}
+ |
error: unnecessary parentheses around `while` condition
--> $DIR/lint-unnecessary-parens.rs:52:11
|
LL | while (true) {}
- | ^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while (true) {}
+LL + while true {}
+ |
error: unnecessary parentheses around `match` scrutinee expression
--> $DIR/lint-unnecessary-parens.rs:53:11
|
LL | match (true) {
- | ^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - match (true) {
+LL + match true {
+ |
error: unnecessary parentheses around `let` scrutinee expression
--> $DIR/lint-unnecessary-parens.rs:56:16
|
LL | if let 1 = (1) {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let 1 = (1) {}
+LL + if let 1 = 1 {}
+ |
error: unnecessary parentheses around `let` scrutinee expression
--> $DIR/lint-unnecessary-parens.rs:57:19
|
LL | while let 1 = (2) {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let 1 = (2) {}
+LL + while let 1 = 2 {}
+ |
error: unnecessary parentheses around method argument
--> $DIR/lint-unnecessary-parens.rs:73:24
|
LL | X { y: false }.foo((true));
- | ^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - X { y: false }.foo((true));
+LL + X { y: false }.foo(true);
+ |
error: unnecessary parentheses around assigned value
--> $DIR/lint-unnecessary-parens.rs:75:18
|
LL | let mut _a = (0);
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let mut _a = (0);
+LL + let mut _a = 0;
+ |
error: unnecessary parentheses around assigned value
--> $DIR/lint-unnecessary-parens.rs:76:10
|
LL | _a = (0);
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - _a = (0);
+LL + _a = 0;
+ |
error: unnecessary parentheses around assigned value
--> $DIR/lint-unnecessary-parens.rs:77:11
|
LL | _a += (1);
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - _a += (1);
+LL + _a += 1;
+ |
error: aborting due to 17 previous errors
--> $DIR/suggestions.rs:48:31
|
LL | let mut registry_no = (format!("NX-{}", 74205));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/suggestions.rs:4:21
|
LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - let mut registry_no = (format!("NX-{}", 74205));
+LL + let mut registry_no = format!("NX-{}", 74205);
+ |
warning: variable does not need to be mutable
--> $DIR/suggestions.rs:48:13
--> $DIR/issue-54538-unused-parens-lint.rs:16:9
|
LL | let (a) = 0;
- | ^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/issue-54538-unused-parens-lint.rs:13:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - let (a) = 0;
+LL + let a = 0;
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:17:9
|
LL | for (a) in 0..1 {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - for (a) in 0..1 {}
+LL + for a in 0..1 {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:18:12
|
LL | if let (a) = 0 {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let (a) = 0 {}
+LL + if let a = 0 {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:19:15
|
LL | while let (a) = 0 {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let (a) = 0 {}
+LL + while let a = 0 {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:20:12
|
LL | fn foo((a): u8) {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - fn foo((a): u8) {}
+LL + fn foo(a: u8) {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:21:14
|
LL | let _ = |(a): u8| 0;
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _ = |(a): u8| 0;
+LL + let _ = |a: u8| 0;
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:49:12
|
LL | if let (0 | 1) = 0 {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let (0 | 1) = 0 {}
+LL + if let 0 | 1 = 0 {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:50:13
|
LL | if let ((0 | 1),) = (0,) {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let ((0 | 1),) = (0,) {}
+LL + if let (0 | 1,) = (0,) {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:51:13
|
LL | if let [(0 | 1)] = [0] {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let [(0 | 1)] = [0] {}
+LL + if let [0 | 1] = [0] {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:52:16
|
LL | if let 0 | (1 | 2) = 0 {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let 0 | (1 | 2) = 0 {}
+LL + if let 0 | 1 | 2 = 0 {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:54:15
|
LL | if let TS((0 | 1)) = TS(0) {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let TS((0 | 1)) = TS(0) {}
+LL + if let TS(0 | 1) = TS(0) {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:56:20
|
LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:66:9
|
LL | (_) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (_) => {}
+LL + _ => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:67:9
|
LL | (y) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (y) => {}
+LL + y => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:68:9
|
LL | (ref r) => {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (ref r) => {}
+LL + ref r => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:69:9
|
LL | (e @ 1...2) => {}
- | ^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ 1...2) => {}
+LL + e @ 1...2 => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:75:9
|
LL | (e @ &(1...2)) => {}
- | ^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ &(1...2)) => {}
+LL + e @ &(1...2) => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:76:10
|
LL | &(_) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - &(_) => {}
+LL + &_ => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:87:9
|
LL | (_) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (_) => {}
+LL + _ => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:88:9
|
LL | (y) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (y) => {}
+LL + y => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:89:9
|
LL | (ref r) => {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (ref r) => {}
+LL + ref r => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:90:9
|
LL | (e @ 1..=2) => {}
- | ^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ 1..=2) => {}
+LL + e @ 1..=2 => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:96:9
|
LL | (e @ &(1..=2)) => {}
- | ^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ &(1..=2)) => {}
+LL + e @ &(1..=2) => {}
+ |
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:97:10
|
LL | &(_) => {}
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - &(_) => {}
+LL + &_ => {}
+ |
error: aborting due to 24 previous errors
--> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29
|
LL | while let Some(_) = ({yield}) {}
- | ^^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24
|
LL | #![deny(unused_braces, unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - while let Some(_) = ({yield}) {}
+LL + while let Some(_) = {yield} {}
+ |
error: unnecessary parentheses around `let` scrutinee expression
--> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29
|
LL | while let Some(_) = ((yield)) {}
- | ^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let Some(_) = ((yield)) {}
+LL + while let Some(_) = (yield) {}
+ |
error: unnecessary braces around block return value
--> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10
|
LL | {{yield}};
- | ^^^^^^^ help: remove these braces
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9
|
LL | #![deny(unused_braces, unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - {{yield}};
+LL + {yield};
+ |
error: unnecessary parentheses around block return value
--> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10
|
LL | {( yield )};
- | ^^^^^^^^^ help: remove these parentheses
+ | ^^ ^^
+ |
+help: remove these parentheses
+ |
+LL - {( yield )};
+LL + {yield};
+ |
error: unnecessary parentheses around block return value
--> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30
|
LL | while let Some(_) = {(yield)} {}
- | ^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let Some(_) = {(yield)} {}
+LL + while let Some(_) = {yield} {}
+ |
error: unnecessary braces around block return value
--> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30
|
LL | while let Some(_) = {{yield}} {}
- | ^^^^^^^ help: remove these braces
+ | ^ ^
+ |
+help: remove these braces
+ |
+LL - while let Some(_) = {{yield}} {}
+LL + while let Some(_) = {yield} {}
+ |
error: aborting due to 6 previous errors
--> $DIR/unused_braces.rs:10:13
|
LL | let _ = (7);
- | ^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/unused_braces.rs:4:24
|
LL | #![warn(unused_braces, unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - let _ = (7);
+LL + let _ = 7;
+ |
warning: unnecessary braces around `if` condition
--> $DIR/unused_braces.rs:26:8
|
LL | if { true } {
- | ^^^^^^^^ help: remove these braces
+ | ^^ ^^
|
note: the lint level is defined here
--> $DIR/unused_braces.rs:4:9
|
LL | #![warn(unused_braces, unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - if { true } {
+LL + if true {
+ |
warning: unnecessary braces around `while` condition
--> $DIR/unused_braces.rs:30:11
|
LL | while { false } {
- | ^^^^^^^^^ help: remove these braces
+ | ^^ ^^
+ |
+help: remove these braces
+ |
+LL - while { false } {
+LL + while false {
+ |
warning: unnecessary braces around const expression
--> $DIR/unused_braces.rs:34:17
|
LL | let _: [u8; { 3 }];
- | ^^^^^ help: remove these braces
+ | ^^ ^^
+ |
+help: remove these braces
+ |
+LL - let _: [u8; { 3 }];
+LL + let _: [u8; 3];
+ |
warning: unnecessary braces around function argument
--> $DIR/unused_braces.rs:37:13
|
LL | consume({ 7 });
- | ^^^^^ help: remove these braces
+ | ^^ ^^
+ |
+help: remove these braces
+ |
+LL - consume({ 7 });
+LL + consume(7);
+ |
warning: 5 warnings emitted
--> $DIR/unused_braces_borrow.rs:24:13
|
LL | consume({ a.b });
- | ^^^^^^^ help: remove these braces
+ | ^^ ^^
|
note: the lint level is defined here
--> $DIR/unused_braces_borrow.rs:4:9
|
LL | #![warn(unused_braces)]
| ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - consume({ a.b });
+LL + consume(a.b);
+ |
warning: 1 warning emitted
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));
--> $DIR/unused_parens_json_suggestion.rs:16:14
|
LL | let _a = (1 / (2 + 3));
- | ^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/unused_parens_json_suggestion.rs:10:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - let _a = (1 / (2 + 3));
+LL + let _a = 1 / (2 + 3);
+ |
"}
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {
--> $DIR/unused_parens_remove_json_suggestion.rs:17:8
|
LL | if (_b) {
- | ^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/unused_parens_remove_json_suggestion.rs:10:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - if (_b) {
+LL + if _b {
+ |
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {
--> $DIR/unused_parens_remove_json_suggestion.rs:28:7
|
LL | if(c) {
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if(c) {
+LL + if c {
+ |
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":" if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){
--> $DIR/unused_parens_remove_json_suggestion.rs:32:8
|
LL | if (c){
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if (c){
+LL + if c {
+ |
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
--> $DIR/unused_parens_remove_json_suggestion.rs:36:11
|
LL | while (false && true){
- | ^^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while (false && true){
+LL + while false && true {
+ |
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {
--> $DIR/unused_parens_remove_json_suggestion.rs:37:12
|
LL | if (c) {
- | ^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if (c) {
+LL + if c {
+ |
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {
--> $DIR/unused_parens_remove_json_suggestion.rs:43:10
|
LL | while(true && false) {
- | ^^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while(true && false) {
+LL + while true && false {
+ |
"}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
--> $DIR/unused_parens_remove_json_suggestion.rs:44:18
|
LL | for _ in (0 .. 3){
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - for _ in (0 .. 3){
+LL + for _ in 0 .. 3 {
+ |
"}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
--> $DIR/unused_parens_remove_json_suggestion.rs:49:14
|
LL | for _ in (0 .. 3) {
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - for _ in (0 .. 3) {
+LL + for _ in 0 .. 3 {
+ |
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {
--> $DIR/unused_parens_remove_json_suggestion.rs:50:15
|
LL | while (true && false) {
- | ^^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while (true && false) {
+LL + while true && false {
+ |
"}
{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors
--- /dev/null
+// build-fail
+// ignore-emscripten no llvm_asm! support
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+fn main() {
+ unsafe {
+ llvm_asm!("" :: "r"(""));
+ //~^ ERROR: invalid value for constraint in inline assembly
+ }
+}
--- /dev/null
+error[E0669]: invalid value for constraint in inline assembly
+ --> $DIR/issue-37433.rs:9:29
+ |
+LL | llvm_asm!("" :: "r"(""));
+ | ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
// check-pass
+#![feature(label_break_value)]
-
-// Issue #21633: reject duplicate loop labels in function bodies.
+// Issue #21633: reject duplicate loop labels and block labels in function bodies.
//
// This is testing the generalization (to the whole function body)
// discussed here:
{ 'lt: loop { break; } }
{ 'lt: while let Some(_) = None::<i32> { break; } }
//~^ WARN label name `'lt` shadows a label name that is already in scope
+ { 'bl: {} }
+ { 'bl: {} } //~ WARN label name `'bl` shadows a label name that is already in scope
}
LL | { 'lt: while let Some(_) = None::<i32> { break; } }
| ^^^ label `'lt` already in scope
-warning: 8 warnings emitted
+warning: label name `'bl` shadows a label name that is already in scope
+ --> $DIR/loops-reject-duplicate-labels-2.rs:30:7
+ |
+LL | { 'bl: {} }
+ | --- first declared here
+LL | { 'bl: {} }
+ | ^^^ label `'bl` already in scope
+
+warning: 9 warnings emitted
// check-pass
+#![feature(label_break_value)]
-
-// Issue #21633: reject duplicate loop labels in function bodies.
-// This is testing the exact cases that are in the issue description.
+// Issue #21633: reject duplicate loop labels and block labels in function bodies.
#[allow(unused_labels)]
fn foo() {
'lt: loop { break; }
'lt: while let Some(_) = None::<i32> { break; }
//~^ WARN label name `'lt` shadows a label name that is already in scope
+ 'bl: {}
+ 'bl: {} //~ WARN label name `'bl` shadows a label name that is already in scope
}
// Note however that it is okay for the same label to be reused in
impl S {
fn m1(&self) { 'okay: loop { break 'okay; } }
fn m2(&self) { 'okay: loop { break 'okay; } }
+ fn m3(&self) { 'okay: { break 'okay; } }
+ fn m4(&self) { 'okay: { break 'okay; } }
}
let s = S;
s.m1();
s.m2();
+ s.m3();
+ s.m4();
foo();
}
warning: label name `'fl` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:10:5
+ --> $DIR/loops-reject-duplicate-labels.rs:9:5
|
LL | 'fl: for _ in 0..10 { break; }
| --- first declared here
| ^^^ label `'fl` already in scope
warning: label name `'lf` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:13:5
+ --> $DIR/loops-reject-duplicate-labels.rs:12:5
|
LL | 'lf: loop { break; }
| --- first declared here
| ^^^ label `'lf` already in scope
warning: label name `'wl` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:15:5
+ --> $DIR/loops-reject-duplicate-labels.rs:14:5
|
LL | 'wl: while 2 > 1 { break; }
| --- first declared here
| ^^^ label `'wl` already in scope
warning: label name `'lw` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:17:5
+ --> $DIR/loops-reject-duplicate-labels.rs:16:5
|
LL | 'lw: loop { break; }
| --- first declared here
| ^^^ label `'lw` already in scope
warning: label name `'fw` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:19:5
+ --> $DIR/loops-reject-duplicate-labels.rs:18:5
|
LL | 'fw: for _ in 0..10 { break; }
| --- first declared here
| ^^^ label `'fw` already in scope
warning: label name `'wf` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:21:5
+ --> $DIR/loops-reject-duplicate-labels.rs:20:5
|
LL | 'wf: while 2 > 1 { break; }
| --- first declared here
| ^^^ label `'wf` already in scope
warning: label name `'tl` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:23:5
+ --> $DIR/loops-reject-duplicate-labels.rs:22:5
|
LL | 'tl: while let Some(_) = None::<i32> { break; }
| --- first declared here
| ^^^ label `'tl` already in scope
warning: label name `'lt` shadows a label name that is already in scope
- --> $DIR/loops-reject-duplicate-labels.rs:25:5
+ --> $DIR/loops-reject-duplicate-labels.rs:24:5
|
LL | 'lt: loop { break; }
| --- first declared here
LL | 'lt: while let Some(_) = None::<i32> { break; }
| ^^^ label `'lt` already in scope
-warning: 8 warnings emitted
+warning: label name `'bl` shadows a label name that is already in scope
+ --> $DIR/loops-reject-duplicate-labels.rs:27:5
+ |
+LL | 'bl: {}
+ | --- first declared here
+LL | 'bl: {}
+ | ^^^ label `'bl` already in scope
+
+warning: 9 warnings emitted
// check-pass
-
+#![feature(label_break_value)]
#![allow(dead_code, unused_variables)]
-// Issue #21633: reject duplicate loop labels in function bodies.
+// Issue #21633: reject duplicate loop labels and block labels in function bodies.
//
-// Test rejection of lifetimes in *expressions* that shadow loop labels.
+// Test rejection of lifetimes in *expressions* that shadow labels.
fn foo() {
// Reusing lifetime `'a` in function item is okay.
assert_eq!((*b)(&z), z);
break 'a;
}
-}
+ 'b: {
+ let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
+ //~^ WARN lifetime name `'b` shadows a label name that is already in scope
+ break 'b;
+ }
+}
pub fn main() {
foo();
LL | let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
| ^^ label `'a` already in scope
-warning: 1 warning emitted
+warning: lifetime name `'b` shadows a label name that is already in scope
+ --> $DIR/loops-reject-lifetime-shadowing-label.rs:28:55
+ |
+LL | 'b: {
+ | -- first declared here
+LL | let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
+ | ^^ label `'b` already in scope
+
+warning: 2 warnings emitted
--- /dev/null
+#[macro_export]
+macro_rules! define_macro {
+ ($i:ident) => {
+ macro_rules! $i { () => {} }
+ }
+}
--- /dev/null
+// check-pass
+//
+// Ensures that we properly lint
+// a removed 'expression' resulting from a macro
+// in trailing expression position
+
+macro_rules! expand_it {
+ () => {
+ #[cfg(FALSE)] 25; //~ WARN trailing semicolon in macro
+ //~| WARN this was previously
+ }
+}
+
+fn main() {
+ expand_it!()
+}
--- /dev/null
+warning: trailing semicolon in macro used in expression position
+ --> $DIR/lint-trailing-macro-call.rs:9:25
+ |
+LL | #[cfg(FALSE)] 25;
+ | ^
+...
+LL | expand_it!()
+ | ------------ in this macro invocation
+ |
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
+ = 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 #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: macro invocations at the end of a block are treated as expressions
+ = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it`
+ = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
--- /dev/null
+// aux-build:define-macro.rs
+
+macro_rules! bar { () => {} }
+define_macro!(bar);
+bar!(); //~ ERROR `bar` is ambiguous
+
+macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
+m!();
+
+fn main() {}
--- /dev/null
+error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+ --> $DIR/out-of-order-shadowing.rs:5:1
+ |
+LL | bar!();
+ | ^^^ ambiguous name
+ |
+note: `bar` could refer to the macro defined here
+ --> $DIR/out-of-order-shadowing.rs:4:1
+ |
+LL | define_macro!(bar);
+ | ^^^^^^^^^^^^^^^^^^^
+note: `bar` could also refer to the macro defined here
+ --> $DIR/out-of-order-shadowing.rs:3:1
+ |
+LL | macro_rules! bar { () => {} }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `define_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
--- /dev/null
+// run-pass
+
+#![allow(non_shorthand_field_patterns)]
+
+#[derive(Copy, Clone)]
+struct Pair { x: isize, y: isize }
+
+pub fn main() {
+ let a: isize =
+ match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } };
+ assert_eq!(a, 2);
+
+ let b: isize =
+ match (Pair {x: 10, y: 20}) {
+ x if x.x < 5 && x.y < 5 => { 1 }
+ Pair {x: x, y: y} if x == 10 && y == 20 => { 2 }
+ Pair {x: _x, y: _y} => { 3 }
+ };
+ assert_eq!(b, 2);
+}
--- /dev/null
+// run-pass
+#![allow(unused_variables)]
+pub fn main() {
+ let x = (0, 2);
+
+ match x {
+ (0, ref y) => {}
+ (y, 0) => {}
+ _ => (),
+ }
+}
--- /dev/null
+// Matching against float literals should result in a linter error
+
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+#![allow(unused)]
+#![forbid(illegal_floating_point_literal_pattern)]
+
+fn main() {
+ let x = 42.0;
+ match x {
+ 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ //~| ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+ //~| ERROR floating-point types cannot be used in patterns
+ //~| WARNING hard error
+ //~| WARNING hard error
+
+ ..71.0 => {}
+ //~^ ERROR floating-point types cannot be used in patterns
+ //~| WARNING this was previously accepted by the compiler
+ ..=72.0 => {}
+ //~^ ERROR floating-point types cannot be used in patterns
+ //~| WARNING this was previously accepted by the compiler
+ 71.0.. => {}
+ //~^ ERROR floating-point types cannot be used in patterns
+ //~| WARNING this was previously accepted by the compiler
+ _ => {},
+ };
+ let y = 5.0;
+ // Same for tuples
+ match (x, 5) {
+ (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
+ //~| WARNING hard error
+ _ => {},
+ }
+ // Or structs
+ struct Foo { x: f32 };
+ match (Foo { x }) {
+ Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
+ //~| WARNING hard error
+ _ => {},
+ }
+}
--- /dev/null
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:11:9
+ |
+LL | 5.0 => {},
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-41255.rs:6:11
+ |
+LL | #![forbid(illegal_floating_point_literal_pattern)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:13:9
+ |
+LL | 5.0f32 => {},
+ | ^^^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:15:10
+ |
+LL | -5.0 => {},
+ | ^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:17:9
+ |
+LL | 1.0 .. 33.0 => {},
+ | ^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:17:16
+ |
+LL | 1.0 .. 33.0 => {},
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:21:9
+ |
+LL | 39.0 ..= 70.0 => {},
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:21:18
+ |
+LL | 39.0 ..= 70.0 => {},
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:26:11
+ |
+LL | ..71.0 => {}
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:29:12
+ |
+LL | ..=72.0 => {}
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:32:9
+ |
+LL | 71.0.. => {}
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:40:10
+ |
+LL | (3.14, 1) => {},
+ | ^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-41255.rs:47:18
+ |
+LL | Foo { x: 2.0 } => {},
+ | ^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 12 previous errors
+
--- /dev/null
+#![allow(dead_code)]
+#![deny(unused_variables)]
+
+// This test aims to check that unused variable suggestions update bindings in all
+// match arms.
+
+fn main() {
+ enum E {
+ A(i32,),
+ B(i32,),
+ }
+
+ match E::A(1) {
+ E::A(x) | E::B(x) => {}
+ //~^ ERROR unused variable: `x`
+ }
+
+ enum F {
+ A(i32, i32,),
+ B(i32, i32,),
+ C(i32, i32,),
+ }
+
+ let _ = match F::A(1, 2) {
+ F::A(x, y) | F::B(x, y) => { y },
+ //~^ ERROR unused variable: `x`
+ F::C(a, b) => { 3 }
+ //~^ ERROR unused variable: `a`
+ //~^^ ERROR unused variable: `b`
+ };
+
+ let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+ //~^ ERROR unused variable: `x`
+ y
+ } else {
+ 3
+ };
+
+ while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+ //~^ ERROR unused variable: `x`
+ let _ = y;
+ break;
+ }
+}
--- /dev/null
+error: unused variable: `x`
+ --> $DIR/issue-56685.rs:14:14
+ |
+LL | E::A(x) | E::B(x) => {}
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-56685.rs:2:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+help: if this is intentional, prefix it with an underscore
+ |
+LL | E::A(_x) | E::B(_x) => {}
+ | ~~ ~~
+
+error: unused variable: `x`
+ --> $DIR/issue-56685.rs:25:14
+ |
+LL | F::A(x, y) | F::B(x, y) => { y },
+ | ^ ^
+ |
+help: if this is intentional, prefix it with an underscore
+ |
+LL | F::A(_x, y) | F::B(_x, y) => { y },
+ | ~~ ~~
+
+error: unused variable: `a`
+ --> $DIR/issue-56685.rs:27:14
+ |
+LL | F::C(a, b) => { 3 }
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/issue-56685.rs:27:17
+ |
+LL | F::C(a, b) => { 3 }
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `x`
+ --> $DIR/issue-56685.rs:32:25
+ |
+LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+ | ^ ^
+ |
+help: if this is intentional, prefix it with an underscore
+ |
+LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+ | ~~ ~~
+
+error: unused variable: `x`
+ --> $DIR/issue-56685.rs:39:20
+ |
+LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+ | ^ ^
+ |
+help: if this is intentional, prefix it with an underscore
+ |
+LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+ | ~~ ~~
+
+error: aborting due to 6 previous errors
+
help: change the type of the numeric literal from `usize` to `u32`
|
LL | let x: u32 = 22_u32;
- | ~~~~~~
+ | ~~~
error: aborting due to previous error
help: change the type of the numeric literal from `usize` to `u32`
|
LL | let x: u32 = 22_u32;
- | ~~~~~~
+ | ~~~
error: aborting due to previous error
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | let y: usize = x.foo().try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 2 previous errors
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-struct S<T> {
- contents: T,
-}
-
-impl<T> S<T> {
- fn new<U>(x: T, _: U) -> S<T> {
- S {
- contents: x,
- }
- }
-}
-
-trait Trait<T> {
- fn new<U>(x: T, y: U) -> Self;
-}
-
-struct S2 {
- contents: isize,
-}
-
-impl Trait<isize> for S2 {
- fn new<U>(x: isize, _: U) -> S2 {
- S2 {
- contents: x,
- }
- }
-}
-
-pub fn main() {
- let _ = S::<isize>::new::<f64>(1, 1.0);
- let _: S2 = Trait::<isize>::new::<f64>(1, 1.0);
-}
--- /dev/null
+// Regression test for #88972. Used to cause a query cycle:
+// optimized mir -> remove zsts -> layout of a generator -> optimized mir.
+//
+// edition:2018
+// compile-flags: --crate-type=lib
+// build-pass
+
+pub async fn listen() -> Result<(), std::io::Error> {
+ let f = do_async();
+ std::mem::forget(f);
+ Ok(())
+}
+
+pub async fn do_async() {
+ listen().await.unwrap()
+}
| ------------ found signature of `fn(u64) -> _`
...
LL | foo(f);
- | ^ expected signature of `fn(usize) -> _`
+ | --- ^ expected signature of `fn(usize) -> _`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/E0631.rs:3:11
| ------------ found signature of `fn(u64) -> _`
...
LL | bar(f);
- | ^ expected signature of `fn(usize) -> _`
+ | --- ^ expected signature of `fn(usize) -> _`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `bar`
--> $DIR/E0631.rs:4:11
--> $DIR/closure-arg-count.rs:24:57
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
- | ^^^ expected function that takes a single 2-tuple as argument
+ | --- ^^^ expected function that takes a single 2-tuple as argument
+ | |
+ | required by a bound introduced by this call
...
LL | fn foo() {}
| -------- takes 0 arguments
LL | let bar = |i, x, y| i;
| --------- takes 3 distinct arguments
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
- | ^^^ expected closure that takes a single 2-tuple as argument
+ | --- ^^^ expected closure that takes a single 2-tuple as argument
+ | |
+ | required by a bound introduced by this call
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:29:57
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
- | ^^^ expected function that takes a single 2-tuple as argument
+ | --- ^^^ expected function that takes a single 2-tuple as argument
+ | |
+ | required by a bound introduced by this call
...
LL | fn qux(x: usize, y: usize) {}
| -------------------------- takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:32:45
|
LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
- | ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+ | --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+ | |
+ | required by a bound introduced by this call
error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
--> $DIR/closure-arg-count.rs:35:10
|
LL | call(Foo);
- | ^^^ expected function that takes 0 arguments
+ | ---- ^^^ expected function that takes 0 arguments
+ | |
+ | required by a bound introduced by this call
...
LL | struct Foo(u8);
| --------------- takes 1 argument
| --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _`
...
LL | apply(&3, takes_mut);
- | ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+ | ----- ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `apply`
--> $DIR/fn-variance-1.rs:5:37
| ----------------------- found signature of `for<'r> fn(&'r isize) -> _`
...
LL | apply(&mut 3, takes_imm);
- | ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+ | ----- ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `apply`
--> $DIR/fn-variance-1.rs:5:37
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | ($arr.len() * size_of($arr[0])).try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | + +++++++++++++++++++++
error[E0605]: non-primitive cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:22:19
help: change the type of the numeric literal from `u8` to `u16`
|
LL | foo(1u16);
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-literal-cast.rs:8:10
help: change the type of the numeric literal from `f32` to `f64`
|
LL | foo1(2f64);
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-literal-cast.rs:10:10
help: change the type of the numeric literal from `i16` to `i32`
|
LL | foo2(3i32);
- | ~~~~
+ | ~~~
error: aborting due to 3 previous errors
let z = call_it(3, f);
//~^ ERROR type mismatch
//~| NOTE expected signature of `fn(isize, isize) -> _`
+ //~| NOTE required by a bound introduced by this call
println!("{}", z);
}
| ----------------------------- found signature of `fn(usize, isize) -> _`
LL |
LL | let z = call_it(3, f);
- | ^ expected signature of `fn(isize, isize) -> _`
+ | ------- ^ expected signature of `fn(isize, isize) -> _`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-vtable-mismatch.rs:7:14
// run-pass
#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
/*!
* On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment,
* but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment
// run-pass
#![allow(unused_mut)]
+#![allow(dead_code)]
#![feature(box_syntax)]
#[derive(Clone)]
// run-pass
#![allow(unused_mut)]
+#![allow(dead_code)]
#![feature(box_syntax)]
#[derive(Clone)]
LL | let i = box 3;
| - captured outer variable
LL | let _f = to_fn(|| test(i));
- | ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
+ | --------^-
+ | | |
+ | | move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
+ | captured by this `Fn` closure
error: aborting due to previous error
--> $DIR/mutexguard-sync.rs:11:15
|
LL | test_sync(guard);
- | ^^^^^ `Cell<i32>` cannot be shared between threads safely
+ | --------- ^^^^^ `Cell<i32>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: required because of the requirements on the impl of `Sync` for `MutexGuard<'_, Cell<i32>>`
--> $DIR/namespace-mix.rs:33:11
|
LL | check(m1::S{});
- | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:35:11
|
LL | check(m2::S{});
- | ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:36:11
|
LL | check(m2::S);
- | ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:39:11
|
LL | check(xm1::S{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:41:11
|
LL | check(xm2::S{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:42:11
|
LL | check(xm2::S);
- | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:55:11
|
LL | check(m3::TS{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:56:11
|
LL | check(m3::TS);
- | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:57:11
|
LL | check(m4::TS{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:58:11
|
LL | check(m4::TS);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:61:11
|
LL | check(xm3::TS{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:62:11
|
LL | check(xm3::TS);
- | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:63:11
|
LL | check(xm4::TS{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:64:11
|
LL | check(xm4::TS);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:77:11
|
LL | check(m5::US{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:78:11
|
LL | check(m5::US);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:79:11
|
LL | check(m6::US{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:80:11
|
LL | check(m6::US);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:83:11
|
LL | check(xm5::US{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:84:11
|
LL | check(xm5::US);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:85:11
|
LL | check(xm6::US{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:86:11
|
LL | check(xm6::US);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:99:11
|
LL | check(m7::V{});
- | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:101:11
|
LL | check(m8::V{});
- | ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:102:11
|
LL | check(m8::V);
- | ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:105:11
|
LL | check(xm7::V{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:107:11
|
LL | check(xm8::V{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:108:11
|
LL | check(xm8::V);
- | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:121:11
|
LL | check(m9::TV{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:122:11
|
LL | check(m9::TV);
- | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:123:11
|
LL | check(mA::TV{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:124:11
|
LL | check(mA::TV);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:127:11
|
LL | check(xm9::TV{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:128:11
|
LL | check(xm9::TV);
- | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:129:11
|
LL | check(xmA::TV{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:130:11
|
LL | check(xmA::TV);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:143:11
|
LL | check(mB::UV{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:144:11
|
LL | check(mB::UV);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:145:11
|
LL | check(mC::UV{});
- | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:146:11
|
LL | check(mC::UV);
- | ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:149:11
|
LL | check(xmB::UV{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:150:11
|
LL | check(xmB::UV);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:151:11
|
LL | check(xmC::UV{});
- | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--> $DIR/namespace-mix.rs:152:11
|
LL | check(xmC::UV);
- | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `check`
--> $DIR/namespace-mix.rs:21:13
--- /dev/null
+// run-pass
+
+#![allow(dead_code)]
+// Issue #521
+
+// pretty-expanded FIXME #23616
+
+fn f() {
+ let _x = match true {
+ true => { 10 }
+ false => { return }
+ };
+}
+
+pub fn main() { }
| ^^
| |
| borrowed value does not live long enough
- | requires that `a` is borrowed for `'static`
+ | this usage requires that `a` is borrowed for `'static`
LL | loop { }
LL | }
| - `a` dropped here while still borrowed
LL | let x = (vec![22], vec![44]);
| - captured outer variable
LL | expect_fn(|| drop(x.0));
- | ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
+ | --------^^^-
+ | | |
+ | | move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
+ | captured by this `Fn` closure
error: aborting due to previous error
|
LL | impl Foo<'_> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/issue-55394.rs:9:9
|
LL | Foo { bar }
|
LL | impl<'a> FromBox<'a> for C<'a> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/type-alias-free-regions.rs:17:9
|
LL | C { f: b }
|
LL | impl<'a> FromTuple<'a> for C<'a> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/type-alias-free-regions.rs:27:9
|
LL | C { f: Box::new(b.0) }
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'static`
+ | this usage requires that `c` is borrowed for `'static`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | };
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'static`
+ | this usage requires that `c` is borrowed for `'static`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | };
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'static`
+ | this usage requires that `c` is borrowed for `'static`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | };
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'static`
+ | this usage requires that `c` is borrowed for `'static`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | }
| - `c` dropped here while still borrowed
| ^^
| |
| borrowed value does not live long enough
- | requires that `c` is borrowed for `'a`
+ | this usage requires that `c` is borrowed for `'a`
LL | };
| - `c` dropped here while still borrowed
| |
| lifetime `'a` defined here
LL | Foo { x, y };
- | ^ requires that `'a` must outlive `'b`
+ | ^ this usage requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
--> $DIR/no_send-rc.rs:7:9
|
LL | bar(x);
- | ^ `Rc<{integer}>` cannot be sent between threads safely
+ | --- ^ `Rc<{integer}>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `Rc<{integer}>`
note: required by a bound in `bar`
--> $DIR/no_send-struct.rs:15:9
|
LL | bar(x);
- | ^ `Foo` cannot be sent between threads safely
+ | --- ^ `Foo` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `Foo`
note: required by a bound in `bar`
--> $DIR/no_share-struct.rs:12:9
|
LL | bar(x);
- | ^ `Foo` cannot be shared between threads safely
+ | --- ^ `Foo` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `Foo`
note: required by a bound in `bar`
help: change the type of the numeric literal from `i8` to `i32`
|
LL | const C: i32 = 1i32;
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/const-scope.rs:2:15
help: change the type of the numeric literal from `i8` to `i32`
|
LL | let c: i32 = 1i32;
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/const-scope.rs:6:17
help: change the type of the numeric literal from `i8` to `i32`
|
LL | let c: i32 = 1i32;
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/const-scope.rs:11:17
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | let d: i8 = c.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 6 previous errors
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | test(array.len().try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to previous error
help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
|
LL | let x: u16 = foo().try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-2.rs:7:18
|
LL | let y: i64 = x + x;
- | --- ^^^^^
- | | |
- | | expected `i64`, found `u16`
- | | help: you can convert a `u16` to an `i64`: `(x + x).into()`
+ | --- ^^^^^ expected `i64`, found `u16`
+ | |
| expected due to this
+ |
+help: you can convert a `u16` to an `i64`
+ |
+LL | let y: i64 = (x + x).into();
+ | + ++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-2.rs:9:18
|
LL | let z: i32 = x + x;
- | --- ^^^^^
- | | |
- | | expected `i32`, found `u16`
- | | help: you can convert a `u16` to an `i32`: `(x + x).into()`
+ | --- ^^^^^ expected `i32`, found `u16`
+ | |
| expected due to this
+ |
+help: you can convert a `u16` to an `i32`
+ |
+LL | let z: i32 = (x + x).into();
+ | + ++++++++
error: aborting due to 3 previous errors
help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
|
LL | u16::from(x_u8) > x_u16;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:25:16
help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
|
LL | u32::from(x_u8) > x_u32;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:27:16
help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
|
LL | u64::from(x_u8) > x_u64;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:29:16
help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
|
LL | u128::from(x_u8) > x_u128;
- | ~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:31:16
help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
|
LL | usize::from(x_u8) > x_usize;
- | ~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:34:17
|
LL | x_u16 > x_u8;
- | ^^^^
- | |
- | expected `u16`, found `u8`
- | help: you can convert a `u8` to a `u16`: `x_u8.into()`
+ | ^^^^ expected `u16`, found `u8`
+ |
+help: you can convert a `u8` to a `u16`
+ |
+LL | x_u16 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:36:17
help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
|
LL | u32::from(x_u16) > x_u32;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:38:17
help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
|
LL | u64::from(x_u16) > x_u64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:40:17
help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
|
LL | u128::from(x_u16) > x_u128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:42:17
help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
|
LL | usize::from(x_u16) > x_usize;
- | ~~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:45:17
|
LL | x_u32 > x_u8;
- | ^^^^
- | |
- | expected `u32`, found `u8`
- | help: you can convert a `u8` to a `u32`: `x_u8.into()`
+ | ^^^^ expected `u32`, found `u8`
+ |
+help: you can convert a `u8` to a `u32`
+ |
+LL | x_u32 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:47:17
|
LL | x_u32 > x_u16;
- | ^^^^^
- | |
- | expected `u32`, found `u16`
- | help: you can convert a `u16` to a `u32`: `x_u16.into()`
+ | ^^^^^ expected `u32`, found `u16`
+ |
+help: you can convert a `u16` to a `u32`
+ |
+LL | x_u32 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:49:17
help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
|
LL | u64::from(x_u32) > x_u64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:51:17
help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
|
LL | u128::from(x_u32) > x_u128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:53:17
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | x_u32 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:56:17
|
LL | x_u64 > x_u8;
- | ^^^^
- | |
- | expected `u64`, found `u8`
- | help: you can convert a `u8` to a `u64`: `x_u8.into()`
+ | ^^^^ expected `u64`, found `u8`
+ |
+help: you can convert a `u8` to a `u64`
+ |
+LL | x_u64 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:58:17
|
LL | x_u64 > x_u16;
- | ^^^^^
- | |
- | expected `u64`, found `u16`
- | help: you can convert a `u16` to a `u64`: `x_u16.into()`
+ | ^^^^^ expected `u64`, found `u16`
+ |
+help: you can convert a `u16` to a `u64`
+ |
+LL | x_u64 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:60:17
|
LL | x_u64 > x_u32;
- | ^^^^^
- | |
- | expected `u64`, found `u32`
- | help: you can convert a `u32` to a `u64`: `x_u32.into()`
+ | ^^^^^ expected `u64`, found `u32`
+ |
+help: you can convert a `u32` to a `u64`
+ |
+LL | x_u64 > x_u32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:62:17
help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
|
LL | u128::from(x_u64) > x_u128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:64:17
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:67:18
|
LL | x_u128 > x_u8;
- | ^^^^
- | |
- | expected `u128`, found `u8`
- | help: you can convert a `u8` to a `u128`: `x_u8.into()`
+ | ^^^^ expected `u128`, found `u8`
+ |
+help: you can convert a `u8` to a `u128`
+ |
+LL | x_u128 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:69:18
|
LL | x_u128 > x_u16;
- | ^^^^^
- | |
- | expected `u128`, found `u16`
- | help: you can convert a `u16` to a `u128`: `x_u16.into()`
+ | ^^^^^ expected `u128`, found `u16`
+ |
+help: you can convert a `u16` to a `u128`
+ |
+LL | x_u128 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:71:18
|
LL | x_u128 > x_u32;
- | ^^^^^
- | |
- | expected `u128`, found `u32`
- | help: you can convert a `u32` to a `u128`: `x_u32.into()`
+ | ^^^^^ expected `u128`, found `u32`
+ |
+help: you can convert a `u32` to a `u128`
+ |
+LL | x_u128 > x_u32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:73:18
|
LL | x_u128 > x_u64;
- | ^^^^^
- | |
- | expected `u128`, found `u64`
- | help: you can convert a `u64` to a `u128`: `x_u64.into()`
+ | ^^^^^ expected `u128`, found `u64`
+ |
+help: you can convert a `u64` to a `u128`
+ |
+LL | x_u128 > x_u64.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:75:18
help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:78:19
|
LL | x_usize > x_u8;
- | ^^^^
- | |
- | expected `usize`, found `u8`
- | help: you can convert a `u8` to a `usize`: `x_u8.into()`
+ | ^^^^ expected `usize`, found `u8`
+ |
+help: you can convert a `u8` to a `usize`
+ |
+LL | x_usize > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:80:19
|
LL | x_usize > x_u16;
- | ^^^^^
- | |
- | expected `usize`, found `u16`
- | help: you can convert a `u16` to a `usize`: `x_u16.into()`
+ | ^^^^^ expected `usize`, found `u16`
+ |
+help: you can convert a `u16` to a `usize`
+ |
+LL | x_usize > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:82:19
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_u32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:84:19
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:86:19
help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:92:16
help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
|
LL | i16::from(x_i8) > x_i16;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:94:16
help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
|
LL | i32::from(x_i8) > x_i32;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:96:16
help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_i8) > x_i64;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:98:16
help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_i8) > x_i128;
- | ~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:100:16
help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
|
LL | isize::from(x_i8) > x_isize;
- | ~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:103:17
|
LL | x_i16 > x_i8;
- | ^^^^
- | |
- | expected `i16`, found `i8`
- | help: you can convert an `i8` to an `i16`: `x_i8.into()`
+ | ^^^^ expected `i16`, found `i8`
+ |
+help: you can convert an `i8` to an `i16`
+ |
+LL | x_i16 > x_i8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:105:17
help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
|
LL | i32::from(x_i16) > x_i32;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:107:17
help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_i16) > x_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:109:17
help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_i16) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:111:17
help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
|
LL | isize::from(x_i16) > x_isize;
- | ~~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:114:17
|
LL | x_i32 > x_i8;
- | ^^^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `x_i8.into()`
+ | ^^^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | x_i32 > x_i8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:116:17
|
LL | x_i32 > x_i16;
- | ^^^^^
- | |
- | expected `i32`, found `i16`
- | help: you can convert an `i16` to an `i32`: `x_i16.into()`
+ | ^^^^^ expected `i32`, found `i16`
+ |
+help: you can convert an `i16` to an `i32`
+ |
+LL | x_i32 > x_i16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:118:17
help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_i32) > x_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:120:17
help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_i32) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:122:17
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
LL | x_i32 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:125:17
|
LL | x_i64 > x_i8;
- | ^^^^
- | |
- | expected `i64`, found `i8`
- | help: you can convert an `i8` to an `i64`: `x_i8.into()`
+ | ^^^^ expected `i64`, found `i8`
+ |
+help: you can convert an `i8` to an `i64`
+ |
+LL | x_i64 > x_i8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:127:17
|
LL | x_i64 > x_i16;
- | ^^^^^
- | |
- | expected `i64`, found `i16`
- | help: you can convert an `i16` to an `i64`: `x_i16.into()`
+ | ^^^^^ expected `i64`, found `i16`
+ |
+help: you can convert an `i16` to an `i64`
+ |
+LL | x_i64 > x_i16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:129:17
|
LL | x_i64 > x_i32;
- | ^^^^^
- | |
- | expected `i64`, found `i32`
- | help: you can convert an `i32` to an `i64`: `x_i32.into()`
+ | ^^^^^ expected `i64`, found `i32`
+ |
+help: you can convert an `i32` to an `i64`
+ |
+LL | x_i64 > x_i32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:131:17
help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_i64) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:133:17
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
LL | x_i64 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:136:18
|
LL | x_i128 > x_i8;
- | ^^^^
- | |
- | expected `i128`, found `i8`
- | help: you can convert an `i8` to an `i128`: `x_i8.into()`
+ | ^^^^ expected `i128`, found `i8`
+ |
+help: you can convert an `i8` to an `i128`
+ |
+LL | x_i128 > x_i8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:138:18
|
LL | x_i128 > x_i16;
- | ^^^^^
- | |
- | expected `i128`, found `i16`
- | help: you can convert an `i16` to an `i128`: `x_i16.into()`
+ | ^^^^^ expected `i128`, found `i16`
+ |
+help: you can convert an `i16` to an `i128`
+ |
+LL | x_i128 > x_i16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:140:18
|
LL | x_i128 > x_i32;
- | ^^^^^
- | |
- | expected `i128`, found `i32`
- | help: you can convert an `i32` to an `i128`: `x_i32.into()`
+ | ^^^^^ expected `i128`, found `i32`
+ |
+help: you can convert an `i32` to an `i128`
+ |
+LL | x_i128 > x_i32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:142:18
|
LL | x_i128 > x_i64;
- | ^^^^^
- | |
- | expected `i128`, found `i64`
- | help: you can convert an `i64` to an `i128`: `x_i64.into()`
+ | ^^^^^ expected `i128`, found `i64`
+ |
+help: you can convert an `i64` to an `i128`
+ |
+LL | x_i128 > x_i64.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:144:18
help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
|
LL | x_i128 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:147:19
|
LL | x_isize > x_i8;
- | ^^^^
- | |
- | expected `isize`, found `i8`
- | help: you can convert an `i8` to an `isize`: `x_i8.into()`
+ | ^^^^ expected `isize`, found `i8`
+ |
+help: you can convert an `i8` to an `isize`
+ |
+LL | x_isize > x_i8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:149:19
|
LL | x_isize > x_i16;
- | ^^^^^
- | |
- | expected `isize`, found `i16`
- | help: you can convert an `i16` to an `isize`: `x_i16.into()`
+ | ^^^^^ expected `isize`, found `i16`
+ |
+help: you can convert an `i16` to an `isize`
+ |
+LL | x_isize > x_i16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:151:19
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_i32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:153:19
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_i64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:155:19
help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_i128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:161:16
help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
|
LL | x_u8 > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:163:16
help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
|
LL | i16::from(x_u8) > x_i16;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:165:16
help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
|
LL | i32::from(x_u8) > x_i32;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:167:16
help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_u8) > x_i64;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:169:16
help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_u8) > x_i128;
- | ~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:171:16
help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
|
LL | isize::from(x_u8) > x_isize;
- | ~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:174:17
help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
|
LL | x_u16 > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:176:17
help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
|
LL | x_u16 > x_i16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:178:17
help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
|
LL | i32::from(x_u16) > x_i32;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:180:17
help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_u16) > x_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:182:17
help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_u16) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:184:17
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
LL | x_u16 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:187:17
help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
|
LL | x_u32 > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:189:17
help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
|
LL | x_u32 > x_i16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:191:17
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
LL | x_u32 > x_i32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:193:17
help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
|
LL | i64::from(x_u32) > x_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:195:17
help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_u32) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:197:17
help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
|
LL | x_u32 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:200:17
help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:202:17
help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_i16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:204:17
help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_i32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:206:17
help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_i64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:208:17
help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
|
LL | i128::from(x_u64) > x_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:210:17
help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
|
LL | x_u64 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:213:18
help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:215:18
help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_i16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:217:18
help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_i32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:219:18
help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_i64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:221:18
help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_i128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:223:18
help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
|
LL | x_u128 > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:226:19
help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_i8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:228:19
help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_i16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:230:19
help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_i32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:232:19
help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_i64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:234:19
help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_i128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:236:19
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | x_usize > x_isize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:242:16
help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_u8.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:244:16
help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_u16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:246:16
help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_u32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:248:16
help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:250:16
help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:252:16
help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
|
LL | x_i8 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:255:17
|
LL | x_i16 > x_u8;
- | ^^^^
- | |
- | expected `i16`, found `u8`
- | help: you can convert a `u8` to an `i16`: `x_u8.into()`
+ | ^^^^ expected `i16`, found `u8`
+ |
+help: you can convert a `u8` to an `i16`
+ |
+LL | x_i16 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:257:17
help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
|
LL | x_i16 > x_u16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:259:17
help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
|
LL | x_i16 > x_u32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:261:17
help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
|
LL | x_i16 > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:263:17
help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
|
LL | x_i16 > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:265:17
help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
|
LL | x_i16 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:268:17
|
LL | x_i32 > x_u8;
- | ^^^^
- | |
- | expected `i32`, found `u8`
- | help: you can convert a `u8` to an `i32`: `x_u8.into()`
+ | ^^^^ expected `i32`, found `u8`
+ |
+help: you can convert a `u8` to an `i32`
+ |
+LL | x_i32 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:270:17
|
LL | x_i32 > x_u16;
- | ^^^^^
- | |
- | expected `i32`, found `u16`
- | help: you can convert a `u16` to an `i32`: `x_u16.into()`
+ | ^^^^^ expected `i32`, found `u16`
+ |
+help: you can convert a `u16` to an `i32`
+ |
+LL | x_i32 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:272:17
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | x_i32 > x_u32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:274:17
help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
|
LL | x_i32 > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:276:17
help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
|
LL | x_i32 > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:278:17
help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
|
LL | x_i32 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:281:17
|
LL | x_i64 > x_u8;
- | ^^^^
- | |
- | expected `i64`, found `u8`
- | help: you can convert a `u8` to an `i64`: `x_u8.into()`
+ | ^^^^ expected `i64`, found `u8`
+ |
+help: you can convert a `u8` to an `i64`
+ |
+LL | x_i64 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:283:17
|
LL | x_i64 > x_u16;
- | ^^^^^
- | |
- | expected `i64`, found `u16`
- | help: you can convert a `u16` to an `i64`: `x_u16.into()`
+ | ^^^^^ expected `i64`, found `u16`
+ |
+help: you can convert a `u16` to an `i64`
+ |
+LL | x_i64 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:285:17
|
LL | x_i64 > x_u32;
- | ^^^^^
- | |
- | expected `i64`, found `u32`
- | help: you can convert a `u32` to an `i64`: `x_u32.into()`
+ | ^^^^^ expected `i64`, found `u32`
+ |
+help: you can convert a `u32` to an `i64`
+ |
+LL | x_i64 > x_u32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:287:17
help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
|
LL | x_i64 > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:289:17
help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
|
LL | x_i64 > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:291:17
help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
|
LL | x_i64 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:294:18
|
LL | x_i128 > x_u8;
- | ^^^^
- | |
- | expected `i128`, found `u8`
- | help: you can convert a `u8` to an `i128`: `x_u8.into()`
+ | ^^^^ expected `i128`, found `u8`
+ |
+help: you can convert a `u8` to an `i128`
+ |
+LL | x_i128 > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:296:18
|
LL | x_i128 > x_u16;
- | ^^^^^
- | |
- | expected `i128`, found `u16`
- | help: you can convert a `u16` to an `i128`: `x_u16.into()`
+ | ^^^^^ expected `i128`, found `u16`
+ |
+help: you can convert a `u16` to an `i128`
+ |
+LL | x_i128 > x_u16.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:298:18
|
LL | x_i128 > x_u32;
- | ^^^^^
- | |
- | expected `i128`, found `u32`
- | help: you can convert a `u32` to an `i128`: `x_u32.into()`
+ | ^^^^^ expected `i128`, found `u32`
+ |
+help: you can convert a `u32` to an `i128`
+ |
+LL | x_i128 > x_u32.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:300:18
|
LL | x_i128 > x_u64;
- | ^^^^^
- | |
- | expected `i128`, found `u64`
- | help: you can convert a `u64` to an `i128`: `x_u64.into()`
+ | ^^^^^ expected `i128`, found `u64`
+ |
+help: you can convert a `u64` to an `i128`
+ |
+LL | x_i128 > x_u64.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:302:18
help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
|
LL | x_i128 > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:304:18
help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
|
LL | x_i128 > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:307:19
|
LL | x_isize > x_u8;
- | ^^^^
- | |
- | expected `isize`, found `u8`
- | help: you can convert a `u8` to an `isize`: `x_u8.into()`
+ | ^^^^ expected `isize`, found `u8`
+ |
+help: you can convert a `u8` to an `isize`
+ |
+LL | x_isize > x_u8.into();
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:309:19
help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_u16.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:311:19
help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_u32.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:313:19
help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_u64.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:315:19
help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_u128.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast-binop.rs:317:19
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
LL | x_isize > x_usize.try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 132 previous errors
help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
|
LL | isize::from(x_u8) > -1_isize;
- | ~~~~~~~~~~~~~~~~~
+ | ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:23:15
help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
|
LL | i128::from(x_u64) > -1_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:29:13
help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
|
LL | i128::from(x_u32) > -1_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:31:13
help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
|
LL | i128::from(x_u16) > -1_i128;
- | ~~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:33:12
help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
|
LL | i128::from(x_u8) > -1_i128;
- | ~~~~~~~~~~~~~~~~
+ | +++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:36:15
help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
|
LL | i64::from(x_u32) > -1_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:44:13
help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
|
LL | i64::from(x_u16) > -1_i64;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:46:12
help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
|
LL | i64::from(x_u8) > -1_i64;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:49:15
help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
|
LL | i32::from(x_u16) > -1_i32;
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:59:12
help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
|
LL | i32::from(x_u8) > -1_i32;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:62:15
help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
|
LL | i16::from(x_u8) > -1_i16;
- | ~~~~~~~~~~~~~~~
+ | ++++++++++ +
error[E0308]: mismatched types
--> $DIR/numeric-cast-no-fix.rs:75:15
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:25:18
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:27:18
|
LL | foo::<usize>(x_u16);
- | ^^^^^
- | |
- | expected `usize`, found `u16`
- | help: you can convert a `u16` to a `usize`: `x_u16.into()`
+ | ^^^^^ expected `usize`, found `u16`
+ |
+help: you can convert a `u16` to a `usize`
+ |
+LL | foo::<usize>(x_u16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:29:18
|
LL | foo::<usize>(x_u8);
- | ^^^^
- | |
- | expected `usize`, found `u8`
- | help: you can convert a `u8` to a `usize`: `x_u8.into()`
+ | ^^^^ expected `usize`, found `u8`
+ |
+help: you can convert a `u8` to a `usize`
+ |
+LL | foo::<usize>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:31:18
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:33:18
help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:35:18
help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:37:18
help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:39:18
help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:44:18
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:46:18
help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:48:18
help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:50:18
help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:52:18
|
LL | foo::<isize>(x_u8);
- | ^^^^
- | |
- | expected `isize`, found `u8`
- | help: you can convert a `u8` to an `isize`: `x_u8.into()`
+ | ^^^^ expected `isize`, found `u8`
+ |
+help: you can convert a `u8` to an `isize`
+ |
+LL | foo::<isize>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:55:18
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:57:18
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:59:18
|
LL | foo::<isize>(x_i16);
- | ^^^^^
- | |
- | expected `isize`, found `i16`
- | help: you can convert an `i16` to an `isize`: `x_i16.into()`
+ | ^^^^^ expected `isize`, found `i16`
+ |
+help: you can convert an `i16` to an `isize`
+ |
+LL | foo::<isize>(x_i16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:61:18
|
LL | foo::<isize>(x_i8);
- | ^^^^
- | |
- | expected `isize`, found `i8`
- | help: you can convert an `i8` to an `isize`: `x_i8.into()`
+ | ^^^^ expected `isize`, found `i8`
+ |
+help: you can convert an `i8` to an `isize`
+ |
+LL | foo::<isize>(x_i8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:66:16
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:69:16
|
LL | foo::<u64>(x_u32);
- | ^^^^^
- | |
- | expected `u64`, found `u32`
- | help: you can convert a `u32` to a `u64`: `x_u32.into()`
+ | ^^^^^ expected `u64`, found `u32`
+ |
+help: you can convert a `u32` to a `u64`
+ |
+LL | foo::<u64>(x_u32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:71:16
|
LL | foo::<u64>(x_u16);
- | ^^^^^
- | |
- | expected `u64`, found `u16`
- | help: you can convert a `u16` to a `u64`: `x_u16.into()`
+ | ^^^^^ expected `u64`, found `u16`
+ |
+help: you can convert a `u16` to a `u64`
+ |
+LL | foo::<u64>(x_u16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:73:16
|
LL | foo::<u64>(x_u8);
- | ^^^^
- | |
- | expected `u64`, found `u8`
- | help: you can convert a `u8` to a `u64`: `x_u8.into()`
+ | ^^^^ expected `u64`, found `u8`
+ |
+help: you can convert a `u8` to a `u64`
+ |
+LL | foo::<u64>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:75:16
help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:77:16
help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:79:16
help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:81:16
help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:83:16
help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:88:16
help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:90:16
help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:92:16
|
LL | foo::<i64>(x_u32);
- | ^^^^^
- | |
- | expected `i64`, found `u32`
- | help: you can convert a `u32` to an `i64`: `x_u32.into()`
+ | ^^^^^ expected `i64`, found `u32`
+ |
+help: you can convert a `u32` to an `i64`
+ |
+LL | foo::<i64>(x_u32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:94:16
|
LL | foo::<i64>(x_u16);
- | ^^^^^
- | |
- | expected `i64`, found `u16`
- | help: you can convert a `u16` to an `i64`: `x_u16.into()`
+ | ^^^^^ expected `i64`, found `u16`
+ |
+help: you can convert a `u16` to an `i64`
+ |
+LL | foo::<i64>(x_u16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:96:16
|
LL | foo::<i64>(x_u8);
- | ^^^^
- | |
- | expected `i64`, found `u8`
- | help: you can convert a `u8` to an `i64`: `x_u8.into()`
+ | ^^^^ expected `i64`, found `u8`
+ |
+help: you can convert a `u8` to an `i64`
+ |
+LL | foo::<i64>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:98:16
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:101:16
|
LL | foo::<i64>(x_i32);
- | ^^^^^
- | |
- | expected `i64`, found `i32`
- | help: you can convert an `i32` to an `i64`: `x_i32.into()`
+ | ^^^^^ expected `i64`, found `i32`
+ |
+help: you can convert an `i32` to an `i64`
+ |
+LL | foo::<i64>(x_i32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:103:16
|
LL | foo::<i64>(x_i16);
- | ^^^^^
- | |
- | expected `i64`, found `i16`
- | help: you can convert an `i16` to an `i64`: `x_i16.into()`
+ | ^^^^^ expected `i64`, found `i16`
+ |
+help: you can convert an `i16` to an `i64`
+ |
+LL | foo::<i64>(x_i16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:105:16
|
LL | foo::<i64>(x_i8);
- | ^^^^
- | |
- | expected `i64`, found `i8`
- | help: you can convert an `i8` to an `i64`: `x_i8.into()`
+ | ^^^^ expected `i64`, found `i8`
+ |
+help: you can convert an `i8` to an `i64`
+ |
+LL | foo::<i64>(x_i8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:110:16
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:112:16
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:115:16
|
LL | foo::<u32>(x_u16);
- | ^^^^^
- | |
- | expected `u32`, found `u16`
- | help: you can convert a `u16` to a `u32`: `x_u16.into()`
+ | ^^^^^ expected `u32`, found `u16`
+ |
+help: you can convert a `u16` to a `u32`
+ |
+LL | foo::<u32>(x_u16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:117:16
|
LL | foo::<u32>(x_u8);
- | ^^^^
- | |
- | expected `u32`, found `u8`
- | help: you can convert a `u8` to a `u32`: `x_u8.into()`
+ | ^^^^ expected `u32`, found `u8`
+ |
+help: you can convert a `u8` to a `u32`
+ |
+LL | foo::<u32>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:119:16
help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:121:16
help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:123:16
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:125:16
help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:127:16
help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:132:16
help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:134:16
help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:136:16
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:138:16
|
LL | foo::<i32>(x_u16);
- | ^^^^^
- | |
- | expected `i32`, found `u16`
- | help: you can convert a `u16` to an `i32`: `x_u16.into()`
+ | ^^^^^ expected `i32`, found `u16`
+ |
+help: you can convert a `u16` to an `i32`
+ |
+LL | foo::<i32>(x_u16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:140:16
|
LL | foo::<i32>(x_u8);
- | ^^^^
- | |
- | expected `i32`, found `u8`
- | help: you can convert a `u8` to an `i32`: `x_u8.into()`
+ | ^^^^ expected `i32`, found `u8`
+ |
+help: you can convert a `u8` to an `i32`
+ |
+LL | foo::<i32>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:142:16
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:144:16
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:147:16
|
LL | foo::<i32>(x_i16);
- | ^^^^^
- | |
- | expected `i32`, found `i16`
- | help: you can convert an `i16` to an `i32`: `x_i16.into()`
+ | ^^^^^ expected `i32`, found `i16`
+ |
+help: you can convert an `i16` to an `i32`
+ |
+LL | foo::<i32>(x_i16.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:149:16
|
LL | foo::<i32>(x_i8);
- | ^^^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `x_i8.into()`
+ | ^^^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | foo::<i32>(x_i8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:154:16
help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:156:16
help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:158:16
help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:161:16
|
LL | foo::<u16>(x_u8);
- | ^^^^
- | |
- | expected `u16`, found `u8`
- | help: you can convert a `u8` to a `u16`: `x_u8.into()`
+ | ^^^^ expected `u16`, found `u8`
+ |
+help: you can convert a `u8` to a `u16`
+ |
+LL | foo::<u16>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:163:16
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:165:16
help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:167:16
help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:169:16
help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:171:16
help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:176:16
help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:178:16
help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:180:16
help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:182:16
help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:184:16
|
LL | foo::<i16>(x_u8);
- | ^^^^
- | |
- | expected `i16`, found `u8`
- | help: you can convert a `u8` to an `i16`: `x_u8.into()`
+ | ^^^^ expected `i16`, found `u8`
+ |
+help: you can convert a `u8` to an `i16`
+ |
+LL | foo::<i16>(x_u8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:186:16
help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:188:16
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:190:16
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:193:16
|
LL | foo::<i16>(x_i8);
- | ^^^^
- | |
- | expected `i16`, found `i8`
- | help: you can convert an `i8` to an `i16`: `x_i8.into()`
+ | ^^^^ expected `i16`, found `i8`
+ |
+help: you can convert an `i8` to an `i16`
+ |
+LL | foo::<i16>(x_i8.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:198:15
help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:200:15
help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:202:15
help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:204:15
help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:207:15
help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:209:15
help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:211:15
help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:213:15
help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:215:15
help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:220:15
help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_usize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:222:15
help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:224:15
help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:226:15
help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:228:15
help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u8.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:230:15
help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_isize.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:232:15
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i64.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:234:15
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i32.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:236:15
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i16.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:242:16
help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer,
| rounded if necessary
LL | foo::<f64>(x_usize as f64);
- | ~~~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:244:16
help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer,
| rounded if necessary
LL | foo::<f64>(x_u64 as f64);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:246:16
help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u32.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:248:16
help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u16.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:250:16
help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u8.into());
- | ~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:252:16
help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_isize as f64);
- | ~~~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:254:16
help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_i64 as f64);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:256:16
help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i32.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:258:16
help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i16.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:260:16
help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i8.into());
- | ~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:263:16
|
LL | foo::<f64>(x_f32);
- | ^^^^^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `x_f32.into()`
+ | ^^^^^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | foo::<f64>(x_f32.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:266:16
help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer,
| rounded if necessary
LL | foo::<f32>(x_usize as f32);
- | ~~~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:268:16
help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer,
| rounded if necessary
LL | foo::<f32>(x_u64 as f32);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:270:16
help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer,
| rounded if necessary
LL | foo::<f32>(x_u32 as f32);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:272:16
help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_u16.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:274:16
help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_u8.into());
- | ~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:276:16
help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_isize as f32);
- | ~~~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:278:16
help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_i64 as f32);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:280:16
help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_i32 as f32);
- | ~~~~~~~~~~~~
+ | ++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:282:16
help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_i16.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:284:16
help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_i8.into());
- | ~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:289:16
|
LL | foo::<u32>(x_u8 as u16);
- | ^^^^^^^^^^^
- | |
- | expected `u32`, found `u16`
- | help: you can convert a `u16` to a `u32`: `(x_u8 as u16).into()`
+ | ^^^^^^^^^^^ expected `u32`, found `u16`
+ |
+help: you can convert a `u16` to a `u32`
+ |
+LL | foo::<u32>((x_u8 as u16).into());
+ | + ++++++++
error[E0308]: mismatched types
--> $DIR/numeric-cast.rs:291:16
|
LL | foo::<i32>(-x_i8);
- | ^^^^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `(-x_i8).into()`
+ | ^^^^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | foo::<i32>((-x_i8).into());
+ | + ++++++++
error: aborting due to 113 previous errors
--> $DIR/numeric-fields.rs:7:17
|
LL | S{0: a, 0x1: b, ..} => {}
- | ^^^ struct `S` does not have this field
+ | ^^^
+ | |
+ | struct `S` does not have this field
+ | help: `S` has a field named `1`
error: aborting due to 2 previous errors
help: change the type of the numeric literal from `u64` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:9:18
help: change the type of the numeric literal from `u32` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:11:18
help: change the type of the numeric literal from `u16` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:13:18
help: change the type of the numeric literal from `u8` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:15:18
help: change the type of the numeric literal from `isize` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:17:18
help: change the type of the numeric literal from `i64` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:19:18
help: change the type of the numeric literal from `i32` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:21:18
help: change the type of the numeric literal from `i16` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:23:18
help: change the type of the numeric literal from `i8` to `usize`
|
LL | foo::<usize>(42_usize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:25:18
help: change the type of the numeric literal from `f64` to `usize`
|
LL | foo::<usize>(42usize);
- | ~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:27:18
help: change the type of the numeric literal from `f32` to `usize`
|
LL | foo::<usize>(42usize);
- | ~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:30:18
help: change the type of the numeric literal from `usize` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:32:18
help: change the type of the numeric literal from `u64` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:34:18
help: change the type of the numeric literal from `u32` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:36:18
help: change the type of the numeric literal from `u16` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:38:18
help: change the type of the numeric literal from `u8` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:41:18
help: change the type of the numeric literal from `i64` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:43:18
help: change the type of the numeric literal from `i32` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:45:18
help: change the type of the numeric literal from `i16` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:47:18
help: change the type of the numeric literal from `i8` to `isize`
|
LL | foo::<isize>(42_isize);
- | ~~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:49:18
help: change the type of the numeric literal from `f64` to `isize`
|
LL | foo::<isize>(42isize);
- | ~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:51:18
help: change the type of the numeric literal from `f32` to `isize`
|
LL | foo::<isize>(42isize);
- | ~~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:54:16
help: change the type of the numeric literal from `usize` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:57:16
help: change the type of the numeric literal from `u32` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:59:16
help: change the type of the numeric literal from `u16` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:61:16
help: change the type of the numeric literal from `u8` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:63:16
help: change the type of the numeric literal from `isize` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:65:16
help: change the type of the numeric literal from `i64` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:67:16
help: change the type of the numeric literal from `i32` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:69:16
help: change the type of the numeric literal from `i16` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:71:16
help: change the type of the numeric literal from `i8` to `u64`
|
LL | foo::<u64>(42_u64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:73:16
help: change the type of the numeric literal from `f64` to `u64`
|
LL | foo::<u64>(42u64);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:75:16
help: change the type of the numeric literal from `f32` to `u64`
|
LL | foo::<u64>(42u64);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:78:16
help: change the type of the numeric literal from `usize` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:80:16
help: change the type of the numeric literal from `u64` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:82:16
help: change the type of the numeric literal from `u32` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:84:16
help: change the type of the numeric literal from `u16` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:86:16
help: change the type of the numeric literal from `u8` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:88:16
help: change the type of the numeric literal from `isize` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:91:16
help: change the type of the numeric literal from `i32` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:93:16
help: change the type of the numeric literal from `i16` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:95:16
help: change the type of the numeric literal from `i8` to `i64`
|
LL | foo::<i64>(42_i64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:97:16
help: change the type of the numeric literal from `f64` to `i64`
|
LL | foo::<i64>(42i64);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:99:16
help: change the type of the numeric literal from `f32` to `i64`
|
LL | foo::<i64>(42i64);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:102:16
help: change the type of the numeric literal from `usize` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:104:16
help: change the type of the numeric literal from `u64` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:107:16
help: change the type of the numeric literal from `u16` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:109:16
help: change the type of the numeric literal from `u8` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:111:16
help: change the type of the numeric literal from `isize` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:113:16
help: change the type of the numeric literal from `i64` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:115:16
help: change the type of the numeric literal from `i32` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:117:16
help: change the type of the numeric literal from `i16` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:119:16
help: change the type of the numeric literal from `i8` to `u32`
|
LL | foo::<u32>(42_u32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:121:16
help: change the type of the numeric literal from `f64` to `u32`
|
LL | foo::<u32>(42u32);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:123:16
help: change the type of the numeric literal from `f32` to `u32`
|
LL | foo::<u32>(42u32);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:126:16
help: change the type of the numeric literal from `usize` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:128:16
help: change the type of the numeric literal from `u64` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:130:16
help: change the type of the numeric literal from `u32` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:132:16
help: change the type of the numeric literal from `u16` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:134:16
help: change the type of the numeric literal from `u8` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:136:16
help: change the type of the numeric literal from `isize` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:138:16
help: change the type of the numeric literal from `i64` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:141:16
help: change the type of the numeric literal from `i16` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:143:16
help: change the type of the numeric literal from `i8` to `i32`
|
LL | foo::<i32>(42_i32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:145:16
help: change the type of the numeric literal from `f64` to `i32`
|
LL | foo::<i32>(42i32);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:147:16
help: change the type of the numeric literal from `f32` to `i32`
|
LL | foo::<i32>(42i32);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:150:16
help: change the type of the numeric literal from `usize` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:152:16
help: change the type of the numeric literal from `u64` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:154:16
help: change the type of the numeric literal from `u32` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:157:16
help: change the type of the numeric literal from `u8` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:159:16
help: change the type of the numeric literal from `isize` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:161:16
help: change the type of the numeric literal from `i64` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:163:16
help: change the type of the numeric literal from `i32` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:165:16
help: change the type of the numeric literal from `i16` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:167:16
help: change the type of the numeric literal from `i8` to `u16`
|
LL | foo::<u16>(42_u16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:169:16
help: change the type of the numeric literal from `f64` to `u16`
|
LL | foo::<u16>(42u16);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:171:16
help: change the type of the numeric literal from `f32` to `u16`
|
LL | foo::<u16>(42u16);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:174:16
help: change the type of the numeric literal from `usize` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:176:16
help: change the type of the numeric literal from `u64` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:178:16
help: change the type of the numeric literal from `u32` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:180:16
help: change the type of the numeric literal from `u16` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:182:16
help: change the type of the numeric literal from `u8` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:184:16
help: change the type of the numeric literal from `isize` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:186:16
help: change the type of the numeric literal from `i64` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:188:16
help: change the type of the numeric literal from `i32` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:191:16
help: change the type of the numeric literal from `i8` to `i16`
|
LL | foo::<i16>(42_i16);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:193:16
help: change the type of the numeric literal from `f64` to `i16`
|
LL | foo::<i16>(42i16);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:195:16
help: change the type of the numeric literal from `f32` to `i16`
|
LL | foo::<i16>(42i16);
- | ~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:198:15
help: change the type of the numeric literal from `usize` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:200:15
help: change the type of the numeric literal from `u64` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:202:15
help: change the type of the numeric literal from `u32` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:204:15
help: change the type of the numeric literal from `u16` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:207:15
help: change the type of the numeric literal from `isize` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:209:15
help: change the type of the numeric literal from `i64` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:211:15
help: change the type of the numeric literal from `i32` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:213:15
help: change the type of the numeric literal from `i16` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:215:15
help: change the type of the numeric literal from `i8` to `u8`
|
LL | foo::<u8>(42_u8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:217:15
help: change the type of the numeric literal from `f64` to `u8`
|
LL | foo::<u8>(42u8);
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:219:15
help: change the type of the numeric literal from `f32` to `u8`
|
LL | foo::<u8>(42u8);
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:222:15
help: change the type of the numeric literal from `usize` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:224:15
help: change the type of the numeric literal from `u64` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:226:15
help: change the type of the numeric literal from `u32` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:228:15
help: change the type of the numeric literal from `u16` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:230:15
help: change the type of the numeric literal from `u8` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:232:15
help: change the type of the numeric literal from `isize` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:234:15
help: change the type of the numeric literal from `i64` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:236:15
help: change the type of the numeric literal from `i32` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:238:15
help: change the type of the numeric literal from `i16` to `i8`
|
LL | foo::<i8>(42_i8);
- | ~~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:241:15
help: change the type of the numeric literal from `f64` to `i8`
|
LL | foo::<i8>(42i8);
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:243:15
help: change the type of the numeric literal from `f32` to `i8`
|
LL | foo::<i8>(42i8);
- | ~~~~
+ | ~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:246:16
help: change the type of the numeric literal from `usize` to `f64`
|
LL | foo::<f64>(42_f64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:248:16
help: change the type of the numeric literal from `u64` to `f64`
|
LL | foo::<f64>(42_f64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:250:16
help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_u32.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:252:16
help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_u16.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:254:16
help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_u8.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:256:16
help: change the type of the numeric literal from `isize` to `f64`
|
LL | foo::<f64>(42_f64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:258:16
help: change the type of the numeric literal from `i64` to `f64`
|
LL | foo::<f64>(42_f64);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:260:16
help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_i32.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:262:16
help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_i16.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:264:16
help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(42_i8.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:267:16
help: change the type of the numeric literal from `f32` to `f64`
|
LL | foo::<f64>(42.0_f64);
- | ~~~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:270:16
help: change the type of the numeric literal from `usize` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:272:16
help: change the type of the numeric literal from `u64` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:274:16
help: change the type of the numeric literal from `u32` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:276:16
help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(42_u16.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:278:16
help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(42_u8.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:280:16
help: change the type of the numeric literal from `isize` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:282:16
help: change the type of the numeric literal from `i64` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:284:16
help: change the type of the numeric literal from `i32` to `f32`
|
LL | foo::<f32>(42_f32);
- | ~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:286:16
help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(42_i16.into());
- | ~~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:288:16
help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(42_i8.into());
- | ~~~~~~~~~~~~
+ | +++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:290:16
help: change the type of the numeric literal from `f64` to `f32`
|
LL | foo::<f32>(42.0_f32);
- | ~~~~~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:294:16
|
LL | foo::<u32>(42_u8 as u16);
- | ^^^^^^^^^^^^
- | |
- | expected `u32`, found `u16`
- | help: you can convert a `u16` to a `u32`: `(42_u8 as u16).into()`
+ | ^^^^^^^^^^^^ expected `u32`, found `u16`
+ |
+help: you can convert a `u16` to a `u32`
+ |
+LL | foo::<u32>((42_u8 as u16).into());
+ | + ++++++++
error[E0308]: mismatched types
--> $DIR/numeric-suffix.rs:296:16
|
LL | foo::<i32>(-42_i8);
- | ^^^^^^
- | |
- | expected `i32`, found `i8`
- | help: you can convert an `i8` to an `i32`: `(-42_i8).into()`
+ | ^^^^^^ expected `i32`, found `i8`
+ |
+help: you can convert an `i8` to an `i32`
+ |
+LL | foo::<i32>((-42_i8).into());
+ | + ++++++++
error: aborting due to 134 previous errors
--> $DIR/object-does-not-impl-trait.rs:6:44
|
LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
- | ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+ | -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `take_foo`
--> $DIR/object-does-not-impl-trait.rs:5:15
|
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/object-lifetime-default-elision.rs:71:5
|
LL | ss
|
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/object-lifetime-default-elision.rs:71:5
|
LL | ss
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `X` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-associated-consts.rs:9:11
|
| --- this trait cannot be made into an object...
LL | const X: usize;
| ^ ...because it contains this associated `const`
+ = help: consider moving `X` to another trait
error: aborting due to previous error
LL | t
| ^ `Bar` cannot be made into an object
|
- = help: consider moving `X` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-associated-consts.rs:9:11
|
| --- this trait cannot be made into an object...
LL | const X: usize;
| ^ ...because it contains this associated `const`
+ = help: consider moving `X` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
= note: required by cast to type `&dyn Bar`
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-generics.rs:10:8
|
| --- this trait cannot be made into an object...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
+ = help: consider moving `bar` to another trait
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-generics.rs:24:39
LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-generics.rs:10:8
|
| --- this trait cannot be made into an object...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
+ = help: consider moving `bar` to another trait
error: aborting due to 2 previous errors
LL | t
| ^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-generics.rs:10:8
|
| --- this trait cannot be made into an object...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
+ = help: consider moving `bar` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
= note: required by cast to type `&dyn Bar`
LL | t as &dyn Bar
| ^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-generics.rs:10:8
|
| --- this trait cannot be made into an object...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
+ = help: consider moving `bar` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
= note: required by cast to type `&dyn Bar`
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-mentions-Self.rs:11:22
|
| --- this trait cannot be made into an object...
LL | fn bar(&self, x: &Self);
| ^^^^^ ...because method `bar` references the `Self` type in this parameter
+ = help: consider moving `bar` to another trait
error[E0038]: the trait `Baz` cannot be made into an object
--> $DIR/object-safety-mentions-Self.rs:28:30
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
| ^^^^^^^^ `Baz` cannot be made into an object
|
- = help: consider moving `baz` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-mentions-Self.rs:15:22
|
| --- this trait cannot be made into an object...
LL | fn baz(&self) -> Self;
| ^^^^ ...because method `baz` references the `Self` type in its return type
+ = help: consider moving `baz` to another trait
error: aborting due to 2 previous errors
LL | t
| ^ `Bar` cannot be made into an object
|
- = help: consider moving `bar` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-mentions-Self.rs:11:22
|
| --- this trait cannot be made into an object...
LL | fn bar(&self, x: &Self);
| ^^^^^ ...because method `bar` references the `Self` type in this parameter
+ = help: consider moving `bar` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
= note: required by cast to type `&dyn Bar`
LL | t
| ^ `Baz` cannot be made into an object
|
- = help: consider moving `baz` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-safety-mentions-Self.rs:15:22
|
| --- this trait cannot be made into an object...
LL | fn baz(&self) -> Self;
| ^^^^ ...because method `baz` references the `Self` type in its return type
+ = help: consider moving `baz` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T`
= note: required by cast to type `&dyn Baz`
LL | let x = || {
| _____________-
LL | | f(Foo{});
- | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | |
+ | | required by a bound introduced by this call
LL | | let y = || {
LL | | f(Foo{});
LL | | };
LL | let y = || {
| _________________-
LL | | f(Foo{});
- | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | |
+ | | required by a bound introduced by this call
LL | | };
| |_________- in this scope
|
LL | | let y = || {
... |
LL | | f(Foo{});
- | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | |
+ | | required by a bound introduced by this call
... |
LL | | f(Foo{});
LL | | }
LL | | let y = || {
... |
LL | | f(Foo{});
- | | ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | - ^^^^^ the trait `Trait` is not implemented for `Foo`
+ | | |
+ | | required by a bound introduced by this call
LL | | }
| |_- in this scope
|
--> $DIR/multiple-impls.rs:33:18
|
LL | Index::index(&[] as &[i32], 2u32);
- | ^^^^^^^^^^^^^ trait message
+ | ------------ ^^^^^^^^^^^^^ trait message
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
note: required by `Index::index`
--> $DIR/multiple-impls.rs:36:18
|
LL | Index::index(&[] as &[i32], Foo(2u32));
- | ^^^^^^^^^^^^^ on impl for Foo
+ | ------------ ^^^^^^^^^^^^^ on impl for Foo
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
note: required by `Index::index`
--> $DIR/multiple-impls.rs:39:18
|
LL | Index::index(&[] as &[i32], Bar(2u32));
- | ^^^^^^^^^^^^^ on impl for Bar
+ | ------------ ^^^^^^^^^^^^^ on impl for Bar
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
note: required by `Index::index`
--> $DIR/on-impl.rs:22:25
|
LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
- | ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Index<u32>` is not implemented for `[i32]`
note: required by `Index::index`
+++ /dev/null
-// aux-build:define-macro.rs
-
-macro_rules! bar { () => {} }
-define_macro!(bar);
-bar!(); //~ ERROR `bar` is ambiguous
-
-macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
-m!();
-
-fn main() {}
+++ /dev/null
-error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
- --> $DIR/out-of-order-shadowing.rs:5:1
- |
-LL | bar!();
- | ^^^ ambiguous name
- |
-note: `bar` could refer to the macro defined here
- --> $DIR/out-of-order-shadowing.rs:4:1
- |
-LL | define_macro!(bar);
- | ^^^^^^^^^^^^^^^^^^^
-note: `bar` could also refer to the macro defined here
- --> $DIR/out-of-order-shadowing.rs:3:1
- |
-LL | macro_rules! bar { () => {} }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the macro `define_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
// run-pass
+#![allow(dead_code)]
+
use std::rc::Rc;
use std::ops::Deref;
}) > 0 //~ ERROR expected expression
}
+fn qux() -> u32 {
+ ({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+ //~^ ERROR mismatched types
+}
+
fn main() {}
} > 0 //~ ERROR expected expression
}
+fn qux() -> u32 {
+ {2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+ //~^ ERROR mismatched types
+}
+
fn main() {}
LL | ({ 3 }) * 3
| + +
-error: aborting due to 9 previous errors
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt.rs:36:6
+ |
+LL | {2} - 2
+ | ^ expected `()`, found integer
+ |
+help: you might have meant to return this value
+ |
+LL | {return 2;} - 2
+ | ++++++ +
+
+error[E0600]: cannot apply unary operator `-` to type `u32`
+ --> $DIR/expr-as-stmt.rs:36:9
+ |
+LL | {2} - 2
+ | ^^^ cannot apply unary operator `-`
+ |
+help: parentheses are required to parse this as an expression
+ |
+LL | ({2}) - 2
+ | + +
+
+error: aborting due to 11 previous errors
-Some errors have detailed explanations: E0308, E0614.
+Some errors have detailed explanations: E0308, E0600, E0614.
For more information about an error, try `rustc --explain E0308`.
help: if this is a `self` type, give it a parameter name
|
LL | fn fizz(self: i32) {}
- | ~~~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn fizz(i32: TypeName) {}
- | ~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn fizz(_: i32) {}
- | ~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `S`
--> $DIR/inverted-parameters.rs:27:23
macro_rules! foo {
($rest: tt) => {
- bar(baz: $rest)
+ bar(baz: $rest) //~ ERROR invalid `struct` delimiters or `fn` call arguments
}
}
fn main() {
- foo!(true); //~ ERROR expected type, found keyword
+ foo!(true);
//~^ ERROR expected identifier, found keyword
}
LL | foo!(r#true);
| ~~~~~~
-error: expected type, found keyword `true`
- --> $DIR/issue-44406.rs:8:10
+error: invalid `struct` delimiters or `fn` call arguments
+ --> $DIR/issue-44406.rs:3:9
|
LL | bar(baz: $rest)
- | - help: try using a semicolon: `;`
+ | ^^^^^^^^^^^^^^^
...
LL | foo!(true);
- | ^^^^ expected type
+ | ----------- in this macro invocation
+ |
+ = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: if `bar` is a struct, use braces as delimiters
+ |
+LL | bar { }
+ | ~
+help: if `bar` is a function, use the arguments directly
|
- = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
- = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+LL - bar(baz: $rest)
+LL + bar(true);
+ |
error: aborting due to 2 previous errors
--- /dev/null
+// check-pass
+
+#![allow(non_camel_case_types)]
+
+struct union;
+
+impl union {
+ pub fn new() -> Self {
+ union { }
+ }
+}
+
+fn main() {
+ let _u = union::new();
+}
--- /dev/null
+// Regression test for #88818 (improve error message for missing trait
+// in `impl for X`).
+
+struct S { }
+impl for S { }
+//~^ ERROR: missing trait in a trait impl
+//~| HELP: add a trait here
+//~| HELP: for an inherent impl, drop this `for`
+
+fn main() {}
--- /dev/null
+error: missing trait in a trait impl
+ --> $DIR/issue-88818.rs:5:5
+ |
+LL | impl for S { }
+ | ^
+ |
+help: add a trait here
+ |
+LL | impl Trait for S { }
+ | +++++
+help: for an inherent impl, drop this `for`
+ |
+LL - impl for S { }
+LL + impl S { }
+ |
+
+error: aborting due to previous error
+
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a `self` type, give it a parameter name
|
-LL | fn test(self: &str) {
- | ~~~~~~~~~~
+LL | fn test(self: &'a str) {
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn test(str: &TypeName) {
| ~~~~~~~~~~~~~~
help: if this is a type, explicitly ignore the parameter name
|
-LL | fn test(_: &str) {
- | ~~~~~~~
+LL | fn test(_: &'a str) {
+ | ++
error: aborting due to 2 previous errors
--- /dev/null
+// check-pass
+
+use std::io::Write;
+
+fn main() -> Result<(), std::io::Error> {
+ vec! { 1, 2, 3 }.len();
+ write! { vec![], "" }?;
+ println!{""}
+ [0]; // separate statement, not indexing into the result of println.
+ Ok(())
+}
help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: x) {
- | ~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn foo(x: TypeName) {
- | ~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(_: x) {
- | ~~~~
+ | ++
error: aborting due to previous error
help: if this is a `self` type, give it a parameter name
|
LL | fn a(self: B<) {}
- | ~~~~~~~
+ | +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn a(_: B<) {}
- | ~~~~
+ | ++
error: aborting due to previous error
for ( elem in vec ) {
//~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in`
- //~| ERROR unexpected closing `)`
+ //~| ERROR unexpected parenthesis surrounding `for` loop head
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
}
}
LL | for ( elem in vec ) {
| ^^ expected one of `)`, `,`, `@`, or `|`
-error: unexpected closing `)`
- --> $DIR/recover-for-loop-parens-around-head.rs:10:23
+error: unexpected parenthesis surrounding `for` loop head
+ --> $DIR/recover-for-loop-parens-around-head.rs:10:9
|
LL | for ( elem in vec ) {
- | --------------^
- | |
- | opening `(`
- | help: remove parenthesis in `for` loop: `elem in vec`
+ | ^ ^
+ |
+help: remove parenthesis in `for` loop
+ |
+LL - for ( elem in vec ) {
+LL + for elem in vec {
+ |
error[E0308]: mismatched types
--> $DIR/recover-for-loop-parens-around-head.rs:13:38
fn main() {
let x = Enum::Foo(a: 3, b: 4);
- //~^ ERROR expected type, found `3`
+ //~^ ERROR invalid `struct` delimiters or `fn` call arguments
match x {
Enum::Foo(a, b) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
-error: expected type, found `3`
- --> $DIR/recover-from-bad-variant.rs:7:26
+error: invalid `struct` delimiters or `fn` call arguments
+ --> $DIR/recover-from-bad-variant.rs:7:13
|
LL | let x = Enum::Foo(a: 3, b: 4);
- | - ^ expected type
- | |
- | tried to parse a type due to this type ascription
+ | ^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
- = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Enum::Foo` is a struct, use braces as delimiters
+ |
+LL | let x = Enum::Foo { a: 3, b: 4 };
+ | ~ ~
+help: if `Enum::Foo` is a function, use the arguments directly
+ |
+LL - let x = Enum::Foo(a: 3, b: 4);
+LL + let x = Enum::Foo(3, 4);
+ |
error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
--> $DIR/recover-from-bad-variant.rs:10:9
--- /dev/null
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+ let _spade = "♠️";
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _s = "ṩ̂̊";
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _a = 'Å';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+ //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
--- /dev/null
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+ let _spade = '♠️';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _s = 'ṩ̂̊';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _a = 'Å';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+ //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
--- /dev/null
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:7:18
+ |
+LL | let _spade = '♠️';
+ | ^^^
+ |
+note: this `♠` is followed by the combining mark `\u{fe0f}`
+ --> $DIR/unicode-character-literal.rs:7:19
+ |
+LL | let _spade = '♠️';
+ | ^
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _spade = "♠️";
+ | ~~~
+
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:12:14
+ |
+LL | let _s = 'ṩ̂̊';
+ | ^^^
+ |
+note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ --> $DIR/unicode-character-literal.rs:12:15
+ |
+LL | let _s = 'ṩ̂̊';
+ | ^
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _s = "ṩ̂̊";
+ | ~~~
+
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:17:14
+ |
+LL | let _a = 'Å';
+ | ^-^
+ | |
+ | help: consider using the normalized form `\u{c5}` of this character: `Å`
+ |
+note: this `A` is followed by the combining mark `\u{30a}`
+ --> $DIR/unicode-character-literal.rs:17:15
+ |
+LL | let _a = 'Å';
+ | ^
+
+error: aborting due to 3 previous errors
+
--> $DIR/path-lookahead.rs:10:12
|
LL | return (<T as ToString>::to_string(&arg));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/path-lookahead.rs:5:9
|
LL | #![warn(unused_parens)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - return (<T as ToString>::to_string(&arg));
+LL + return <T as ToString>::to_string(&arg);
+ |
warning: 1 warning emitted
--> $DIR/phantom-auto-trait.rs:21:12
|
LL | is_zen(x)
- | ^ `T` cannot be shared between threads safely
+ | ------ ^ `T` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Zen` for `&T`
--> $DIR/phantom-auto-trait.rs:10:24
--> $DIR/phantom-auto-trait.rs:26:12
|
LL | is_zen(x)
- | ^ `T` cannot be shared between threads safely
+ | ------ ^ `T` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required because of the requirements on the impl of `Zen` for `&T`
--> $DIR/phantom-auto-trait.rs:10:24
--- /dev/null
+// compile-flags:-Zpolymorphize=on
+// build-pass
+
+fn test<T>() {
+ std::mem::size_of::<T>();
+}
+
+pub fn foo<T>(_: T) -> &'static fn() {
+ &(test::<T> as fn())
+}
+
+fn outer<T>() {
+ foo(|| ());
+}
+
+fn main() {
+ outer::<u8>();
+}
help: change the type of the numeric literal from `i32` to `u32`
|
LL | let_in(3u32, |i| { assert!(i == 3u32); });
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/pptypedef.rs:8:37
help: change the type of the numeric literal from `u32` to `i32`
|
LL | let_in(3i32, |i| { assert!(i == 3i32); });
- | ~~~~
+ | ~~~
error: aborting due to 2 previous errors
--- /dev/null
+mod foo {
+ pub struct Pub { private: () }
+
+ pub enum Enum {
+ Variant { x: (), y: () },
+ Other
+ }
+
+ fn correct() {
+ Pub {};
+ //~^ ERROR missing field `private` in initializer of `Pub`
+ Enum::Variant { x: () };
+ //~^ ERROR missing field `y` in initializer of `Enum`
+ }
+}
+
+fn correct() {
+ foo::Pub {};
+ //~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
+}
+
+fn wrong() {
+ foo::Enum::Variant { x: () };
+ //~^ ERROR missing field `y` in initializer of `Enum`
+ foo::Enum::Variant { };
+ //~^ ERROR missing fields `x` and `y` in initializer of `Enum`
+}
+
+fn main() {}
--- /dev/null
+error[E0063]: missing field `private` in initializer of `Pub`
+ --> $DIR/issue-79593.rs:10:9
+ |
+LL | Pub {};
+ | ^^^ missing `private`
+
+error[E0063]: missing field `y` in initializer of `Enum`
+ --> $DIR/issue-79593.rs:12:9
+ |
+LL | Enum::Variant { x: () };
+ | ^^^^^^^^^^^^^ missing `y`
+
+error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
+ --> $DIR/issue-79593.rs:18:5
+ |
+LL | foo::Pub {};
+ | ^^^^^^^^
+
+error[E0063]: missing field `y` in initializer of `Enum`
+ --> $DIR/issue-79593.rs:23:5
+ |
+LL | foo::Enum::Variant { x: () };
+ | ^^^^^^^^^^^^^^^^^^ missing `y`
+
+error[E0063]: missing fields `x` and `y` in initializer of `Enum`
+ --> $DIR/issue-79593.rs:25:5
+ |
+LL | foo::Enum::Variant { };
+ | ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | Some(x) => { return x.try_into().unwrap() },
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/span-preservation.rs:33:22
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/region-object-lifetime-in-coercion.rs:23:5
|
LL | Box::new(v)
|
LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
LL | box v as Box<dyn SomeTrait + 'a>
|
LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/regions-creating-enums4.rs:7:5
|
LL | Ast::Add(x, y)
|
LL | with(|o| o)
| ^^^^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/regions-ret-borrowed-1.rs:10:14
|
LL | with(|o| o)
|
LL | with(|o| o)
| ^^^^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/regions-ret-borrowed.rs:13:14
|
LL | with(|o| o)
|
LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
--> $DIR/regions-trait-object-subtyping.rs:15:5
|
LL | x
help: change the type of the numeric literal from `u8` to `usize`
|
LL | let f = [0; 4usize];
- | ~~~~~~
+ | ~~~~~
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:31:17
--- /dev/null
+// Regression test for the ICE described in #87496.
+
+// check-pass
+
+#[repr(transparent)]
+struct TransparentCustomZst(());
+extern "C" {
+ fn good17(p: TransparentCustomZst);
+ //~^ WARNING: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+}
+
+fn main() {}
--- /dev/null
+warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+ --> $DIR/repr-transparent-issue-87496.rs:8:18
+ |
+LL | fn good17(p: TransparentCustomZst);
+ | ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: `#[warn(improper_ctypes)]` on by default
+ = note: this struct contains only zero-sized fields
+note: the type is defined here
+ --> $DIR/repr-transparent-issue-87496.rs:6:1
+ |
+LL | struct TransparentCustomZst(());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
--- /dev/null
+mod foo {
+ pub struct Bx(());
+}
+
+mod bar {
+ use foo::Bx;
+
+ fn foo() {
+ Bx(());
+ //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
+ }
+}
+
+mod baz {
+ fn foo() {
+ Bx(());
+ //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425]
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0423]: cannot initialize a tuple struct which contains private fields
+ --> $DIR/issue-42944.rs:9:9
+ |
+LL | Bx(());
+ | ^^
+ |
+note: constructor is not visible here due to private fields
+ --> $DIR/issue-42944.rs:2:19
+ |
+LL | pub struct Bx(());
+ | ^^ private field
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
+ --> $DIR/issue-42944.rs:16:9
+ |
+LL | Bx(());
+ | ^^ not found in this scope
+ |
+help: consider importing this tuple struct
+ |
+LL | use foo::Bx;
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0425.
+For more information about an error, try `rustc --explain E0423`.
--- /dev/null
+struct A;
+
+impl A {
+//~^ NOTE `Self` type implicitly declared here, by this `impl`
+ fn banana(&mut self) {
+ fn peach(this: &Self) {
+ //~^ ERROR can't use generic parameters from outer function
+ //~| NOTE use of generic parameter from outer function
+ //~| NOTE use a type here instead
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/use-self-in-inner-fn.rs:6:25
+ |
+LL | impl A {
+ | ---- `Self` type implicitly declared here, by this `impl`
+...
+LL | fn peach(this: &Self) {
+ | ^^^^
+ | |
+ | use of generic parameter from outer function
+ | use a type here instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
pub enum NonExhaustiveEnum {
Unit,
Tuple(u32),
- Struct { field: u32 }
+ Struct { field: u32 },
+}
+
+#[non_exhaustive]
+pub enum NestedNonExhaustive {
+ A(NonExhaustiveEnum),
+ B,
+ C,
}
#[non_exhaustive]
pub enum EmptyNonExhaustiveEnum {}
+
+pub enum VariantNonExhaustive {
+ #[non_exhaustive]
+ Bar {
+ x: u32,
+ y: u64,
+ },
+ Baz(u32, u16),
+}
+
+#[non_exhaustive]
+pub enum NonExhaustiveSingleVariant {
+ A(bool),
+}
+#[derive(Default)]
#[non_exhaustive]
pub struct NormalStruct {
pub first_field: u16,
pub struct FunctionalRecord {
pub first_field: u16,
pub second_field: u16,
- pub third_field: bool
+ pub third_field: bool,
}
impl Default for FunctionalRecord {
FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
}
}
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NestedStruct {
+ pub foo: u16,
+ pub bar: NormalStruct,
+}
--- /dev/null
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+// aux-build:enums.rs
+extern crate enums;
+
+// aux-build:structs.rs
+extern crate structs;
+
+use enums::{
+ EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
+ VariantNonExhaustive,
+};
+use structs::{FunctionalRecord, NestedStruct, NormalStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+ a: u8,
+ b: usize,
+ c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+ A,
+ B,
+ C,
+}
+
+fn main() {
+ let enumeration = Bar::A;
+
+ // Ok: this is a crate local non_exhaustive enum
+ match enumeration {
+ Bar::A => {}
+ Bar::B => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ let non_enum = NonExhaustiveEnum::Unit;
+
+ // Ok: without the attribute
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ match non_enum {
+ NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ let x = 5;
+ match non_enum {
+ NonExhaustiveEnum::Unit if x > 10 => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: all covered and not `unreachable-patterns`
+ #[deny(unreachable_patterns)]
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NestedNonExhaustive::B {
+ NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+ NestedNonExhaustive::A(_) => {}
+ NestedNonExhaustive::B => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+ //~^^^^^ some variants are not matched explicitly
+
+ // The io::ErrorKind has many `unstable` fields how do they interact with this
+ // lint
+ #[deny(non_exhaustive_omitted_patterns)]
+ match std::io::ErrorKind::Other {
+ std::io::ErrorKind::NotFound => {}
+ std::io::ErrorKind::PermissionDenied => {}
+ std::io::ErrorKind::ConnectionRefused => {}
+ std::io::ErrorKind::ConnectionReset => {}
+ std::io::ErrorKind::ConnectionAborted => {}
+ std::io::ErrorKind::NotConnected => {}
+ std::io::ErrorKind::AddrInUse => {}
+ std::io::ErrorKind::AddrNotAvailable => {}
+ std::io::ErrorKind::BrokenPipe => {}
+ std::io::ErrorKind::AlreadyExists => {}
+ std::io::ErrorKind::WouldBlock => {}
+ std::io::ErrorKind::InvalidInput => {}
+ std::io::ErrorKind::InvalidData => {}
+ std::io::ErrorKind::TimedOut => {}
+ std::io::ErrorKind::WriteZero => {}
+ std::io::ErrorKind::Interrupted => {}
+ std::io::ErrorKind::Other => {}
+ std::io::ErrorKind::UnexpectedEof => {}
+ std::io::ErrorKind::Unsupported => {}
+ std::io::ErrorKind::OutOfMemory => {}
+ // All stable variants are above and unstable in `_`
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ match VariantNonExhaustive::Baz(1, 2) {
+ VariantNonExhaustive::Baz(_, _) => {}
+ VariantNonExhaustive::Bar { x, .. } => {}
+ }
+ //~^^ some fields are not explicitly listed
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ //~^ some fields are not explicitly listed
+
+ // Ok: this is local
+ #[warn(non_exhaustive_omitted_patterns)]
+ let Foo { a, b, .. } = Foo::default();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ //~^ some fields are not explicitly listed
+ //~^^ some fields are not explicitly listed
+
+ // Ok: because this only has 1 variant
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ NonExhaustiveSingleVariant::A(true) => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: we don't lint on `if let` expressions
+ #[deny(non_exhaustive_omitted_patterns)]
+ if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+}
--- /dev/null
+warning: some fields are not explicitly listed
+ --> $DIR/reachable-patterns.rs:127:9
+ |
+LL | VariantNonExhaustive::Bar { x, .. } => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:124:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+ --> $DIR/reachable-patterns.rs:132:9
+ |
+LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:131:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+ --> $DIR/reachable-patterns.rs:140:29
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:139:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+ --> $DIR/reachable-patterns.rs:140:9
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:54:9
+ |
+LL | _ => {}
+ | ^ pattern `Struct { .. }` not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:53:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:61:9
+ |
+LL | _ => {}
+ | ^ pattern `Tuple(_)` not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:60:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:71:9
+ |
+LL | _ => {}
+ | ^ pattern `Unit` not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:70:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:88:32
+ |
+LL | NestedNonExhaustive::A(_) => {}
+ | ^ patterns `Tuple(_)` and `Struct { .. }` not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:85:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:90:9
+ |
+LL | _ => {}
+ | ^ pattern `C` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:120:9
+ |
+LL | _ => {}
+ | ^ patterns `HostUnreachable`, `NetworkUnreachable`, `NetworkDown` and 18 more not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:97:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `ErrorKind` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/reachable-patterns.rs:153:9
+ |
+LL | _ => {}
+ | ^ pattern `A(_)` not covered
+ |
+note: the lint level is defined here
+ --> $DIR/reachable-patterns.rs:151:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: aborting due to 7 previous errors; 4 warnings emitted
+
LL | let ts_explicit = structs::TupleStruct(640, 480);
| ^^^^^^^^^^^ private tuple struct constructor
|
- ::: $DIR/auxiliary/structs.rs:11:24
+ ::: $DIR/auxiliary/structs.rs:12:24
|
LL | pub struct TupleStruct(pub u16, pub u16);
| ---------------- a constructor is private if any of the fields is private
|
note: the tuple struct constructor `TupleStruct` is defined here
- --> $DIR/auxiliary/structs.rs:11:1
+ --> $DIR/auxiliary/structs.rs:12:1
|
LL | pub struct TupleStruct(pub u16, pub u16);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^ private unit struct
|
note: the unit struct `UnitStruct` is defined here
- --> $DIR/auxiliary/structs.rs:8:1
+ --> $DIR/auxiliary/structs.rs:9:1
|
LL | pub struct UnitStruct;
| ^^^^^^^^^^^^^^^^^^^^^^
help: if this is a `self` type, give it a parameter name
|
LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
- | ~~~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
- | ~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); }
- | ~~~~~~
+ | ++
error: aborting due to previous error
// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
// bound.
-// const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
-// FIXME(fee1-dead)^ why should the order matter here?
-const fn equals_self<T: ~const PartialEq + PartialEq>(t: &T) -> bool {
+const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
*t == *t
}
-pub const EQ: bool = equals_self(&S);
+trait A: PartialEq {}
+impl<T: PartialEq> A for T {}
+
+const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+ *t == *t
+}
+
+pub const EQ: bool = equals_self(&S) && equals_self2(&S);
fn main() {}
--> $DIR/call-generic-method-nonconst.rs:19:34
|
LL | pub const EQ: bool = equals_self(&S);
- | ^^ no implementation for `S == S`
+ | ----------- ^^ no implementation for `S == S`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `PartialEq` is not implemented for `S`
note: required by a bound in `equals_self`
--- /dev/null
+error: `~const` is not allowed here
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+ --> $DIR/const-drop-fail.rs:45:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:36:19
+ |
+LL | const fn check<T: ~const Drop>(_: T) {}
+ | ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+ --> $DIR/const-drop-fail.rs:47:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstImplWithDropGlue(NonTrivialDrop),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:36:19
+ |
+LL | const fn check<T: ~const Drop>(_: T) {}
+ | ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+ --> $DIR/const-drop-fail.rs:49:5
+ |
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+ |
+note: required by `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:1
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+ --> $DIR/const-drop-fail.rs:49:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+ |
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(const_fn_trait_bound)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::PhantomData;
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+ fn drop(&mut self) {
+ println!("Non trivial drop");
+ }
+}
+
+struct ConstImplWithDropGlue(NonTrivialDrop);
+
+impl const Drop for ConstImplWithDropGlue {
+ fn drop(&mut self) {}
+}
+
+trait A { fn a() { println!("A"); } }
+
+impl A for NonTrivialDrop {}
+
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+//~^ ERROR `~const` is not allowed
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+ fn drop(&mut self) {
+ T::a();
+ }
+}
+
+const fn check<T: ~const Drop>(_: T) {}
+
+macro_rules! check_all {
+ ($($exp:expr),*$(,)?) => {$(
+ const _: () = check($exp);
+ )*};
+}
+
+check_all! {
+ NonTrivialDrop,
+ //~^ ERROR the trait bound
+ ConstImplWithDropGlue(NonTrivialDrop),
+ //~^ ERROR the trait bound
+ ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ //~^ ERROR the trait bound
+ //~| ERROR the trait bound
+}
+
+fn main() {}
--- /dev/null
+error: `~const` is not allowed here
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^
+ |
+ = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+ --> $DIR/const-drop-fail.rs:45:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | NonTrivialDrop,
+ | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:36:19
+ |
+LL | const fn check<T: ~const Drop>(_: T) {}
+ | ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+ --> $DIR/const-drop-fail.rs:47:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstImplWithDropGlue(NonTrivialDrop),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+ |
+note: required by a bound in `check`
+ --> $DIR/const-drop-fail.rs:36:19
+ |
+LL | const fn check<T: ~const Drop>(_: T) {}
+ | ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+ --> $DIR/const-drop-fail.rs:49:5
+ |
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+ |
+note: required by `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:1
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+ --> $DIR/const-drop-fail.rs:49:5
+ |
+LL | const _: () = check($exp);
+ | ----- required by a bound introduced by this call
+...
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+ |
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// run-pass
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+#![feature(const_mut_refs)]
+#![feature(const_panic)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+ fn drop(&mut self) {
+ *self.0 += 1;
+ }
+}
+
+const fn a<T: ~const Drop>(_: T) {}
+
+const fn b() -> u8 {
+ let mut c = 0;
+ let _ = S(&mut c);
+ a(S(&mut c));
+ c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+ ($($exp:expr),*$(,)?) => {
+ $(
+ const _: () = a($exp);
+ )*
+ }
+}
+
+#[allow(dead_code)]
+mod t {
+ pub struct Foo;
+ pub enum Bar { A }
+ pub fn foo() {}
+ pub struct ConstDrop;
+
+ impl const Drop for ConstDrop {
+ fn drop(&mut self) {}
+ }
+
+ pub struct HasConstDrop(pub ConstDrop);
+ pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+}
+
+use t::*;
+
+implements_const_drop! {
+ 1u8,
+ 2,
+ 3.0,
+ Foo,
+ Bar::A,
+ foo,
+ ConstDrop,
+ HasConstDrop(ConstDrop),
+ TrivialFields(1, 2, 3, 4),
+ &1,
+ &1 as *const i32,
+}
+
+fn main() {
+ struct HasDropGlue(Box<u8>);
+ struct HasDropImpl;
+ impl Drop for HasDropImpl {
+ fn drop(&mut self) {
+ println!("not trivial drop");
+ }
+ }
+
+ // These types should pass because ~const in a non-const context should have no effect.
+ a(HasDropGlue(Box::new(0)));
+ a(HasDropImpl);
+
+ assert_eq!(C, 2);
+}
--- /dev/null
+// check-pass
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+struct S;
+
+trait A {}
+trait B {}
+
+impl const A for S {}
+impl const B for S {}
+
+impl S {
+ const fn a<T: ~const A>() where T: ~const B {
+
+ }
+}
+
+const _: () = S::a::<S>();
+
+fn main() {}
--> $DIR/fn-traits.rs:24:10
|
LL | call(foo);
- | ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+ | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<()>` is not implemented for `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
--> $DIR/fn-traits.rs:25:14
|
LL | call_mut(foo);
- | ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+ | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
--> $DIR/fn-traits.rs:26:15
|
LL | call_once(foo);
- | ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+ | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
--> $DIR/fn-traits.rs:28:10
|
LL | call(foo_unsafe);
- | ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | ---- ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
--> $DIR/fn-traits.rs:30:14
|
LL | call_mut(foo_unsafe);
- | ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | -------- ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
--> $DIR/fn-traits.rs:32:15
|
LL | call_once(foo_unsafe);
- | ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | --------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
= note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
// run-pass
#![feature(box_syntax)]
+#![allow(dead_code)]
#[derive(Copy, Clone)]
struct Foo {
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | let _: i32 = (22_i64 >> 1_i32).try_into().unwrap();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | + +++++++++++++++++++++
error: aborting due to 4 previous errors
--- /dev/null
+// build-fail
+
+// Test that the simd_shuffle intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+extern "platform-intrinsic" {
+ fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+fn main() {
+ const I: [u32; 2] = [0; 2];
+ const I2: [f32; 2] = [0.; 2];
+ let v = Simd::<u32, 4>([0; 4]);
+
+ unsafe {
+ let _: Simd<u32, 2> = simd_shuffle(v, v, I);
+
+ let _: Simd<u32, 4> = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+ let _: Simd<f32, 2> = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+ let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+ }
+}
--- /dev/null
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4_usize>` with length 4
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:24:31
+ |
+LL | let _: Simd<u32, 4> = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4_usize>`), found `Simd<f32, 2_usize>` with element type `f32`
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:27:31
+ |
+LL | let _: Simd<f32, 2> = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]`
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:30:31
+ |
+LL | let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
--- /dev/null
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+ fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+trait Shuffle<const N: usize> {
+ const I: [u32; N];
+
+ unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N> {
+ simd_shuffle(a, b, Self::I)
+ }
+}
+
+fn main() {
+ struct I1;
+ impl Shuffle<4> for I1 {
+ const I: [u32; 4] = [0, 2, 4, 6];
+ }
+
+ struct I2;
+ impl Shuffle<2> for I2 {
+ const I: [u32; 2] = [1, 5];
+ }
+
+ let a = Simd::<u8, 4>([0, 1, 2, 3]);
+ let b = Simd::<u8, 4>([4, 5, 6, 7]);
+ unsafe {
+ let x: Simd<u8, 4> = I1.shuffle(a, b);
+ assert_eq!(x.0, [0, 2, 4, 6]);
+
+ let y: Simd<u8, 2> = I2.shuffle(a, b);
+ assert_eq!(y.0, [1, 5]);
+ }
+}
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
+
+ extern "platform-intrinsic" {
+ fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+ }
+ let v = u8x2(0, 0);
+ const I: [u32; 2] = [4, 4];
+ unsafe {
+ let _: u8x2 = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+ }
}
|
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 6 previous errors
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
+ --> $DIR/shuffle-not-out-of-bounds.rs:198:23
+ |
+LL | let _: u8x2 = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0511`.
--- /dev/null
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+ fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+ const I1: [u32; 4] = [0, 2, 4, 6];
+ const I2: [u32; 2] = [1, 5];
+ let a = Simd::<u8, 4>([0, 1, 2, 3]);
+ let b = Simd::<u8, 4>([4, 5, 6, 7]);
+ unsafe {
+ let x: Simd<u8, 4> = simd_shuffle(a, b, I1);
+ assert_eq!(x.0, [0, 2, 4, 6]);
+
+ let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
+ assert_eq!(y.0, [1, 5]);
+ }
+}
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
|
-LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
- | ----- captured outer variable
+LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
+ | ----- captured outer variable
...
-LL | foo(f);
- | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
+LL | f(Box::new(|a| {
+ | ________________-
+LL | |
+LL | | foo(f);
+ | | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
+LL | |
+LL | | }), 3);
+ | |_____- captured by this `FnMut` closure
error[E0505]: cannot move out of `f` because it is borrowed
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16
help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: Option<i32>, String) {}
- | ~~~~~~~~~~~~
+ | +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(_: Option<i32>, String) {}
- | ~~~~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/issue-34264.rs:1:27
help: if this is a parameter name, give it a type
|
LL | fn foo(Option<i32>, String: TypeName) {}
- | ~~~~~~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(Option<i32>, _: String) {}
- | ~~~~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `,`
--> $DIR/issue-34264.rs:3:9
help: if this is a `self` type, give it a parameter name
|
LL | fn bar(self: x, y: usize) {}
- | ~~~~~~~
+ | +++++
help: if this is a parameter name, give it a type
|
LL | fn bar(x: TypeName, y: usize) {}
- | ~~~~~~~~~~~
+ | ++++++++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn bar(_: x, y: usize) {}
- | ~~~~
+ | ++
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/issue-34264.rs:7:5
--- /dev/null
+// check-pass
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+fn main() {}
+
+pub trait Alpha<T> { }
+
+pub trait Beta {
+ type Event;
+}
+
+pub trait Delta {
+ type Handle;
+ fn process(&self);
+}
+
+pub struct Parent<A, T>(A, T);
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle>,
+ T: Delta,
+ T::Handle: Beta<Event = <Handle as Beta>::Event> {
+ type Handle = Handle;
+ default fn process(&self) {
+ unimplemented!()
+ }
+}
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle> + Alpha<Handle>,
+ T: Delta,
+ T::Handle: Beta<Event = <Handle as Beta>::Event> {
+ fn process(&self) {
+ unimplemented!()
+ }
+}
+
+pub struct Handle;
+
+impl Beta for Handle {
+ type Event = ();
+}
--- /dev/null
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-35376.rs:2:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
--- /dev/null
+// build-pass
+#![allow(dead_code)]
+
+struct A {
+ a: &'static (),
+}
+
+static B: &'static A = &A { a: &() };
+static C: &'static A = &B;
+
+fn main() {}
--> $DIR/str-idx.rs:4:19
|
LL | let _ = s.get(4);
- | ^ string indices are ranges of `usize`
+ | --- ^ string indices are ranges of `usize`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
= note: you can use `.chars().nth()` or `.bytes().nth()`
--> $DIR/str-idx.rs:5:29
|
LL | let _ = s.get_unchecked(4);
- | ^ string indices are ranges of `usize`
+ | ------------- ^ string indices are ranges of `usize`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
= note: you can use `.chars().nth()` or `.bytes().nth()`
--> $DIR/str-mut-idx.rs:9:15
|
LL | s.get_mut(1);
- | ^ string indices are ranges of `usize`
+ | ------- ^ string indices are ranges of `usize`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
= note: you can use `.chars().nth()` or `.bytes().nth()`
--> $DIR/str-mut-idx.rs:11:25
|
LL | s.get_unchecked_mut(1);
- | ^ string indices are ranges of `usize`
+ | ----------------- ^ string indices are ranges of `usize`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
= note: you can use `.chars().nth()` or `.bytes().nth()`
// run-pass
#![allow(non_camel_case_types)]
+#![allow(dead_code)]
trait noisy {
fn speak(&mut self) -> isize;
// run-pass
#![allow(non_camel_case_types)]
+#![allow(dead_code)]
trait noisy {
fn speak(&mut self);
// run-pass
+
+#![allow(dead_code)]
+
#[derive(Debug)]
struct Foo {
x: isize,
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+// Check that constant ADTs are codegened OK, part k of N.
+
+enum Bar {
+ C
+}
+
+enum Foo {
+ A {},
+ B {
+ y: usize,
+ z: Bar
+ },
+}
+
+const LIST: [(usize, Foo); 2] = [
+ (51, Foo::B { y: 42, z: Bar::C }),
+ (52, Foo::B { y: 45, z: Bar::C }),
+];
+
+pub fn main() {
+ match LIST {
+ [
+ (51, Foo::B { y: 42, z: Bar::C }),
+ (52, Foo::B { y: 45, z: Bar::C })
+ ] => {}
+ _ => {
+ // I would want to print the enum here, but if
+ // the discriminant is garbage this causes an
+ // `unreachable` and silent process exit.
+ panic!("trivial match failed")
+ }
+ }
+}
// run-pass
#![allow(non_camel_case_types)]
+#![allow(dead_code)]
#[derive(Debug)]
enum a_tag {
| --- consider calling this function
...
LL | bar(foo);
- | ^^^ `fn() -> impl Future {foo}` is not a future
+ | --- ^^^ `fn() -> impl Future {foo}` is not a future
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `fn() -> impl Future {foo}`
note: required by a bound in `bar`
LL | let async_closure = async || ();
| -------- consider calling this closure
LL | bar(async_closure);
- | ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+ | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
note: required by a bound in `bar`
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:28:21
|
-LL | let x = X(Y);
- | - captured outer variable
+LL | let x = X(Y);
+ | - captured outer variable
...
-LL | let X(_t) = x;
- | -- ^ help: consider borrowing here: `&x`
- | |
- | data moved here
- | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+ | | -- ^ help: consider borrowing here: `&x`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | |
+LL | |
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:32:34
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | if let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+LL | |
+LL | | if let Either::One(_t) = e { }
+ | | -- ^ help: consider borrowing here: `&e`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:36:37
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | while let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | while let Either::One(_t) = e { }
+ | | -- ^ help: consider borrowing here: `&e`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:40:15
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | match e {
- | ^ help: consider borrowing here: `&e`
-...
-LL | Either::One(_t)
- | --
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match e {
+ | | ^ help: consider borrowing here: `&e`
+... |
+LL | | Either::One(_t)
+ | | --
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:47:15
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
-...
-LL | match e {
- | ^ help: consider borrowing here: `&e`
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | Either::One(_t) => (),
- | --
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match e {
+ | | ^ help: consider borrowing here: `&e`
+... |
+LL | | Either::One(_t) => (),
+ | | --
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:56:25
|
-LL | let x = X(Y);
- | - captured outer variable
+LL | let x = X(Y);
+ | - captured outer variable
...
-LL | let X(mut _t) = x;
- | ------ ^ help: consider borrowing here: `&x`
- | |
- | data moved here
- | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | let X(mut _t) = x;
+ | | ------ ^ help: consider borrowing here: `&x`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:60:38
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | if let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | if let Either::One(mut _t) = em { }
+ | | ------ ^^ help: consider borrowing here: `&em`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:64:41
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | while let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | while let Either::One(mut _t) = em { }
+ | | ------ ^^ help: consider borrowing here: `&em`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:68:15
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
-...
-LL | match em {
- | ^^ help: consider borrowing here: `&em`
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | Either::One(mut _t)
- | ------
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match em {
+ | | ^^ help: consider borrowing here: `&em`
+... |
+LL | | Either::One(mut _t)
+ | | ------
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
--> $DIR/move-into-closure.rs:75:15
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | match em {
- | ^^ help: consider borrowing here: `&em`
-...
-LL | Either::One(mut _t) => (),
- | ------
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fn(|| {
+ | ________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match em {
+ | | ^^ help: consider borrowing here: `&em`
+... |
+LL | | Either::One(mut _t) => (),
+ | | ------
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `Fn` closure
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:95:21
|
-LL | let x = X(Y);
- | - captured outer variable
+LL | let x = X(Y);
+ | - captured outer variable
...
-LL | let X(_t) = x;
- | -- ^ help: consider borrowing here: `&x`
- | |
- | data moved here
- | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+ | | -- ^ help: consider borrowing here: `&x`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | |
+LL | |
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:99:34
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | if let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+LL | |
+LL | | if let Either::One(_t) = e { }
+ | | -- ^ help: consider borrowing here: `&e`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:103:37
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | while let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | while let Either::One(_t) = e { }
+ | | -- ^ help: consider borrowing here: `&e`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:107:15
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
-...
-LL | match e {
- | ^ help: consider borrowing here: `&e`
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | Either::One(_t)
- | --
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match e {
+ | | ^ help: consider borrowing here: `&e`
+... |
+LL | | Either::One(_t)
+ | | --
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:114:15
|
-LL | let e = Either::One(X(Y));
- | - captured outer variable
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
...
-LL | match e {
- | ^ help: consider borrowing here: `&e`
-...
-LL | Either::One(_t) => (),
- | --
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match e {
+ | | ^ help: consider borrowing here: `&e`
+... |
+LL | | Either::One(_t) => (),
+ | | --
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:123:25
|
-LL | let x = X(Y);
- | - captured outer variable
+LL | let x = X(Y);
+ | - captured outer variable
...
-LL | let X(mut _t) = x;
- | ------ ^ help: consider borrowing here: `&x`
- | |
- | data moved here
- | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | let X(mut _t) = x;
+ | | ------ ^ help: consider borrowing here: `&x`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:127:38
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | if let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | if let Either::One(mut _t) = em { }
+ | | ------ ^^ help: consider borrowing here: `&em`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:131:41
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | while let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | while let Either::One(mut _t) = em { }
+ | | ------ ^^ help: consider borrowing here: `&em`
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:135:15
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
-...
-LL | match em {
- | ^^ help: consider borrowing here: `&em`
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | Either::One(mut _t)
- | ------
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match em {
+ | | ^^ help: consider borrowing here: `&em`
+... |
+LL | | Either::One(mut _t)
+ | | ------
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:142:15
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | match em {
- | ^^ help: consider borrowing here: `&em`
-...
-LL | Either::One(mut _t) => (),
- | ------
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match em {
+ | | ^^ help: consider borrowing here: `&em`
+... |
+LL | | Either::One(mut _t) => (),
+ | | ------
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
--> $DIR/move-into-closure.rs:150:15
|
-LL | let mut em = Either::One(X(Y));
- | ------ captured outer variable
-...
-LL | match em {
- | ^^ help: consider borrowing here: `&em`
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
...
-LL | Either::One(mut _t) => (),
- | ------
- | |
- | data moved here
- | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL | consume_fnmut(|| {
+ | ___________________-
+LL | | let X(_t) = x;
+LL | |
+LL | |
+... |
+LL | | match em {
+ | | ^^ help: consider borrowing here: `&em`
+... |
+LL | | Either::One(mut _t) => (),
+ | | ------
+ | | |
+ | | data moved here
+ | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+... |
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error: aborting due to 21 previous errors
| --- consider calling this function
...
LL | bar(foo);
- | ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+ | --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `bar`
--> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
LL | let closure = || S;
| -- consider calling this closure
LL | bar(closure);
- | ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+ | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `bar`
--> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
--> $DIR/imm-ref-trait-object-literal.rs:12:7
|
LL | foo(&s);
- | ^^ the trait `Trait` is not implemented for `&S`
+ | --- ^^ the trait `Trait` is not implemented for `&S`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<&'a mut S as Trait>
--> $DIR/imm-ref-trait-object-literal.rs:13:7
|
LL | foo(s);
- | ^
- | |
- | expected an implementor of trait `Trait`
- | help: consider mutably borrowing here: `&mut s`
+ | --- ^
+ | | |
+ | | expected an implementor of trait `Trait`
+ | | help: consider mutably borrowing here: `&mut s`
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/imm-ref-trait-object-literal.rs:7:11
--> $DIR/impl-trait-with-missing-bounds.rs:14:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/impl-trait-with-missing-bounds.rs:22:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/impl-trait-with-missing-bounds.rs:30:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/impl-trait-with-missing-bounds.rs:37:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator + std::fmt::Debug as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/impl-trait-with-missing-bounds.rs:6:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/impl-trait-with-missing-bounds.rs:45:13
|
LL | qux(constraint);
- | ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
note: required by a bound in `qux`
--> $DIR/issue-62843.rs:4:32
|
LL | println!("{:?}", line.find(pattern));
- | ^^^^^^^
- | |
- | expected an implementor of trait `Pattern<'_>`
- | help: consider borrowing here: `&pattern`
+ | ---- ^^^^^^^
+ | | |
+ | | expected an implementor of trait `Pattern<'_>`
+ | | help: consider borrowing here: `&pattern`
+ | required by a bound introduced by this call
|
= note: the trait bound `String: Pattern<'_>` is not satisfied
= note: required because of the requirements on the impl of `Pattern<'_>` for `String`
help: if this is a `self` type, give it a parameter name
|
LL | pub fn foo(self: Box<Self>) { }
- | ~~~~~~~~~
+ | +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | pub fn foo(_: Box<Self>) { }
- | ~~~~~~
+ | ++
error: expected one of `:`, `@`, or `|`, found `<`
--> $DIR/issue-64252-self-type.rs:10:15
help: if this is a `self` type, give it a parameter name
|
LL | fn bar(self: Box<Self>) { }
- | ~~~~~~~~~
+ | +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn bar(_: Box<Self>) { }
- | ~~~~~~
+ | ++
error: aborting due to 2 previous errors
--> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20
|
LL | assert_is_send(&bar);
- | ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
note: required by a bound in `assert_is_send`
--> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20
|
LL | assert_is_send(&bar);
- | ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
note: required by a bound in `assert_is_send`
--> $DIR/issue-84973-2.rs:11:9
|
LL | foo(a);
- | ^
- | |
- | expected an implementor of trait `Tr`
- | help: consider mutably borrowing here: `&mut a`
+ | --- ^
+ | | |
+ | | expected an implementor of trait `Tr`
+ | | help: consider mutably borrowing here: `&mut a`
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/issue-84973-2.rs:7:11
let ref_cl: &dyn Fn() -> () = &cl;
f_sized(*ref_cl);
//~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
- //~| ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
use std::rc::Rc;
let rc = Rc::new(0);
--> $DIR/issue-84973-blacklist.rs:15:12
|
LL | f_copy("".to_string());
- | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f_copy`
--> $DIR/issue-84973-blacklist.rs:6:14
--> $DIR/issue-84973-blacklist.rs:16:13
|
LL | f_clone(S);
- | ^ the trait `Clone` is not implemented for `S`
+ | ------- ^ the trait `Clone` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f_clone`
--> $DIR/issue-84973-blacklist.rs:7:15
--> $DIR/issue-84973-blacklist.rs:22:13
|
LL | f_sized(*ref_cl);
- | ^^^^^^^ doesn't have a size known at compile-time
+ | ------- ^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Fn()`
note: required by a bound in `f_sized`
| ^ required by this bound in `f_sized`
error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
- --> $DIR/issue-84973-blacklist.rs:28:12
+ --> $DIR/issue-84973-blacklist.rs:27:12
|
LL | f_send(rc);
- | ^^ `Rc<{integer}>` cannot be sent between threads safely
+ | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `Rc<{integer}>`
note: required by a bound in `f_send`
LL | fn f_send<T: Send>(t: T) {}
| ^^^^ required by this bound in `f_send`
-error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time
- --> $DIR/issue-84973-blacklist.rs:22:5
- |
-LL | f_sized(*ref_cl);
- | ^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `dyn Fn()`
- = note: all function arguments must have a statically known size
- = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.
--> $DIR/issue-84973-negative.rs:10:9
|
LL | bar(a);
- | ^ the trait `Tr` is not implemented for `i32`
+ | --- ^ the trait `Tr` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `bar`
--> $DIR/issue-84973-negative.rs:5:11
--> $DIR/issue-84973-negative.rs:11:9
|
LL | bar(b);
- | ^
- | |
- | expected an implementor of trait `Tr`
- | help: consider borrowing here: `&b`
+ | --- ^
+ | | |
+ | | expected an implementor of trait `Tr`
+ | | help: consider borrowing here: `&b`
+ | required by a bound introduced by this call
|
note: required by a bound in `bar`
--> $DIR/issue-84973-negative.rs:5:11
--> $DIR/issue-84973.rs:6:24
|
LL | let o = Other::new(f);
- | ^
- | |
- | expected an implementor of trait `SomeTrait`
- | help: consider borrowing here: `&f`
+ | ---------- ^
+ | | |
+ | | expected an implementor of trait `SomeTrait`
+ | | help: consider borrowing here: `&f`
+ | required by a bound introduced by this call
|
note: required by `Other::<'a, G>::new`
--> $DIR/issue-84973.rs:27:5
--> $DIR/mut-borrow-needed-by-trait.rs:17:29
|
LL | let fp = BufWriter::new(fp);
- | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+ | -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+ | |
+ | required by a bound introduced by this call
|
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by `BufWriter::<W>::new`
LL | fn bar(x: &dyn Trait) {}
| ^^^^^^^^^ `Trait` cannot be made into an object
|
- = help: consider moving `baz` to another trait
- = help: consider moving `bat` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/object-unsafe-trait-references-self.rs:2:22
|
| ^^^^ ...because method `baz` references the `Self` type in this parameter
LL | fn bat(&self) -> Self {}
| ^^^^ ...because method `bat` references the `Self` type in its return type
+ = help: consider moving `baz` to another trait
+ = help: consider moving `bat` to another trait
error[E0038]: the trait `Other` cannot be made into an object
--> $DIR/object-unsafe-trait-references-self.rs:10:12
error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
--> $DIR/option-content-move2.rs:9:9
|
-LL | let mut var = None;
- | ------- captured outer variable
-...
-LL | move || {
- | ^^^^^^^ move out of `var` occurs here
-LL |
-LL | var = Some(NotCopyable);
- | ---
- | |
- | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
- | move occurs due to use in closure
+LL | let mut var = None;
+ | ------- captured outer variable
+LL | func(|| {
+ | __________-
+LL | | // Shouldn't suggest `move ||.as_ref()` here
+LL | | move || {
+ | | ^^^^^^^ move out of `var` occurs here
+LL | |
+LL | | var = Some(NotCopyable);
+ | | ---
+ | | |
+ | | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
+ | | move occurs due to use in closure
+LL | | }
+LL | | });
+ | |_____- captured by this `FnMut` closure
error: aborting due to previous error
--> $DIR/restrict-type-argument.rs:4:13
|
LL | is_send(val);
- | ^^^ `impl Sync` cannot be sent between threads safely
+ | ------- ^^^ `impl Sync` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--> $DIR/restrict-type-argument.rs:8:13
|
LL | is_send(val);
- | ^^^ `S` cannot be sent between threads safely
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--> $DIR/restrict-type-argument.rs:12:13
|
LL | is_send(val);
- | ^^^ `S` cannot be sent between threads safely
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--> $DIR/restrict-type-argument.rs:20:13
|
LL | is_send(val);
- | ^^^ `S` cannot be sent between threads safely
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--> $DIR/restrict-type-argument.rs:24:13
|
LL | is_send(val);
- | ^^^ `S` cannot be sent between threads safely
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--> $DIR/restrict-type-argument.rs:28:13
|
LL | is_send(val);
- | ^^^ `S` cannot be sent between threads safely
+ | ------- ^^^ `S` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `is_send`
--> $DIR/restrict-type-argument.rs:1:15
--- /dev/null
+fn main() {
+ let v = vec![1i32, 2, 3];
+ for _ in v[1..] {
+ //~^ ERROR [i32]` is not an iterator [E0277]
+ //~^^ ERROR known at compilation time
+ }
+ struct K {
+ n: i32,
+ }
+ let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }];
+ for i2 in v2[1..] {
+ //~^ ERROR [K]` is not an iterator [E0277]
+ //~^^ ERROR known at compilation time
+ i2.n = 2;
+ }
+}
--- /dev/null
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+ --> $DIR/slice-issue-87994.rs:3:12
+ |
+LL | for _ in v[1..] {
+ | ^^^^^^
+ | |
+ | expected an implementor of trait `IntoIterator`
+ | help: consider borrowing here: `&v[1..]`
+ |
+ = note: the trait bound `[i32]: IntoIterator` is not satisfied
+ = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+ |
+LL | fn into_iter(self) -> Self::IntoIter;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[i32]` is not an iterator
+ --> $DIR/slice-issue-87994.rs:3:12
+ |
+LL | for _ in v[1..] {
+ | ^^^^^^
+ | |
+ | expected an implementor of trait `IntoIterator`
+ | help: consider borrowing here: `&v[1..]`
+ |
+ = note: the trait bound `[i32]: IntoIterator` is not satisfied
+ = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+ |
+LL | fn into_iter(self) -> Self::IntoIter;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+ --> $DIR/slice-issue-87994.rs:11:13
+ |
+LL | for i2 in v2[1..] {
+ | ^^^^^^^
+ | |
+ | expected an implementor of trait `IntoIterator`
+ | help: consider borrowing here: `&v2[1..]`
+ |
+ = note: the trait bound `[K]: IntoIterator` is not satisfied
+ = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+ |
+LL | fn into_iter(self) -> Self::IntoIter;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[K]` is not an iterator
+ --> $DIR/slice-issue-87994.rs:11:13
+ |
+LL | for i2 in v2[1..] {
+ | ^^^^^^^
+ | |
+ | expected an implementor of trait `IntoIterator`
+ | help: consider borrowing here: `&v2[1..]`
+ |
+ = note: the trait bound `[K]: IntoIterator` is not satisfied
+ = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+ |
+LL | fn into_iter(self) -> Self::IntoIter;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--> $DIR/suggest-change-mut.rs:12:48
|
LL | let mut stream_reader = BufReader::new(&stream);
- | ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+ | -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+ | |
+ | required by a bound introduced by this call
|
note: required by `BufReader::<R>::new`
--> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
|
LL | let _ = RGB { r, g, c };
- | ^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `r: r.into()`
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r: r.into(), g, c };
+ | ++ +++++++
error[E0308]: mismatched types
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
|
LL | let _ = RGB { r, g, c };
- | ^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `g: g.into()`
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g: g.into(), c };
+ | ++ +++++++
error[E0560]: struct `RGB` has no field named `c`
--> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
|
LL | let _ = RGB { r, g, b };
- | ^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `r: r.into()`
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r: r.into(), g, b };
+ | ++ +++++++
error[E0308]: mismatched types
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
|
LL | let _ = RGB { r, g, b };
- | ^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `g: g.into()`
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g: g.into(), b };
+ | ++ +++++++
error[E0308]: mismatched types
--> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
|
LL | let _ = RGB { r, g, b };
- | ^
- | |
- | expected `f64`, found `f32`
- | help: you can convert an `f32` to an `f64`: `b: b.into()`
+ | ^ expected `f64`, found `f32`
+ |
+help: you can convert an `f32` to an `f64`
+ |
+LL | let _ = RGB { r, g, b: b.into() };
+ | ++ +++++++
error: aborting due to 3 previous errors
--- /dev/null
+// build-pass
+
+// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
+// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
+// symbol mangling fix produces the correct result.
+
+fn dummy() {}
+
+mod llvm {
+ pub(crate) struct Foo;
+}
+mod foo {
+ pub(crate) struct Foo<T>(T);
+
+ impl Foo<::llvm::Foo> {
+ pub(crate) fn foo() {
+ for _ in 0..0 {
+ for _ in &[::dummy()] {
+ ::dummy();
+ ::dummy();
+ ::dummy();
+ }
+ }
+ }
+ }
+
+ pub(crate) fn foo() {
+ Foo::foo();
+ Foo::foo();
+ }
+}
+
+pub fn foo() {
+ foo::foo();
+}
+
+fn main() {}
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
LL | fn f() -> isize { return g().try_into().unwrap(); }
- | ~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to previous error
--- /dev/null
+// run-pass
+// compile-flags:--test
+#![deny(private_in_public)]
+
+#[test] fn foo() {}
+mod foo {}
+
+#[test] fn core() {}
+extern crate core;
--- /dev/null
+// run-pass
+// ignore-emscripten no threads support
+// compile-flags: -O
+
+#![feature(thread_local)]
+
+#[thread_local]
+static S: u32 = 222;
+
+fn main() {
+ let local = &S as *const u32 as usize;
+ let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
+ assert_ne!(local, foreign);
+}
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads support
-// compile-flags: -O
-
-#![feature(thread_local)]
-
-#[thread_local]
-static S: u32 = 222;
-
-fn main() {
- let local = &S as *const u32 as usize;
- let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
- assert_ne!(local, foreign);
-}
--> $DIR/same-crate-name.rs:31:20
|
LL | a::try_foo(foo);
- | ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+ | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+ | |
+ | required by a bound introduced by this call
|
help: trait impl with same name found
--> $DIR/auxiliary/crate_a2.rs:5:1
--> $DIR/same-crate-name.rs:38:20
|
LL | a::try_foo(implements_no_traits);
- | ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `try_foo`
--> $DIR/auxiliary/crate_a1.rs:3:24
--> $DIR/same-crate-name.rs:45:20
|
LL | a::try_foo(other_variant_implements_mismatched_trait);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+ | |
+ | required by a bound introduced by this call
|
help: trait impl with same name found
--> $DIR/auxiliary/crate_a2.rs:13:1
--> $DIR/same-crate-name.rs:51:20
|
LL | a::try_foo(other_variant_implements_correct_trait);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<ImplementsTraitForUsize<usize> as main::a::Bar>
--- /dev/null
+// run-pass
+
+trait Speak : Sized {
+ fn say(&self, s:&str) -> String;
+ fn hi(&self) -> String { hello(self) }
+}
+
+fn hello<S:Speak>(s:&S) -> String{
+ s.say("hello")
+}
+
+impl Speak for isize {
+ fn say(&self, s:&str) -> String {
+ format!("{}: {}", s, *self)
+ }
+}
+
+impl<T: Speak> Speak for Option<T> {
+ fn say(&self, s:&str) -> String {
+ match *self {
+ None => format!("{} - none", s),
+ Some(ref x) => { format!("something!{}", x.say(s)) }
+ }
+ }
+}
+
+
+pub fn main() {
+ assert_eq!(3.hi(), "hello: 3".to_string());
+ assert_eq!(Some(Some(3)).hi(),
+ "something!something!hello: 3".to_string());
+ assert_eq!(None::<isize>.hi(), "hello - none".to_string());
+
+ assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string());
+ assert_eq!(Some(3).hi(), "something!hello: 3".to_string());
+}
--> $DIR/supertrait-auto-trait.rs:16:23
|
LL | let (a, b) = copy(NoClone);
- | ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+ | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+ | |
+ | required by a bound introduced by this call
|
= note: required because of the requirements on the impl of `Magic` for `NoClone`
note: required by a bound in `copy`
--- /dev/null
+trait Array: Sized + Copy {}
+
+fn f<T: Array>(x: &T) {
+ let _ = x
+ //~^ ERROR `Array` cannot be made into an object
+ as
+ &dyn Array;
+ //~^ ERROR `Array` cannot be made into an object
+}
+
+fn main() {}
--- /dev/null
+error[E0038]: the trait `Array` cannot be made into an object
+ --> $DIR/issue-20692.rs:7:5
+ |
+LL | &dyn Array;
+ | ^^^^^^^^^^ `Array` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-20692.rs:1:14
+ |
+LL | trait Array: Sized + Copy {}
+ | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
+ | | |
+ | | ...because it requires `Self: Sized`
+ | this trait cannot be made into an object...
+
+error[E0038]: the trait `Array` cannot be made into an object
+ --> $DIR/issue-20692.rs:4:13
+ |
+LL | let _ = x
+ | ^ `Array` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-20692.rs:1:14
+ |
+LL | trait Array: Sized + Copy {}
+ | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized`
+ | | |
+ | | ...because it requires `Self: Sized`
+ | this trait cannot be made into an object...
+ = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Array>` for `&T`
+ = note: required by cast to type `&dyn Array`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
--- /dev/null
+// run-pass
+trait Stringify {
+ fn to_string(&self) -> String;
+}
+
+impl Stringify for u32 {
+ fn to_string(&self) -> String { format!("u32: {}", *self) }
+}
+
+impl Stringify for f32 {
+ fn to_string(&self) -> String { format!("f32: {}", *self) }
+}
+
+fn print<T: Stringify>(x: T) -> String {
+ x.to_string()
+}
+
+fn main() {
+ assert_eq!(&print(5), "u32: 5");
+ assert_eq!(&print(5.0), "f32: 5");
+}
LL | <dyn C>::A;
| ^^^^^ `assoc_const::C` cannot be made into an object
|
- = help: consider moving `C` to another trait
- = help: consider moving `B` to another trait
- = help: consider moving `A` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/item-privacy.rs:25:15
|
| - this trait cannot be made into an object...
LL | const C: u8 = 0;
| ^ ...because it contains this associated `const`
+ = help: consider moving `C` to another trait
+ = help: consider moving `A` to another trait
+ = help: consider moving `B` to another trait
error[E0223]: ambiguous associated type
--> $DIR/item-privacy.rs:115:12
help: change the type of the numeric literal from `i32` to `u32`
|
LL | test(22i32, 44u32);
- | ~~~~~
+ | ~~~
error: aborting due to previous error
--> $DIR/negated-auto-traits-error.rs:23:11
|
LL | Outer(TestType);
- | ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `dummy::TestType`
note: required by `Outer`
--> $DIR/negated-auto-traits-error.rs:32:13
|
LL | is_send(TestType);
- | ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+ | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Send` is not implemented for `dummy1b::TestType`
note: required by a bound in `is_send`
--> $DIR/negated-auto-traits-error.rs:40:13
|
LL | is_send((8, TestType));
- | ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+ | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
- = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
+ = help: the trait `Send` is not implemented for `dummy1c::TestType`
= note: required because it appears within the type `({integer}, dummy1c::TestType)`
note: required by a bound in `is_send`
--> $DIR/negated-auto-traits-error.rs:16:15
--> $DIR/negated-auto-traits-error.rs:48:13
|
LL | is_send(Box::new(TestType));
- | ^^^^^^^^^^^^^^^^^^
- | |
- | expected an implementor of trait `Send`
- | help: consider borrowing here: `&Box::new(TestType)`
+ | ------- ^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected an implementor of trait `Send`
+ | | help: consider borrowing here: `&Box::new(TestType)`
+ | required by a bound introduced by this call
|
= note: the trait bound `dummy2::TestType: Send` is not satisfied
= note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
--> $DIR/negated-auto-traits-error.rs:56:13
|
LL | is_send(Box::new(Outer2(TestType)));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+ | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
|
- = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
+ = help: the trait `Send` is not implemented for `dummy3::TestType`
note: required because it appears within the type `Outer2<dummy3::TestType>`
--> $DIR/negated-auto-traits-error.rs:12:8
|
--> $DIR/negated-auto-traits-error.rs:66:13
|
LL | is_sync(Outer2(TestType));
- | ^^^^^^^^^^^^^^^^
- | |
- | expected an implementor of trait `Sync`
- | help: consider borrowing here: `&Outer2(TestType)`
+ | ------- ^^^^^^^^^^^^^^^^
+ | | |
+ | | expected an implementor of trait `Sync`
+ | | help: consider borrowing here: `&Outer2(TestType)`
+ | required by a bound introduced by this call
|
= note: the trait bound `main::TestType: Sync` is not satisfied
note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
--> $DIR/no-use.rs:10:26
|
LL | <() as MyTrait>::foo(&());
- | ^^^ the trait `MyTrait` is not implemented for `()`
+ | -------------------- ^^^ the trait `MyTrait` is not implemented for `()`
+ | |
+ | required by a bound introduced by this call
|
= help: the following implementations were found:
<() as MyTrait>
--> $DIR/issue-39029.rs:16:37
|
LL | let _errors = TcpListener::bind(&bad);
- | ^^^^
- | |
- | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
- | help: consider adding dereference here: `&*bad`
+ | ----------------- ^^^^
+ | | |
+ | | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+ | | help: consider adding dereference here: `&*bad`
+ | required by a bound introduced by this call
|
= note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs`
note: required by a bound in `TcpListener::bind`
--> $DIR/issue-62530.rs:13:26
|
LL | takes_type_parameter(&string); // Error
- | ^^^^^^^
- | |
- | the trait `SomeTrait` is not implemented for `&String`
- | help: consider adding dereference here: `&*string`
+ | -------------------- ^^^^^^^
+ | | |
+ | | the trait `SomeTrait` is not implemented for `&String`
+ | | help: consider adding dereference here: `&*string`
+ | required by a bound introduced by this call
|
note: required by a bound in `takes_type_parameter`
--> $DIR/issue-62530.rs:4:44
--> $DIR/multiple-0.rs:34:9
|
LL | foo(&baz);
- | ^^^^
- | |
- | the trait `Happy` is not implemented for `&Baz`
- | help: consider adding dereference here: `&***baz`
+ | --- ^^^^
+ | | |
+ | | the trait `Happy` is not implemented for `&Baz`
+ | | help: consider adding dereference here: `&***baz`
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/multiple-0.rs:30:26
--> $DIR/multiple-1.rs:52:9
|
LL | foo(&mut baz);
- | ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+ | --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/multiple-1.rs:45:26
LL | (box 10 as Box<dyn bar>).dup();
| ^^^^^^^^^^^^ `bar` cannot be made into an object
|
- = help: consider moving `dup` to another trait
- = help: consider moving `blah` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/test-2.rs:4:30
|
| | |
| | ...because method `dup` references the `Self` type in its return type
| this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/test-2.rs:13:6
LL | (box 10 as Box<dyn bar>).dup();
| ^^^^^^ `bar` cannot be made into an object
|
- = help: consider moving `dup` to another trait
- = help: consider moving `blah` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/test-2.rs:4:30
|
| | |
| | ...because method `dup` references the `Self` type in its return type
| this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
= note: required by cast to type `Box<dyn bar>`
help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
|
LL | B::get_x().try_into().unwrap()
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to previous error
--> $DIR/trivial-bounds-leak.rs:25:15
|
LL | Foo::test(&4i32);
- | ^^^^^ the trait `Foo` is not implemented for `i32`
+ | --------- ^^^^^ the trait `Foo` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
|
note: required by `Foo::test`
--> $DIR/trivial-bounds-leak.rs:5:5
--> $DIR/trivial-bounds-leak.rs:26:22
|
LL | generic_function(5i32);
- | ^^^^ the trait `Foo` is not implemented for `i32`
+ | ---------------- ^^^^ the trait `Foo` is not implemented for `i32`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `generic_function`
--> $DIR/trivial-bounds-leak.rs:29:24
--> $DIR/try-block-unused-delims.rs:11:13
|
LL | consume((try {}));
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
|
note: the lint level is defined here
--> $DIR/try-block-unused-delims.rs:6:9
|
LL | #![warn(unused_parens, unused_braces)]
| ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - consume((try {}));
+LL + consume(try {});
+ |
warning: unnecessary braces around function argument
--> $DIR/try-block-unused-delims.rs:14:13
|
LL | consume({ try {} });
- | ^^^^^^^^^^ help: remove these braces
+ | ^^ ^^
|
note: the lint level is defined here
--> $DIR/try-block-unused-delims.rs:6:24
|
LL | #![warn(unused_parens, unused_braces)]
| ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - consume({ try {} });
+LL + consume(try {});
+ |
warning: unnecessary parentheses around `match` scrutinee expression
--> $DIR/try-block-unused-delims.rs:17:11
|
LL | match (try {}) {
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - match (try {}) {
+LL + match try {} {
+ |
warning: unnecessary parentheses around `let` scrutinee expression
--> $DIR/try-block-unused-delims.rs:22:22
|
LL | if let Err(()) = (try {}) {}
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let Err(()) = (try {}) {}
+LL + if let Err(()) = try {} {}
+ |
warning: unnecessary parentheses around `match` scrutinee expression
--> $DIR/try-block-unused-delims.rs:25:11
|
LL | match (try {}) {
- | ^^^^^^^^ help: remove these parentheses
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - match (try {}) {
+LL + match try {} {
+ |
warning: 5 warnings emitted
--> $DIR/tutorial-suffix-inference-test.rs:9:18
|
LL | identity_u16(x);
- | ^
- | |
- | expected `u16`, found `u8`
- | help: you can convert a `u8` to a `u16`: `x.into()`
+ | ^ expected `u16`, found `u8`
+ |
+help: you can convert a `u8` to a `u16`
+ |
+LL | identity_u16(x.into());
+ | +++++++
error[E0308]: mismatched types
--> $DIR/tutorial-suffix-inference-test.rs:12:18
help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
|
LL | identity_u16(y.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/tutorial-suffix-inference-test.rs:21:18
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
LL | identity_u16(a.try_into().unwrap());
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to 3 previous errors
--- /dev/null
+macro_rules! many_args {
+ ([$($t:tt)*]#$($h:tt)*) => {
+ many_args!{[$($t)*$($t)*]$($h)*}
+ };
+ ([$($t:tt)*]) => {
+ fn _f($($t: ()),*) {} //~ ERROR function can not have more than 65535 arguments
+ }
+}
+
+many_args!{[_]########## ######}
+
+fn main() {}
--- /dev/null
+error: function can not have more than 65535 arguments
+ --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:24
+ |
+LL | fn _f($($t: ()),*) {}
+ | ________________________^
+LL | | }
+LL | | }
+LL | |
+LL | | many_args!{[_]########## ######}
+ | |____________^
+
+error: aborting due to previous error
+
LL | let y = x as dyn MyAdd<i32>;
| ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object
|
- = help: consider moving `add` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55
|
| ----- ^^^^ ...because method `add` references the `Self` type in its return type
| |
| this trait cannot be made into an object...
+ = help: consider moving `add` to another trait
error: aborting due to 2 previous errors
--- /dev/null
+// run-rustfix
+
+fn main() {
+ let a = Some(42);
+ println!(
+ "The value is {}.",
+ a.unwrap() //~ERROR [E0615]
+ );
+}
--- /dev/null
+// run-rustfix
+
+fn main() {
+ let a = Some(42);
+ println!(
+ "The value is {}.",
+ (a.unwrap)() //~ERROR [E0615]
+ );
+}
--- /dev/null
+error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>`
+ --> $DIR/issue-88803-call-expr-method.rs:7:12
+ |
+LL | (a.unwrap)()
+ | ^^^^^^ method, not a field
+ |
+help: remove wrapping parentheses to call the method
+ |
+LL - (a.unwrap)()
+LL + a.unwrap()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
--- /dev/null
+// Regression test for #88844.
+
+struct Struct { value: i32 }
+//~^ NOTE: similarly named struct `Struct` defined here
+
+impl Stuct {
+//~^ ERROR: cannot find type `Stuct` in this scope [E0412]
+//~| HELP: a struct with a similar name exists
+ fn new() -> Self {
+ Self { value: 42 }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0412]: cannot find type `Stuct` in this scope
+ --> $DIR/issue-88844.rs:6:6
+ |
+LL | struct Struct { value: i32 }
+ | ------------- similarly named struct `Struct` defined here
+...
+LL | impl Stuct {
+ | ^^^^^ help: a struct with a similar name exists: `Struct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
--- /dev/null
+// run-rustfix
+
+fn main() {
+ let a = Some(42);
+ println!(
+ "The value is {}.",
+ (a.unwrap()) //~ERROR [E0615]
+ );
+}
--- /dev/null
+// run-rustfix
+
+fn main() {
+ let a = Some(42);
+ println!(
+ "The value is {}.",
+ (a.unwrap) //~ERROR [E0615]
+ );
+}
--- /dev/null
+error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>`
+ --> $DIR/issue-89044-wrapped-expr-method.rs:7:12
+ |
+LL | (a.unwrap)
+ | ^^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | (a.unwrap())
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
--> $DIR/typeck-unsafe-always-share.rs:19:10
|
LL | test(us);
- | ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+ | ---- ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `UnsafeCell<MySync<{integer}>>`
note: required by a bound in `test`
--> $DIR/typeck-unsafe-always-share.rs:23:10
|
LL | test(uns);
- | ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+ | ---- ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `UnsafeCell<NoSync>`
note: required by a bound in `test`
--> $DIR/typeck-unsafe-always-share.rs:30:10
|
LL | test(NoSync);
- | ^^^^^^ `NoSync` cannot be shared between threads safely
+ | ---- ^^^^^^ `NoSync` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `NoSync`
note: required by a bound in `test`
help: change the type of the numeric literal from `i8` to `u8`
|
LL | let b: typeof(a) = 1u8;
- | ~~~
+ | ~~
error: aborting due to 2 previous errors
help: change the type of the numeric literal from `u32` to `i32`
|
LL | <i32 as Add<i32>>::add(1i32, 2);
- | ~~~~
+ | ~~~
error[E0308]: mismatched types
--> $DIR/ufcs-qpath-self-mismatch.rs:8:31
help: change the type of the numeric literal from `u32` to `i32`
|
LL | <i32 as Add<i32>>::add(1, 2i32);
- | ~~~~
+ | ~~~
error: aborting due to 3 previous errors
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn(|| drop(x));
- | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | --------^-
+ | | |
+ | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | captured by this `Fn` closure
error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
--> $DIR/unboxed-closure-illegal-move.rs:19:35
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn_mut(|| drop(x));
- | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | --------^-
+ | | |
+ | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | captured by this `FnMut` closure
error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
--> $DIR/unboxed-closure-illegal-move.rs:28:36
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn(move || drop(x));
- | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | -------------^-
+ | | |
+ | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | captured by this `Fn` closure
error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
--> $DIR/unboxed-closure-illegal-move.rs:32:40
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn_mut(move || drop(x));
- | ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | -------------^-
+ | | |
+ | | move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+ | captured by this `FnMut` closure
error: aborting due to 4 previous errors
--> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21
|
LL | let x = call_it(&S, 22);
- | ^^ expected an `Fn<(isize,)>` closure, found `S`
+ | ------- ^^ expected an `Fn<(isize,)>` closure, found `S`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `Fn<(isize,)>` is not implemented for `S`
note: required by a bound in `call_it`
help: change the type of the numeric literal from `usize` to `isize`
|
LL | let z = f(1_isize, 2);
- | ~~~~~~~
+ | ~~~~~
error: aborting due to previous error
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21
|
LL | let x = call_it(&square, 22);
- | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25
|
LL | let y = call_it_mut(&mut square, 22);
- | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26
|
LL | let z = call_it_once(square, 22);
- | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-abi.rs:20:21
|
LL | let x = call_it(&square, 22);
- | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-abi.rs:25:25
|
LL | let y = call_it_mut(&mut square, 22);
- | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-abi.rs:30:26
|
LL | let z = call_it_once(square, 22);
- | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21
|
LL | let x = call_it(&square, 22);
- | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25
|
LL | let y = call_it_mut(&mut square, 22);
- | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26
|
LL | let z = call_it_once(square, 22);
- | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+ | |
+ | required by a bound introduced by this call
|
= help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
note: required by a bound in `call_it_once`
+++ /dev/null
-#![allow(incomplete_features)]
-#![feature(unnamed_fields)]
-
-fn f() -> struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-fn f2(a: struct { field: u8 } ) {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-union G {
- field: struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
-}
-//~| ERROR unions may not contain fields that need dropping [E0740]
-
-struct H { _: u8 } // Should error after hir checks
-
-struct I(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-enum J {
- K(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
- L {
- _ : struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous fields are not allowed outside of structs or unions
- //~| ERROR anonymous structs are unimplemented
- },
- M {
- _ : u8 //~ ERROR anonymous fields are not allowed outside of structs or unions
- }
-}
-
-static M: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-type N = union { field: u8 }; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-fn main() {
- const O: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
-
- let p: [struct { field: u8 }; 1]; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
-
- let q: (struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
-
- let cl = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
- //~^ ERROR anonymous structs are unimplemented
-}
+++ /dev/null
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:4:11
- |
-LL | fn f() -> struct { field: u8 } {}
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:7:10
- |
-LL | fn f2(a: struct { field: u8 } ) {}
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:11:12
- |
-LL | field: struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:18:10
- |
-LL | struct I(struct { field: u8 }, u8);
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:22:7
- |
-LL | K(struct { field: u8 }),
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
- --> $DIR/restrict_anonymous.rs:25:9
- |
-LL | _ : struct { field: u8 }
- | -^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | anonymous field declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:25:13
- |
-LL | _ : struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
- --> $DIR/restrict_anonymous.rs:30:9
- |
-LL | _ : u8
- | -^^^^^
- | |
- | anonymous field declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:34:11
- |
-LL | static M: union { field: u8 } = 0;
- | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:37:10
- |
-LL | type N = union { field: u8 };
- | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:41:14
- |
-LL | const O: struct { field: u8 } = 0;
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:44:13
- |
-LL | let p: [struct { field: u8 }; 1];
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:47:13
- |
-LL | let q: (struct { field: u8 }, u8);
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
- --> $DIR/restrict_anonymous.rs:50:20
- |
-LL | let cl = || -> struct { field: u8 } {};
- | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:4:11
- |
-LL | fn f() -> struct { field: u8 } {}
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:7:10
- |
-LL | fn f2(a: struct { field: u8 } ) {}
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:11:12
- |
-LL | field: struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:18:10
- |
-LL | struct I(struct { field: u8 }, u8);
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:22:7
- |
-LL | K(struct { field: u8 }),
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:25:13
- |
-LL | _ : struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
- --> $DIR/restrict_anonymous.rs:34:11
- |
-LL | static M: union { field: u8 } = 0;
- | ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
- --> $DIR/restrict_anonymous.rs:37:10
- |
-LL | type N = union { field: u8 };
- | ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:44:13
- |
-LL | let p: [struct { field: u8 }; 1];
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:47:13
- |
-LL | let q: (struct { field: u8 }, u8);
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:50:20
- |
-LL | let cl = || -> struct { field: u8 } {};
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
- --> $DIR/restrict_anonymous.rs:41:14
- |
-LL | const O: struct { field: u8 } = 0;
- | ^^^^^^^^^^^^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
- --> $DIR/restrict_anonymous.rs:11:5
- |
-LL | field: struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
- --> $DIR/restrict_anonymous.rs:11:5
- |
-LL | field: struct { field: u8 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
--- /dev/null
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+LL | let f = |v: &mut Vec<_>| {
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+ |
+LL | #[deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |w: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |x: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#[deny(unused_unsafe)]
+fn main() {
+ let mut v = Vec::<i32>::with_capacity(24);
+
+ unsafe {
+ let f = |v: &mut Vec<_>| {
+ unsafe { //~ ERROR unnecessary `unsafe`
+ v.set_len(24);
+ |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+ w.set_len(32);
+ } };
+ }
+ |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+ x.set_len(40);
+ } };
+ };
+
+ v.set_len(0);
+ f(&mut v);
+ }
+
+ |y: &mut Vec<u32>| { unsafe {
+ y.set_len(48);
+ } };
+}
--- /dev/null
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+LL | let f = |v: &mut Vec<_>| {
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+ |
+LL | #[deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |w: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |x: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
--> $DIR/unsized-exprs.rs:24:22
|
LL | udrop::<A<[u8]>>(A { 0: *foo() });
- | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
- = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+ = help: the trait `Sized` is not implemented for `[u8]`
note: required because it appears within the type `A<[u8]>`
--> $DIR/unsized-exprs.rs:3:8
|
fn f10<X: ?Sized>(x1: Box<S<X>>) {
f5(&(32, *x1));
//~^ ERROR the size for values of type
- //~| ERROR the size for values of type
}
-pub fn main() {
-}
+pub fn main() {}
LL | fn f1<X: ?Sized>(x: &X) {
| - this type parameter needs to be `std::marker::Sized`
LL | f2::<X>(x);
- | ^ doesn't have a size known at compile-time
+ | ------- ^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f2`
--> $DIR/unsized3.rs:10:7
LL | fn f3<X: ?Sized + T>(x: &X) {
| - this type parameter needs to be `std::marker::Sized`
LL | f4::<X>(x);
- | ^ doesn't have a size known at compile-time
+ | ------- ^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `f4`
--> $DIR/unsized3.rs:21:7
LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
| - this type parameter needs to be `std::marker::Sized`
LL | f5(x1);
- | ^^ doesn't have a size known at compile-time
+ | -- ^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
note: required because it appears within the type `S<X>`
--> $DIR/unsized3.rs:28:8
LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(*x1, 34));
- | ^^^^^^^^^^ doesn't have a size known at compile-time
+ | -- ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
note: required because it appears within the type `S<X>`
--> $DIR/unsized3.rs:28:8
LL + fn f9<X>(x1: Box<S<X>>) {
|
-error[E0277]: the size for values of type `X` cannot be known at compilation time
- --> $DIR/unsized3.rs:45:9
- |
-LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
- | - this type parameter needs to be `std::marker::Sized`
-LL | f5(&(32, *x1));
- | ^^^^^^^^^ doesn't have a size known at compile-time
- |
-note: required because it appears within the type `S<X>`
- --> $DIR/unsized3.rs:28:8
- |
-LL | struct S<X: ?Sized> {
- | ^
- = note: required because it appears within the type `({integer}, S<X>)`
- = note: tuples must have a statically known size to be initialized
-help: consider removing the `?Sized` bound to make the type parameter `Sized`
- |
-LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
-LL + fn f10<X>(x1: Box<S<X>>) {
- |
-
error[E0277]: the size for values of type `X` cannot be known at compilation time
--> $DIR/unsized3.rs:45:8
|
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
| - this type parameter needs to be `std::marker::Sized`
LL | f5(&(32, *x1));
- | ^^^^^^^^^^ doesn't have a size known at compile-time
+ | -- ^^^^^^^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
|
note: required because it appears within the type `S<X>`
--> $DIR/unsized3.rs:28:8
LL | struct S<X: ?Sized> {
| ^
= note: required because it appears within the type `({integer}, S<X>)`
-note: required by a bound in `f5`
- --> $DIR/unsized3.rs:24:7
- |
-LL | fn f5<Y>(x: &Y) {}
- | ^ required by this bound in `f5`
+ = note: tuples must have a statically known size to be initialized
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
LL + fn f10<X>(x1: Box<S<X>>) {
|
-help: consider relaxing the implicit `Sized` restriction
- |
-LL | fn f5<Y: ?Sized>(x: &Y) {}
- | ++++++++
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.
+++ /dev/null
-struct A;
-
-impl A {
-//~^ NOTE `Self` type implicitly declared here, by this `impl`
- fn banana(&mut self) {
- fn peach(this: &Self) {
- //~^ ERROR can't use generic parameters from outer function
- //~| NOTE use of generic parameter from outer function
- //~| NOTE use a type here instead
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0401]: can't use generic parameters from outer function
- --> $DIR/use-self-in-inner-fn.rs:6:25
- |
-LL | impl A {
- | ---- `Self` type implicitly declared here, by this `impl`
-...
-LL | fn peach(this: &Self) {
- | ^^^^
- | |
- | use of generic parameter from outer function
- | use a type here instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
--> $DIR/vtable-res-trait-param.rs:17:18
|
LL | b.gimme_an_a(y)
- | ^ the trait `TraitA` is not implemented for `{integer}`
+ | ---------- ^ the trait `TraitA` is not implemented for `{integer}`
+ | |
+ | required by a bound introduced by this call
error: aborting due to previous error
LL | const CONST: (bool, dyn T);
| ^^^^^ `T` cannot be made into an object
|
- = help: consider moving `CONST` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/issue-87495.rs:4:11
|
| - this trait cannot be made into an object...
LL | const CONST: (bool, dyn T);
| ^^^^^ ...because it contains this associated `const`
+ = help: consider moving `CONST` to another trait
error: aborting due to previous error
LL | let _x: &dyn A;
| ^^^^^^ `A` cannot be made into an object
|
- = help: consider moving `foo` to another trait
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/wf-object-safe.rs:5:23
|
| - this trait cannot be made into an object...
LL | fn foo(&self, _x: &Self);
| ^^^^^ ...because method `foo` references the `Self` type in this parameter
+ = help: consider moving `foo` to another trait
error: aborting due to previous error
--> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22
|
LL | require_copy(self.x);
- | ^^^^^^ the trait `Copy` is not implemented for `T`
+ | ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `require_copy`
--> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20
--> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22
|
LL | require_copy(self.x);
- | ^^^^^^ the trait `Copy` is not implemented for `T`
+ | ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+ | |
+ | required by a bound introduced by this call
|
note: required by a bound in `require_copy`
--> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20
--> $DIR/where-clauses-method-unsatisfied.rs:18:14
|
LL | x.equals(&x);
- | ^^ the trait `Eq` is not implemented for `Bar`
+ | ------ ^^ the trait `Eq` is not implemented for `Bar`
+ | |
+ | required by a bound introduced by this call
error: aborting due to previous error
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
- | ~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++++++
error: aborting due to previous error
[package]
name = "build-manifest"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
toml = "0.5"
"i686-unknown-freebsd",
"i686-unknown-linux-gnu",
"i686-unknown-linux-musl",
+ "m68k-unknown-linux-gnu",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips64-unknown-linux-gnuabi64",
[package]
name = "bump-stage0"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-Subproject commit 18751dd3f238d94d384a7fe967abfac06cbfe0b9
+Subproject commit 9a28ac83c9eb73e42ffafac552c0a55f00dbf40c
[package]
name = "cargotest2"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "cargotest"
path = "src/driver.rs"
[dependencies]
-# begin automatic update
-clippy_lints = { version = "0.1.50", path = "clippy_lints" }
-# end automatic update
+clippy_lints = { version = "0.1", path = "clippy_lints" }
semver = "0.11"
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
-tempfile = { version = "3.1.0", optional = true }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
+tempfile = { version = "3.2", optional = true }
[dev-dependencies]
cargo_metadata = "0.12"
-compiletest_rs = { version = "0.6.0", features = ["tmp"] }
+compiletest_rs = { version = "0.7", features = ["tmp"] }
tester = "0.9"
-regex = "1.4"
+regex = "1.5"
# This is used by the `collect-metadata` alias.
filetime = "0.2"
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
# for more information.
-rustc-workspace-hack = "1.0.0"
+rustc-workspace-hack = "1.0"
# UI test dependencies
clippy_utils = { path = "clippy_utils" }
derive-new = "0.5"
if_chain = "1.0"
-itertools = "0.10.1"
-quote = "1"
+itertools = "0.10"
+quote = "1.0"
serde = { version = "1.0", features = ["derive"] }
-syn = { version = "1", features = ["full"] }
+syn = { version = "1.0", features = ["full"] }
[build-dependencies]
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
[features]
deny-warnings = ["clippy_lints/deny-warnings"]
[dependencies]
bytecount = "0.6"
clap = "2.33"
-itertools = "0.9"
+itertools = "0.10"
opener = "0.5"
-regex = "1"
+regex = "1.5"
shell-escape = "0.1"
-walkdir = "2"
+walkdir = "2.3"
[features]
deny-warnings = []
categories = ["development-tools", "development-tools::cargo-plugins"]
[build-dependencies]
-term = "0.6"
+term = "0.7"
[dependencies]
cargo_metadata = "0.12"
clippy_utils = { path = "../clippy_utils" }
-if_chain = "1.0.0"
-itertools = "0.9"
+if_chain = "1.0"
+itertools = "0.10"
pulldown-cmark = { version = "0.8", default-features = false }
-quine-mc_cluskey = "0.2.2"
+quine-mc_cluskey = "0.2"
regex-syntax = "0.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", optional = true }
-toml = "0.5.3"
+toml = "0.5"
unicode-normalization = "0.1"
-unicode-script = { version = "0.5.3", default-features = false }
+unicode-script = { version = "0.5", default-features = false }
semver = "0.11"
-rustc-semver = "1.1.0"
+rustc-semver = "1.1"
# NOTE: cargo requires serde feat in its url dep
# see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
-url = { version = "2.1.0", features = ["serde"] }
+url = { version = "2.2", features = ["serde"] }
[features]
deny-warnings = ["clippy_utils/deny-warnings"]
return;
}
- let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt());
- let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt());
+ let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
+ let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent());
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
let lines = snippet.split('\n').collect::<Vec<_>>();
//! lint on missing cargo common metadata
-use std::path::PathBuf;
-
use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
use rustc_lint::{LateContext, LateLintPass};
span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
}
-fn is_empty_str(value: &Option<String>) -> bool {
- value.as_ref().map_or(true, String::is_empty)
-}
-
-fn is_empty_path(value: &Option<PathBuf>) -> bool {
- value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
+fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
+ value.as_ref().map_or(true, |s| s.as_ref().is_empty())
}
fn is_empty_vec(value: &[String]) -> bool {
missing_warning(cx, &package, "package.description");
}
- if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
+ if is_empty_str(&package.license) && is_empty_str(&package.license_file) {
missing_warning(cx, &package, "either package.license or package.license_file");
}
missing_warning(cx, &package, "package.repository");
}
- if is_empty_path(&package.readme) {
+ if is_empty_str(&package.readme) {
missing_warning(cx, &package, "package.readme");
}
});
if let Some((low, high)) = pos {
- Span::new(low, high, header_span.ctxt())
+ Span::new(low, high, header_span.ctxt(), header_span.parent())
} else {
return;
}
let mut span = moved_start.to(span_end);
// Improve formatting if the inner block has indention (i.e. normal Rust formatting)
- let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt());
+ let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
if snippet_opt(cx, test_span)
.map(|snip| snip == " ")
.unwrap_or_default()
span.lo() + BytePos::from_usize(offset),
span.lo() + BytePos::from_usize(offset + word.len()),
span.ctxt(),
+ span.parent(),
);
check_word(cx, word, span);
}
}
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) {
+fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath};
let pos = snippet_opt(cx, item.span.until(target.span()))
.and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
if let Some(pos) = pos {
- Span::new(pos, pos, item.span.data().ctxt)
+ Span::new(pos, pos, item.span.ctxt(), item.span.parent())
} else {
return;
}
Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
})
.expect("failed to create span for type parameters");
- Span::new(pos, pos, item.span.data().ctxt)
+ Span::new(pos, pos, item.span.ctxt(), item.span.parent())
});
let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
hi_pos - BytePos::from_usize("const".len()),
hi_pos,
item.span.ctxt(),
+ item.span.parent(),
);
span_lint_and_then(
cx,
pat: &'tcx Pat<'_>,
arg: &'tcx Expr<'_>,
body: &'tcx Expr<'_>,
- expr: &'tcx Expr<'_>,
) {
let pat_span = pat.span;
span_lint_and_then(
cx,
FOR_KV_MAP,
- expr.span,
+ arg_span,
&format!("you seem to want to iterate on a map's {}s", kind),
|diag| {
let map = sugg::Sugg::hir(cx, arg, "map");
use rustc_lint::LateContext;
use rustc_span::sym;
-pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
if is_trait_method(cx, arg, sym::Iterator) {
span_lint(
cx,
ITER_NEXT_LOOP,
- expr.span,
+ arg.span,
"you are iterating over `Iterator::next()` which is an Option; this will compile but is \
probably not what you want",
);
needless_range_loop::check(cx, pat, arg, body, expr);
explicit_counter_loop::check(cx, pat, arg, body, expr);
}
- check_for_loop_arg(cx, pat, arg, expr);
- for_kv_map::check(cx, pat, arg, body, expr);
+ check_for_loop_arg(cx, pat, arg);
+ for_kv_map::check(cx, pat, arg, body);
mut_range_bound::check(cx, arg, body);
single_element_loop::check(cx, pat, arg, body, expr);
same_item_push::check(cx, pat, arg, body, expr);
manual_flatten::check(cx, pat, arg, body, span);
}
-fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
+fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind {
explicit_into_iter_loop::check(cx, self_arg, arg);
},
"next" => {
- next_loop_linted = iter_next_loop::check(cx, arg, expr);
+ next_loop_linted = iter_next_loop::check(cx, arg);
},
_ => {},
}
span_lint_and_then(
cx,
NEEDLESS_RANGE_LOOP,
- expr.span,
+ arg.span,
&format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
|diag| {
multispan_sugg(
span_lint_and_then(
cx,
NEEDLESS_RANGE_LOOP,
- expr.span,
+ arg.span,
&format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed),
|diag| {
multispan_sugg(
"#[macro_use] is no longer needed"
}
-const BRACKETS: &[char] = &['<', '>'];
-
#[derive(Clone, Debug, PartialEq, Eq)]
struct PathAndSpan {
path: String,
span: Span,
}
-/// `MacroRefData` includes the name of the macro
-/// and the path from `SourceMap::span_to_filename`.
+/// `MacroRefData` includes the name of the macro.
#[derive(Debug, Clone)]
pub struct MacroRefData {
name: String,
- path: String,
}
impl MacroRefData {
- pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self {
- let sm = cx.sess().source_map();
- let mut path = sm.filename_for_diagnostics(&sm.span_to_filename(callee)).to_string();
-
- // std lib paths are <::std::module::file type>
- // so remove brackets, space and type.
- if path.contains('<') {
- path = path.replace(BRACKETS, "");
- }
- if path.contains(' ') {
- path = path.split(' ').next().unwrap().to_string();
- }
- Self { name, path }
+ pub fn new(name: String) -> Self {
+ Self { name }
}
}
fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) {
let call_site = span.source_callsite();
let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
- if let Some(callee) = span.source_callee() {
+ if let Some(_callee) = span.source_callee() {
if !self.collected.contains(&call_site) {
let name = if name.contains("::") {
name.split("::").last().unwrap().to_string()
name.to_string()
};
- self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx));
+ self.mac_refs.push(MacroRefData::new(name));
self.collected.insert(call_site);
}
}
fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_>, span: Span) {
let call_site = span.source_callsite();
let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
- if let Some(callee) = span.source_callee() {
+ if let Some(_callee) = span.source_callee() {
if !self.collected.contains(&call_site) {
self.mac_refs
- .push(MacroRefData::new(name.to_string(), callee.def_site, cx));
+ .push(MacroRefData::new(name.to_string()));
self.collected.insert(call_site);
}
}
},
_,
) => {
- let parent_span = e.span.parent().unwrap();
+ let parent_span = e.span.parent_callsite().unwrap();
if parent_span.ctxt() == ctxt {
(Some(UnwrapKind::QuestionMark), parent_span)
} else {
correct.push("mod.rs");
cx.struct_span_lint(
SELF_NAMED_MODULE_FILES,
- Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+ Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
|build| {
let mut lint =
build.build(&format!("`mod.rs` files are required, found `{}`", path.display()));
cx.struct_span_lint(
MOD_MODULE_FILES,
- Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+ Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
|build| {
let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display()));
lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),));
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::{LitKind, StrStyle};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::{BorrowKind, Expr, ExprKind, HirId};
+use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{BytePos, Span};
}
#[derive(Clone, Default)]
-pub struct Regex {
- spans: FxHashSet<Span>,
- last: Option<HirId>,
-}
+pub struct Regex {}
impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
assert!(start <= end);
- Span::new(start, end, base.ctxt())
+ Span::new(start, end, base.ctxt(), base.parent())
}
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
attr.span.lo() + BytePos(3 + lo),
attr.span.lo() + BytePos(3 + hi),
attr.span.ctxt(),
+ attr.span.parent(),
);
span_lint_and_sugg(
cx,
publish = false
[dependencies]
-if_chain = "1.0.0"
-rustc-semver="1.1.0"
+if_chain = "1.0"
+rustc-semver = "1.1"
[features]
deny-warnings = []
if_else,
) = expr.kind
{
- let hir = cx.tcx.hir();
- let mut iter = hir.parent_iter(expr.hir_id);
+ let mut iter = cx.tcx.hir().parent_iter(expr.hir_id);
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
if let Some((
_,
}
};
}
- fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
+ fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
tcx.item_children(def_id)
.iter()
.find(|item| item.ident.name.as_str() == name)
None
}
});
- try_res!(last).res
+ try_res!(last).res.expect_non_local()
}
/// Convenience function to get the `DefId` of a trait by path.
ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
));
- let map = cx.tcx.hir();
let mut child_id = e.hir_id;
let mut capture = CaptureKind::Value;
let mut capture_expr_ty = e;
- for (parent_id, parent) in map.parent_iter(e.hir_id) {
+ for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
if let [Adjustment {
kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
target,
/// Gets the loop or closure enclosing the given expression, if any.
pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
- let map = tcx.hir();
- for (_, node) in map.parent_iter(expr.hir_id) {
+ for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
match node {
Node::Expr(
e
/// Gets the parent node if it's an impl block.
pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
- let map = tcx.hir();
- match map.parent_iter(id).next() {
+ match tcx.hir().parent_iter(id).next() {
Some((
_,
Node::Item(Item {
/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
- let map = tcx.hir();
- let mut iter = map.parent_iter(expr.hir_id);
+ let mut iter = tcx.hir().parent_iter(expr.hir_id);
match iter.next() {
Some((
_,
/// Gets the node where an expression is either used, or it's type is unified with another branch.
pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
- let map = tcx.hir();
let mut child_id = expr.hir_id;
- let mut iter = map.parent_iter(child_id);
+ let mut iter = tcx.hir().parent_iter(child_id);
loop {
match iter.next() {
None => break None,
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
-pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs", "PermissionsExt", "from_mode"];
+pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
))
}
},
- Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx);
[dependencies]
clap = "2.33"
-flate2 = {version = "1.0.19"}
-fs_extra = {version = "1.2.0"}
-rayon = {version = "1.5.0"}
-serde = {version = "1.0", features = ["derive"]}
-serde_json = {version = "1.0"}
-tar = {version = "0.4.30"}
-toml = {version = "0.5"}
-ureq = {version = "2.0.0-rc3"}
-walkdir = {version = "2.3.2"}
+flate2 = "1.0"
+fs_extra = "1.2"
+rayon = "1.5"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+tar = "0.4"
+toml = "0.5"
+ureq = "2.2"
+walkdir = "2.3"
[features]
deny-warnings = []
// run-rustfix
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
#![deny(clippy::default_trait_access)]
use std::default;
// run-rustfix
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
#![deny(clippy::default_trait_access)]
use std::default;
[package]
name = "compiletest"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
colored = "2"
("i386", "x86"),
("i586", "x86"),
("i686", "x86"),
+ ("m68k", "m68k"),
("mips", "mips"),
("mips64", "mips64"),
("mips64el", "mips64"),
[package]
name = "error_index_generator"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustdoc = { path = "../../librustdoc" }
[package]
name = "expand-yaml-anchors"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
yaml-rust = "0.4.3"
[package]
name = "html-checker"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "html-checker"
[package]
name = "jsondocck"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
jsonpath_lib = "0.2"
[package]
name = "linkchecker"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "linkchecker"
// If at all possible you should use intra-doc links to avoid linkcheck issues. These
// are cases where that does not work
// [(generated_documentation_page, &[broken_links])]
+#[rustfmt::skip]
const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
// These try to link to std::collections, but are defined in alloc
// https://github.com/rust-lang/rust/issues/74481
("std/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
("alloc/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]),
("alloc/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
+
+ // These try to link to various things in std, but are defined in core.
+ // The docs in std::primitive use proper intra-doc links, so these seem fine to special-case.
+ // Most these are broken because liballoc uses `#[lang_item]` magic to define things on
+ // primitives that aren't available in core.
+ ("alloc/slice/trait.Join.html", &["#method.join"]),
+ ("alloc/slice/trait.Concat.html", &["#method.concat"]),
+ ("alloc/slice/index.html", &["#method.concat", "#method.join"]),
+ ("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]),
+ ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]),
+ ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
+ "core/slice::sort_by_key", "core\\slice::sort_by_key",
+ "#method.sort_by_cached_key"]),
];
#[rustfmt::skip]
/// Load a file from disk, or from the cache if available.
fn load_file(&mut self, file: &Path, report: &mut Report) -> (String, &FileEntry) {
+ // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+ #[cfg(windows)]
+ const ERROR_INVALID_NAME: i32 = 123;
+
let pretty_path =
file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
}
Err(e) if e.kind() == ErrorKind::NotFound => FileEntry::Missing,
Err(e) => {
+ // If a broken intra-doc link contains `::`, on windows, it will cause `ERROR_INVALID_NAME` rather than `NotFound`.
+ // Explicitly check for that so that the broken link can be allowed in `LINKCHECK_EXCEPTIONS`.
+ #[cfg(windows)]
+ if e.raw_os_error() == Some(ERROR_INVALID_NAME)
+ && file.as_os_str().to_str().map_or(false, |s| s.contains("::"))
+ {
+ return FileEntry::Missing;
+ }
panic!("unexpected read error for {}: {}", file.display(), e);
}
});
[package]
name = "lint-docs"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
description = "A script to extract the lint documentation for the rustc book."
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
} else if line.starts_with("// ") {
// Ignore comments.
continue;
+ } else if line.starts_with("#[allow") {
+ // Ignore allow of lints (useful for
+ // invalid_rust_codeblocks).
+ continue;
} else {
let name = lint_name(line).map_err(|e| {
format!(
-Subproject commit 7a2f1cadcd5120c44eda3596053de767cd8173a2
+Subproject commit 035933186957cf81c488261fb48a98bf523e8006
if repo:
github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
if github_token:
- validate_maintainers(repo, github_token)
+ # FIXME: This is currently broken. Starting on 2021-09-15, GitHub
+ # seems to have changed it so that to list the collaborators
+ # requires admin permissions. I think this will probably just need
+ # to be removed since we are probably not going to use an admin
+ # token, and I don't see another way to do this.
+ print('maintainer validation disabled')
+ # validate_maintainers(repo, github_token)
else:
print('skipping toolstate maintainers validation since no GitHub token is present')
# When validating maintainers don't run the full script.
[package]
name = "remote-test-client"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
[package]
name = "remote-test-server"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
-Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
+Subproject commit f1d7f98ed07b9934286b9c4809dd4d7a47537879
[package]
name = "rust-demangler"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
[dependencies]
regex = "1.0"
name = "rustbook"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[dependencies]
clap = "2.25.0"
description = """
Hack for the compiler's own build system
"""
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
[package]
name = "rustdoc-themes"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "rustdoc-themes"
[package]
name = "rustdoc-tool"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
# Cargo adds a number of paths to the dylib search path on windows, which results in
# the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
license = "Apache-2.0/MIT"
build = "build.rs"
categories = ["development-tools"]
-edition = "2018"
+edition = "2021"
[[bin]]
name = "rustfmt"
use regex::Regex;
use rustc_ast::visit;
use rustc_ast::{ast, ptr};
-use rustc_span::{symbol, BytePos, Span};
+use rustc_span::{symbol, BytePos, Span, DUMMY_SP};
use crate::attr::filter_inline_attrs;
use crate::comment::{
use crate::utils::*;
use crate::vertical::rewrite_with_alignment;
use crate::visitor::FmtVisitor;
-use crate::DEFAULT_VISIBILITY;
+
+const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
+ kind: ast::VisibilityKind::Inherited,
+ span: DUMMY_SP,
+ tokens: None,
+};
fn type_annotation_separator(config: &Config) -> &str {
colon_spaces(config)
format_header(context, self.prefix, self.ident, self.vis, offset)
}
- pub(crate) fn from_variant(variant: &'a ast::Variant) -> Self {
+ fn from_variant(variant: &'a ast::Variant) -> Self {
StructParts {
prefix: "",
ident: variant.ident,
use std::rc::Rc;
use rustc_ast::ast;
-use rustc_span::{symbol, DUMMY_SP};
+use rustc_span::symbol;
use thiserror::Error;
use crate::comment::LineClasses;
mod vertical;
pub(crate) mod visitor;
-const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
- kind: ast::VisibilityKind::Inherited,
- span: DUMMY_SP,
- tokens: None,
-};
/// The various errors that can occur during formatting. Note that not all of
/// these can currently be propagated to clients.
#[derive(Error, Debug)]
#[derive(Debug, Clone)]
struct ParsedMacroArg {
kind: MacroArgKind,
- span: Span,
}
impl ParsedMacroArg {
struct MacroArgParser {
/// Either a name of the next metavariable, a separator, or junk.
buf: String,
- /// The start position on the current buffer.
- lo: BytePos,
/// The first token of the current buffer.
start_tok: Token,
/// `true` if we are parsing a metavariable or a repeat.
is_meta_var: bool,
- /// The position of the last token.
- hi: BytePos,
/// The last token parsed.
last_tok: Token,
/// Holds the parsed arguments.
impl MacroArgParser {
fn new() -> MacroArgParser {
MacroArgParser {
- lo: BytePos(0),
- hi: BytePos(0),
buf: String::new(),
is_meta_var: false,
last_tok: Token {
}
fn set_last_tok(&mut self, tok: &TokenTree) {
- self.hi = tok.span().hi();
self.last_tok = last_tok(tok);
}
};
self.result.push(ParsedMacroArg {
kind: MacroArgKind::Separator(self.buf.clone(), prefix),
- span: mk_sp(self.lo, self.hi),
});
self.buf.clear();
}
};
self.result.push(ParsedMacroArg {
kind: MacroArgKind::Other(self.buf.clone(), prefix),
- span: mk_sp(self.lo, self.hi),
});
self.buf.clear();
}
match iter.next() {
Some(TokenTree::Token(Token {
kind: TokenKind::Ident(name, _),
- span,
+ ..
})) => {
self.result.push(ParsedMacroArg {
kind: MacroArgKind::MetaVariable(name, self.buf.clone()),
- span: mk_sp(self.lo, span.hi()),
});
self.buf.clear();
}
}
- fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken, span: Span) {
+ fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken) {
self.result.push(ParsedMacroArg {
kind: MacroArgKind::Delimited(delim, inner),
- span,
});
}
inner: Vec<ParsedMacroArg>,
delim: DelimToken,
iter: &mut Cursor,
- span: Span,
) -> Option<()> {
let mut buffer = String::new();
let mut first = true;
- let mut lo = span.lo();
- let mut hi = span.hi();
// Parse '*', '+' or '?.
for tok in iter {
self.set_last_tok(&tok);
if first {
first = false;
- lo = tok.span().lo();
}
match tok {
}
TokenTree::Token(ref t) => {
buffer.push_str(&pprust::token_to_string(&t));
- hi = t.span.hi();
}
_ => return None,
}
} else {
Some(Box::new(ParsedMacroArg {
kind: MacroArgKind::Other(buffer, "".to_owned()),
- span: mk_sp(lo, hi),
}))
};
self.result.push(ParsedMacroArg {
kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()),
- span: mk_sp(self.lo, self.hi),
});
Some(())
}
fn update_buffer(&mut self, t: &Token) {
if self.buf.is_empty() {
- self.lo = t.span.lo();
self.start_tok = t.clone();
} else {
let needs_space = match next_space(&self.last_tok.kind) {
// Start keeping the name of this metavariable in the buffer.
self.is_meta_var = true;
- self.lo = span.lo();
self.start_tok = Token {
kind: TokenKind::Dollar,
span,
self.add_meta_variable(&mut iter)?;
}
TokenTree::Token(ref t) => self.update_buffer(t),
- TokenTree::Delimited(delimited_span, delimited, ref tts) => {
+ TokenTree::Delimited(_delimited_span, delimited, ref tts) => {
if !self.buf.is_empty() {
if next_space(&self.last_tok.kind) == SpaceState::Always {
self.add_separator();
}
// Parse the stuff inside delimiters.
- let mut parser = MacroArgParser::new();
- parser.lo = delimited_span.open.lo();
+ let parser = MacroArgParser::new();
let delimited_arg = parser.parse(tts.clone())?;
- let span = delimited_span.entire();
if self.is_meta_var {
- self.add_repeat(delimited_arg, delimited, &mut iter, span)?;
+ self.add_repeat(delimited_arg, delimited, &mut iter)?;
self.is_meta_var = false;
} else {
- self.add_delimited(delimited_arg, delimited, span);
+ self.add_delimited(delimited_arg, delimited);
}
}
}
let data = delimited_span.entire().data();
(
data.hi,
- Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
+ Span::new(
+ data.lo + BytePos(1),
+ data.hi - BytePos(1),
+ data.ctxt,
+ data.parent,
+ ),
delimited_span.entire(),
)
}
pub(crate) struct Module<'a> {
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
- attrs: Cow<'a, Vec<ast::Attribute>>,
inner_attr: Vec<ast::Attribute>,
pub(crate) span: Span,
}
.collect();
Module {
items: mod_items,
- attrs: mod_attrs,
inner_attr,
span: mod_span,
ast_mod_kind,
use std::iter::ExactSizeIterator;
use std::ops::Deref;
-use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
-use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
+use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_span::{symbol::kw, BytePos, Pos, Span};
+use crate::comment::{combine_strs_with_missing_comments, contains_comment};
use crate::config::lists::*;
use crate::config::{IndentStyle, TypeDensity, Version};
use crate::expr::{
format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
};
-use crate::items::StructParts;
use crate::lists::{
definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
};
colon_spaces, extra_offset, first_line_width, format_extern, format_mutability,
last_line_extendable, last_line_width, mk_sp, rewrite_ident,
};
-use crate::DEFAULT_VISIBILITY;
-use crate::{
- comment::{combine_strs_with_missing_comments, contains_comment},
- items::format_struct_struct,
-};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum PathContext {
ast::TyKind::Tup(ref items) => {
rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
}
- ast::TyKind::AnonymousStruct(ref fields, recovered) => {
- let ident = Ident::new(
- kw::Struct,
- mk_sp(self.span.lo(), self.span.lo() + BytePos(6)),
- );
- let data = ast::VariantData::Struct(fields.clone(), recovered);
- let variant = ast::Variant {
- attrs: AttrVec::new(),
- id: self.id,
- span: self.span,
- vis: DEFAULT_VISIBILITY,
- ident,
- data,
- disr_expr: None,
- is_placeholder: false,
- };
- format_struct_struct(
- &context,
- &StructParts::from_variant(&variant),
- fields,
- shape.indent,
- None,
- )
- }
- ast::TyKind::AnonymousUnion(ref fields, recovered) => {
- let ident = Ident::new(
- kw::Union,
- mk_sp(self.span.lo(), self.span.lo() + BytePos(5)),
- );
- let data = ast::VariantData::Struct(fields.clone(), recovered);
- let variant = ast::Variant {
- attrs: AttrVec::new(),
- id: self.id,
- span: self.span,
- vis: DEFAULT_VISIBILITY,
- ident,
- data,
- disr_expr: None,
- is_placeholder: false,
- };
- format_struct_struct(
- &context,
- &StructParts::from_variant(&variant),
- fields,
- shape.indent,
- None,
- )
- }
ast::TyKind::Path(ref q_self, ref path) => {
rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
}
}
pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
- Span::new(lo, hi, SyntaxContext::root())
+ Span::new(lo, hi, SyntaxContext::root(), None)
}
pub(crate) fn mk_sp_lo_plus_one(lo: BytePos) -> Span {
- Span::new(lo, lo + BytePos(1), SyntaxContext::root())
+ Span::new(lo, lo + BytePos(1), SyntaxContext::root(), None)
}
// Returns `true` if the given span does not intersect with file lines.
[package]
name = "tidy"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
autobins = false
[dependencies]
"num-integer",
"num-traits",
"object",
+ "odht",
"once_cell",
"opaque-debug",
"parking_lot",
-//! Tidy check to ensure that crate `edition` is '2018'
+//! Tidy check to ensure that crate `edition` is '2018' or '2021'.
use std::path::Path;
fn is_edition_2018(mut line: &str) -> bool {
line = line.trim();
- line == "edition = \"2018\"" || line == "edition = \'2018\'"
+ line == "edition = \"2018\""
+}
+
+fn is_edition_2021(mut line: &str) -> bool {
+ line = line.trim();
+ line == "edition = \"2021\""
}
pub fn check(path: &Path, bad: &mut bool) {
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
+ let filestr = file.to_string_lossy().replace("\\", "/");
let filename = file.file_name().unwrap();
if filename != "Cargo.toml" {
return;
}
- let has_edition = contents.lines().any(is_edition_2018);
- if !has_edition {
- tidy_error!(
- bad,
- "{} doesn't have `edition = \"2018\"` on a separate line",
- file.display()
- );
+
+ // Library crates are not yet ready to migrate to 2021.
+ //
+ // The reference and rustc-dev-guide are submodules, so are left at
+ // 2018 for now. They should be removed from this exception list
+ // when bumped.
+ if path.components().any(|c| c.as_os_str() == "library")
+ || filestr.contains("src/doc/reference/style-check/Cargo.toml")
+ || filestr.contains("src/doc/rustc-dev-guide/ci/date-check/Cargo.toml")
+ {
+ let has = contents.lines().any(is_edition_2018);
+ if !has {
+ tidy_error!(
+ bad,
+ "{} doesn't have `edition = \"2018\"` on a separate line",
+ file.display()
+ );
+ }
+ } else {
+ let is_2021 = contents.lines().any(is_edition_2021);
+ if !is_2021 {
+ tidy_error!(
+ bad,
+ "{} doesn't have `edition = \"2021\"` on a separate line",
+ file.display()
+ );
+ }
}
},
);
pub mod extdeps;
pub mod features;
pub mod pal;
+pub mod primitive_docs;
pub mod style;
pub mod target_specific_tests;
pub mod ui_tests;
// Checks that only make sense for the std libs.
check!(pal, &library_path);
+ check!(primitive_docs, &library_path);
// Checks that need to be done for both the compiler and std libraries.
check!(unit_tests, &src_path);
--- /dev/null
+//! Tidy check to make sure `library/{std,core}/src/primitive_docs.rs` are the same file. These are
+//! different files so that relative links work properly without having to have `CARGO_PKG_NAME`
+//! set, but conceptually they should always be the same.
+
+use std::path::Path;
+
+pub fn check(library_path: &Path, bad: &mut bool) {
+ let std_name = "std/src/primitive_docs.rs";
+ let core_name = "core/src/primitive_docs.rs";
+ let std_contents = std::fs::read_to_string(library_path.join(std_name))
+ .unwrap_or_else(|e| panic!("failed to read library/{}: {}", std_name, e));
+ let core_contents = std::fs::read_to_string(library_path.join(core_name))
+ .unwrap_or_else(|e| panic!("failed to read library/{}: {}", core_name, e));
+ if std_contents != core_contents {
+ tidy_error!(bad, "library/{} and library/{} have different contents", core_name, std_name);
+ }
+}
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1345;
-const ISSUES_ENTRY_LIMIT: usize = 2525;
+const ROOT_ENTRY_LIMIT: usize = 1330;
+const ISSUES_ENTRY_LIMIT: usize = 2488;
fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
[package]
name = "tier-check"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
[package]
name = "unicode-bdd"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
name = "unstable-book-gen"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tidy = { path = "../tidy" }
name = "x"
version = "0.1.0"
description = "Run x.py slightly more conveniently"
-edition = "2018"
+edition = "2021"
publish = false