Auto merge of #81090 - ssomers:btree_drainy_refactor_2, r=Mark-Simulacrum
BTreeMap: offer merge in variants with more clarity
r? `@Mark-Simulacrum`
diff --git a/Cargo.lock b/Cargo.lock
index 5e5a48a..c2c06a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4400,7 +4400,7 @@
[[package]]
name = "rustfmt-nightly"
-version = "1.4.31"
+version = "1.4.32"
dependencies = [
"annotate-snippets 0.6.1",
"anyhow",
diff --git a/README.md b/README.md
index 07c0960..6ab11e7 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,4 @@
-<a href = "https://www.rust-lang.org/">
-<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
-</a>
+# The Rust Programming Language
This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 106ffb2..2124f1e 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -87,7 +87,6 @@
}
});
error?;
- buf.shrink_to_fit();
Symbol::intern(&buf)
} else {
symbol
@@ -105,7 +104,6 @@
}
});
error?;
- buf.shrink_to_fit();
LitKind::ByteStr(buf.into())
}
token::ByteStrRaw(_) => {
@@ -120,7 +118,6 @@
}
});
error?;
- buf.shrink_to_fit();
buf
} else {
symbol.to_string().into_bytes()
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index be5b247..8946ac4 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -824,7 +824,7 @@
}
ty => unreachable!("bswap {}", ty),
}
- };
+ }
let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T));
ret.write_cvalue(fx, res);
};
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 6c2a871..544ef38 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -214,11 +214,7 @@
}
pub fn target_cpu(sess: &Session) -> &str {
- let name = match sess.opts.cg.target_cpu {
- Some(ref s) => &**s,
- None => &*sess.target.cpu,
- };
-
+ let name = sess.opts.cg.target_cpu.as_ref().unwrap_or(&sess.target.cpu);
handle_native(name)
}
@@ -254,8 +250,6 @@
}
pub fn tune_cpu(sess: &Session) -> Option<&str> {
- match sess.opts.debugging_opts.tune_cpu {
- Some(ref s) => Some(handle_native(&**s)),
- None => None,
- }
+ let name = sess.opts.debugging_opts.tune_cpu.as_ref()?;
+ Some(handle_native(name))
}
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f47d2ad..2ce5fe5 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -29,7 +29,6 @@
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, EntryFnType};
-use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_target::abi::{Align, LayoutOf, VariantIdx};
@@ -817,32 +816,6 @@
}
tcx.sess.opts.optimize
};
-
- providers.dllimport_foreign_items = |tcx, krate| {
- let module_map = tcx.foreign_modules(krate);
-
- let dllimports = tcx
- .native_libraries(krate)
- .iter()
- .filter(|lib| {
- if !matches!(lib.kind, NativeLibKind::Dylib | NativeLibKind::Unspecified) {
- return false;
- }
- let cfg = match lib.cfg {
- Some(ref cfg) => cfg,
- None => return true,
- };
- attr::cfg_matches(cfg, &tcx.sess.parse_sess, None)
- })
- .filter_map(|lib| lib.foreign_module)
- .map(|id| &module_map[&id])
- .flat_map(|module| module.foreign_items.iter().cloned())
- .collect();
- dllimports
- };
-
- providers.is_dllimport_foreign_item =
- |tcx, def_id| tcx.dllimport_foreign_items(def_id.krate).contains(&def_id);
}
fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md
index fd96987..effa597 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0373.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0373.md
@@ -50,3 +50,24 @@
Now that the closure has its own copy of the data, there's no need to worry
about safety.
+
+This error may also be encountered while using `async` blocks:
+
+```compile_fail,E0373,edition2018
+use std::future::Future;
+
+async fn f() {
+ let v = vec![1, 2, 3i32];
+ spawn(async { //~ ERROR E0373
+ println!("{:?}", v)
+ });
+}
+
+fn spawn<F: Future + Send + 'static>(future: F) {
+ unimplemented!()
+}
+```
+
+Similarly to closures, `async` blocks are not executed immediately and may
+capture closed-over data by reference. For more information, see
+https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 8373304..e8c711c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -56,36 +56,11 @@
};
}
-/// Instead of e.g. `vec![a, b, c]` in a pattern context, suggest `[a, b, c]`.
-fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Parser<'_>) {
- let mut suggestion = None;
- if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
- if let Some(bang) = code.find('!') {
- suggestion = Some(code[bang + 1..].to_string());
- }
- }
- if let Some(suggestion) = suggestion {
- e.span_suggestion(
- site_span,
- "use a slice pattern here instead",
- suggestion,
- Applicability::MachineApplicable,
- );
- } else {
- e.span_label(site_span, "use a slice pattern here instead");
- }
- e.help(
- "for more information, see https://doc.rust-lang.org/edition-guide/\
- rust-2018/slice-patterns.html",
- );
-}
-
fn emit_frag_parse_err(
mut e: DiagnosticBuilder<'_>,
parser: &Parser<'_>,
orig_parser: &mut Parser<'_>,
site_span: Span,
- macro_ident: Ident,
arm_span: Span,
kind: AstFragmentKind,
) {
@@ -113,9 +88,6 @@
e.span_label(site_span, "in this macro invocation");
}
match kind {
- AstFragmentKind::Pat if macro_ident.name == sym::vec => {
- suggest_slice_pat(&mut e, site_span, parser);
- }
// Try a statement if an expression is wanted but failed and suggest adding `;` to call.
AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) {
Err(mut err) => err.cancel(),
@@ -143,7 +115,7 @@
let fragment = match parse_ast_fragment(parser, kind) {
Ok(f) => f,
Err(err) => {
- emit_frag_parse_err(err, parser, snapshot, site_span, macro_ident, arm_span, kind);
+ emit_frag_parse_err(err, parser, snapshot, site_span, arm_span, kind);
return kind.dummy(site_span);
}
};
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 4ede9d6..a81eb74 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -5,6 +5,7 @@
use rustc_ast::NodeId;
use rustc_macros::HashStable_Generic;
use rustc_span::hygiene::MacroKind;
+use rustc_span::Symbol;
use std::array::IntoIter;
use std::fmt::Debug;
@@ -34,7 +35,7 @@
#[derive(HashStable_Generic)]
pub enum NonMacroAttrKind {
/// Single-segment attribute defined by the language (`#[inline]`)
- Builtin,
+ Builtin(Symbol),
/// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
@@ -371,7 +372,7 @@
impl NonMacroAttrKind {
pub fn descr(self) -> &'static str {
match self {
- NonMacroAttrKind::Builtin => "built-in attribute",
+ NonMacroAttrKind::Builtin(..) => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => {
"derive helper attribute"
@@ -393,7 +394,7 @@
NonMacroAttrKind::Tool
| NonMacroAttrKind::DeriveHelper
| NonMacroAttrKind::DeriveHelperCompat => true,
- NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
+ NonMacroAttrKind::Builtin(..) | NonMacroAttrKind::Registered => false,
}
}
}
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 71ce50f..4357eb3 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -530,10 +530,10 @@
let atom = match k1.unpack() {
GenericArgKind::Lifetime(r1) => {
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
}
GenericArgKind::Type(t1) => {
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t1, r2))
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t1, r2))
}
GenericArgKind::Const(..) => {
// Consts cannot outlive one another, so we don't expect to
@@ -541,8 +541,7 @@
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
}
};
- let predicate =
- predicate.rebind(atom).potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
+ let predicate = predicate.rebind(atom).to_predicate(self.tcx);
Obligation::new(cause.clone(), param_env, predicate)
})
@@ -664,7 +663,7 @@
self.obligations.push(Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
- predicate: ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(sup, sub))
+ predicate: ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(sup, sub))
.to_predicate(self.infcx.tcx),
recursion_depth: 0,
});
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index e38eebe..b344086 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -358,7 +358,7 @@
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
- ty::PredicateAtom::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
+ ty::PredicateKind::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
));
}
@@ -451,9 +451,9 @@
b: &'tcx ty::Const<'tcx>,
) {
let predicate = if a_is_expected {
- ty::PredicateAtom::ConstEquate(a, b)
+ ty::PredicateKind::ConstEquate(a, b)
} else {
- ty::PredicateAtom::ConstEquate(b, a)
+ ty::PredicateKind::ConstEquate(b, a)
};
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index fee6f87..c39daea 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1706,8 +1706,8 @@
for (predicate, _) in bounds {
let predicate = predicate.subst(self.tcx, substs);
- if let ty::PredicateAtom::Projection(projection_predicate) =
- predicate.skip_binders()
+ if let ty::PredicateKind::Projection(projection_predicate) =
+ predicate.kind().skip_binder()
{
if projection_predicate.projection_ty.item_def_id == item_def_id {
// We don't account for multiple `Future::Output = Ty` contraints.
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index de98ccc..07c75d5 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -6,7 +6,6 @@
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty;
-use rustc_middle::ty::fold::TypeFoldable;
pub fn explicit_outlives_bounds<'tcx>(
param_env: ty::ParamEnv<'tcx>,
@@ -15,20 +14,20 @@
param_env
.caller_bounds()
.into_iter()
- .map(ty::Predicate::skip_binders)
- .filter(|atom| !atom.has_escaping_bound_vars())
- .filter_map(move |atom| match atom {
- ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::Trait(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
+ .map(ty::Predicate::kind)
+ .filter_map(ty::Binder::no_bound_vars)
+ .filter_map(move |kind| match kind {
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
Some(OutlivesBound::RegionSubRegion(r_b, r_a))
}
})
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index a676c5e..6687198 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -100,7 +100,7 @@
self.fields.obligations.push(Obligation::new(
self.fields.trace.cause.clone(),
self.fields.param_env,
- ty::PredicateAtom::Subtype(ty::SubtypePredicate {
+ ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: self.a_is_expected,
a,
b,
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8273c2d..13cf1e10 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -9,13 +9,8 @@
tcx: TyCtxt<'tcx>,
pred: ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
- match *pred.kind() {
- ty::PredicateKind::ForAll(binder) => {
- let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
- tcx.reuse_or_mk_predicate(pred, new)
- }
- ty::PredicateKind::Atom(_) => pred,
- }
+ let new = tcx.anonymize_late_bound_regions(pred.kind());
+ tcx.reuse_or_mk_predicate(pred, new)
}
struct PredicateSet<'tcx> {
@@ -126,9 +121,9 @@
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
let tcx = self.visited.tcx;
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(data, _) => {
+ ty::PredicateKind::Trait(data, _) => {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
@@ -150,36 +145,36 @@
self.stack.extend(obligations);
}
- ty::PredicateAtom::WellFormed(..) => {
+ ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
// although we easily could.
}
- ty::PredicateAtom::ObjectSafe(..) => {
+ ty::PredicateKind::ObjectSafe(..) => {
// Currently, we do not elaborate object-safe
// predicates.
}
- ty::PredicateAtom::Subtype(..) => {
+ ty::PredicateKind::Subtype(..) => {
// Currently, we do not "elaborate" predicates like `X <: Y`,
// though conceivably we might.
}
- ty::PredicateAtom::Projection(..) => {
+ ty::PredicateKind::Projection(..) => {
// Nothing to elaborate in a projection predicate.
}
- ty::PredicateAtom::ClosureKind(..) => {
+ ty::PredicateKind::ClosureKind(..) => {
// Nothing to elaborate when waiting for a closure's kind to be inferred.
}
- ty::PredicateAtom::ConstEvaluatable(..) => {
+ ty::PredicateKind::ConstEvaluatable(..) => {
// Currently, we do not elaborate const-evaluatable
// predicates.
}
- ty::PredicateAtom::ConstEquate(..) => {
+ ty::PredicateKind::ConstEquate(..) => {
// Currently, we do not elaborate const-equate
// predicates.
}
- ty::PredicateAtom::RegionOutlives(..) => {
+ ty::PredicateKind::RegionOutlives(..) => {
// Nothing to elaborate from `'a: 'b`.
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
// We know that `T: 'a` for some type `T`. We can
// often elaborate this. For example, if we know that
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -209,7 +204,7 @@
if r.is_late_bound() {
None
} else {
- Some(ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
+ Some(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
r, r_min,
)))
}
@@ -217,7 +212,7 @@
Component::Param(p) => {
let ty = tcx.mk_ty_param(p.index, p.name);
- Some(ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(
+ Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
ty, r_min,
)))
}
@@ -242,7 +237,7 @@
}),
);
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
// Nothing to elaborate
}
}
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 4e393df..8cdb33e 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1550,13 +1550,13 @@
impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::fold::TypeFoldable;
- use rustc_middle::ty::PredicateAtom::*;
+ use rustc_middle::ty::PredicateKind::*;
if cx.tcx.features().trivial_bounds {
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.predicates_of(def_id);
for &(predicate, span) in predicates.predicates {
- let predicate_kind_name = match predicate.skip_binders() {
+ let predicate_kind_name = match predicate.kind().skip_binder() {
Trait(..) => "Trait",
TypeOutlives(..) |
RegionOutlives(..) => "Lifetime",
@@ -1936,8 +1936,8 @@
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
- .filter_map(|(pred, _)| match pred.skip_binders() {
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a {
+ .filter_map(|(pred, _)| match pred.kind().skip_binder() {
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a {
ty::ReEarlyBound(ebr) if ebr.index == index => Some(b),
_ => None,
},
@@ -1952,8 +1952,8 @@
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
- .filter_map(|(pred, _)| match pred.skip_binders() {
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
+ .filter_map(|(pred, _)| match pred.kind().skip_binder() {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
a.is_param(index).then_some(b)
}
_ => None,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 0f40324..3971a30 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -354,10 +354,23 @@
lint_name.to_string()
};
// If the lint was scoped with `tool::` check if the tool lint exists
- if tool_name.is_some() {
+ if let Some(tool_name) = tool_name {
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
- None => return CheckLintNameResult::Tool(Err((None, String::new()))),
+ // If the lint isn't registered, there are two possibilities:
+ None => {
+ // 1. The tool is currently running, so this lint really doesn't exist.
+ // FIXME: should this handle tools that never register a lint, like rustfmt?
+ tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
+ let tool_prefix = format!("{}::", tool_name);
+ return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
+ self.no_lint_suggestion(&complete_name)
+ } else {
+ // 2. The tool isn't currently running, so no lints will be registered.
+ // To avoid giving a false positive, ignore all unknown lints.
+ CheckLintNameResult::Tool(Err((None, String::new())))
+ };
+ }
Some(LintGroup { lint_ids, .. }) => {
return CheckLintNameResult::Tool(Ok(&lint_ids));
}
@@ -398,6 +411,21 @@
}
}
+ fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
+ let name_lower = lint_name.to_lowercase();
+ let symbols =
+ self.get_lints().iter().map(|l| Symbol::intern(&l.name_lower())).collect::<Vec<_>>();
+
+ if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
+ // First check if the lint name is (partly) in upper case instead of lower case...
+ CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)))
+ } else {
+ // ...if not, search for lints with a similar name
+ let suggestion = find_best_match_for_name(&symbols, Symbol::intern(&name_lower), None);
+ CheckLintNameResult::NoLint(suggestion)
+ }
+ }
+
fn check_tool_name_for_backwards_compat(
&self,
lint_name: &str,
@@ -407,18 +435,7 @@
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
// Now we are sure, that this lint exists nowhere
- None => {
- let symbols =
- self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
-
- let suggestion = find_best_match_for_name(
- &symbols,
- Symbol::intern(&lint_name.to_lowercase()),
- None,
- );
-
- CheckLintNameResult::NoLint(suggestion)
- }
+ None => self.no_lint_suggestion(lint_name),
Some(LintGroup { lint_ids, depr, .. }) => {
// Reaching this would be weird, but let's cover this case anyway
if let Some(LintAlias { name, silent }) = depr {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 37bdc87..fc8f844 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -381,6 +381,11 @@
src,
Some(li.span().into()),
|lint| {
+ let name = if let Some(tool_name) = tool_name {
+ format!("{}::{}", tool_name, name)
+ } else {
+ name.to_string()
+ };
let mut db = lint.build(&format!("unknown lint: `{}`", name));
if let Some(suggestion) = suggestion {
db.span_suggestion(
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index d4f7903..b031c11 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -45,12 +45,12 @@
impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
- use rustc_middle::ty::PredicateAtom::*;
+ use rustc_middle::ty::PredicateKind::*;
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.explicit_predicates_of(def_id);
for &(predicate, span) in predicates.predicates {
- let trait_predicate = match predicate.skip_binders() {
+ let trait_predicate = match predicate.kind().skip_binder() {
Trait(trait_predicate, _constness) => trait_predicate,
_ => continue,
};
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index bc7363a..c1a3eec 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -202,8 +202,8 @@
let mut has_emitted = false;
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
// We only look at the `DefId`, so it is safe to skip the binder here.
- if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
- predicate.skip_binders()
+ if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
+ predicate.kind().skip_binder()
{
let def_id = poly_trait_predicate.trait_ref.def_id;
let descr_pre =
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e963279..20052ad 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4,7 +4,7 @@
//! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`.
-use crate::{declare_lint, declare_lint_pass, declare_tool_lint};
+use crate::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
@@ -2825,8 +2825,29 @@
};
}
-declare_tool_lint! {
- pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
+declare_lint! {
+ /// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used.
+ ///
+ /// ### Example
+ ///
+ /// ```compile_fail
+ /// #![feature(staged_api)]
+ ///
+ /// #[derive(Clone)]
+ /// #[stable(feature = "x", since = "1")]
+ /// struct S {}
+ ///
+ /// #[unstable(feature = "y", issue = "none")]
+ /// impl Copy for S {}
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// `staged_api` does not currently support using a stability attribute on `impl` blocks.
+ /// `impl`s are always stable if both the type and trait are stable, and always unstable otherwise.
+ pub INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
Deny,
"detects `#[unstable]` on stable trait implementations for stable types"
}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 58931bc..5e26742 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -46,7 +46,7 @@
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
- predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+ predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
interpret_allocs: FxIndexSet<interpret::AllocId>,
@@ -328,7 +328,7 @@
&mut self.type_shorthands
}
- fn predicate_shorthands(&mut self) -> &mut FxHashMap<rustc_middle::ty::Predicate<'tcx>, usize> {
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
&mut self.predicate_shorthands
}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9770e67..00ee7b8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1281,11 +1281,6 @@
}
Other {
- query dllimport_foreign_items(_: CrateNum)
- -> FxHashSet<DefId> {
- storage(ArenaCacheSelector<'tcx>)
- desc { "dllimport_foreign_items" }
- }
query is_dllimport_foreign_item(def_id: DefId) -> bool {
desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) }
}
@@ -1316,7 +1311,7 @@
desc { "looking up a named region" }
}
query is_late_bound_map(_: LocalDefId) ->
- Option<&'tcx FxHashSet<ItemLocalId>> {
+ Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
desc { "testing if a region is late bound" }
}
query object_lifetime_defaults_map(_: LocalDefId)
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 9d37150..a7b0ff4 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -43,10 +43,12 @@
}
}
-impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
type Variant = ty::PredicateKind<'tcx>;
+
+ #[inline]
fn variant(&self) -> &Self::Variant {
- self.kind()
+ self
}
}
@@ -55,7 +57,7 @@
fn position(&self) -> usize;
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
- fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize>;
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
fn encode_alloc_id(&mut self, alloc_id: &AllocId) -> Result<(), Self::Error>;
}
@@ -118,9 +120,15 @@
}
}
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<ty::PredicateKind<'tcx>> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
+ }
+}
+
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
- encode_with_shorthand(e, self, TyEncoder::predicate_shorthands)
+ self.kind().encode(e)
}
}
@@ -218,18 +226,24 @@
}
}
-impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
- fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<ty::PredicateKind<'tcx>> {
+ fn decode(decoder: &mut D) -> Result<ty::Binder<ty::PredicateKind<'tcx>>, D::Error> {
// Handle shorthands first, if we have an usize > 0x80.
- let predicate_kind = if decoder.positioned_at_shorthand() {
+ Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() {
let pos = decoder.read_usize()?;
assert!(pos >= SHORTHAND_OFFSET);
let shorthand = pos - SHORTHAND_OFFSET;
- decoder.with_position(shorthand, ty::PredicateKind::decode)
+ decoder.with_position(shorthand, ty::PredicateKind::decode)?
} else {
- ty::PredicateKind::decode(decoder)
- }?;
+ ty::PredicateKind::decode(decoder)?
+ }))
+ }
+}
+
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
+ fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+ let predicate_kind = Decodable::decode(decoder)?;
let predicate = decoder.tcx().mk_predicate(predicate_kind);
Ok(predicate)
}
@@ -457,3 +471,28 @@
}
}
}
+
+macro_rules! impl_binder_encode_decode {
+ ($($t:ty),+ $(,)?) => {
+ $(
+ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Binder<$t> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ self.as_ref().skip_binder().encode(e)
+ }
+ }
+ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<$t> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ Ok(ty::Binder::bind(Decodable::decode(decoder)?))
+ }
+ }
+ )*
+ }
+}
+
+impl_binder_encode_decode! {
+ &'tcx ty::List<Ty<'tcx>>,
+ ty::FnSig<'tcx>,
+ ty::ExistentialPredicate<'tcx>,
+ ty::TraitRef<'tcx>,
+ Vec<ty::GeneratorInteriorTypeCause<'tcx>>,
+}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index a355242..1cbf761 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -3,6 +3,7 @@
use crate::arena::Arena;
use crate::dep_graph::DepGraph;
use crate::hir::exports::ExportMap;
+use crate::hir::place::Place as HirPlace;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
@@ -17,9 +18,9 @@
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::TyKind::*;
use crate::ty::{
- self, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree,
- ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntVar,
- IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
+ self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
+ DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
+ IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
TyVid, TypeAndMut, Visibility,
};
@@ -133,7 +134,7 @@
}
#[inline(never)]
- fn intern_predicate(&self, kind: PredicateKind<'tcx>) -> &'tcx PredicateInner<'tcx> {
+ fn intern_predicate(&self, kind: Binder<PredicateKind<'tcx>>) -> &'tcx PredicateInner<'tcx> {
self.predicate
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_predicate(kind);
@@ -379,7 +380,7 @@
/// Records the reasons that we picked the kind of each closure;
/// not all closures are present in the map.
- closure_kind_origins: ItemLocalMap<(Span, Symbol)>,
+ closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
/// For each fn, records the "liberated" types of its arguments
/// and return type. Liberated means that all bound regions
@@ -642,11 +643,13 @@
self.upvar_capture_map[&upvar_id]
}
- pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, Symbol)> {
+ pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
}
- pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<'_, (Span, Symbol)> {
+ pub fn closure_kind_origins_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
}
@@ -1948,8 +1951,8 @@
}
}
-impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateInner<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
+impl<'tcx> Borrow<Binder<PredicateKind<'tcx>>> for Interned<'tcx, PredicateInner<'tcx>> {
+ fn borrow<'a>(&'a self) -> &'a Binder<PredicateKind<'tcx>> {
&self.0.kind
}
}
@@ -1987,12 +1990,6 @@
}
}
-impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateKind<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
- &self.0
- }
-}
-
macro_rules! direct_interners {
($($name:ident: $method:ident($ty:ty),)+) => {
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
@@ -2091,8 +2088,8 @@
}
#[inline]
- pub fn mk_predicate(self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> {
- let inner = self.interners.intern_predicate(kind);
+ pub fn mk_predicate(self, binder: Binder<PredicateKind<'tcx>>) -> Predicate<'tcx> {
+ let inner = self.interners.intern_predicate(binder);
Predicate { inner }
}
@@ -2100,9 +2097,9 @@
pub fn reuse_or_mk_predicate(
self,
pred: Predicate<'tcx>,
- kind: PredicateKind<'tcx>,
+ binder: Binder<PredicateKind<'tcx>>,
) -> Predicate<'tcx> {
- if *pred.kind() != kind { self.mk_predicate(kind) } else { pred }
+ if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
}
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
@@ -2578,7 +2575,8 @@
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
+ self.is_late_bound_map(id.owner)
+ .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id))
}
pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 4de3d15..6ecd1eb 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -22,9 +22,9 @@
result
}
- pub fn for_predicate(kind: ty::PredicateKind<'_>) -> FlagComputation {
+ pub fn for_predicate(binder: ty::Binder<ty::PredicateKind<'_>>) -> FlagComputation {
let mut result = FlagComputation::new();
- result.add_predicate_kind(kind);
+ result.add_predicate(binder);
result
}
@@ -204,53 +204,46 @@
}
}
- fn add_predicate_kind(&mut self, kind: ty::PredicateKind<'_>) {
- match kind {
- ty::PredicateKind::ForAll(binder) => {
- self.bound_computation(binder, |computation, atom| {
- computation.add_predicate_atom(atom)
- });
- }
- ty::PredicateKind::Atom(atom) => self.add_predicate_atom(atom),
- }
+ fn add_predicate(&mut self, binder: ty::Binder<ty::PredicateKind<'_>>) {
+ self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom));
}
- fn add_predicate_atom(&mut self, atom: ty::PredicateAtom<'_>) {
+ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
match atom {
- ty::PredicateAtom::Trait(trait_pred, _constness) => {
+ ty::PredicateKind::Trait(trait_pred, _constness) => {
self.add_substs(trait_pred.trait_ref.substs);
}
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
self.add_region(a);
self.add_region(b);
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, region)) => {
self.add_ty(ty);
self.add_region(region);
}
- ty::PredicateAtom::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
+ ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
self.add_ty(a);
self.add_ty(b);
}
- ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
+ ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
self.add_projection_ty(projection_ty);
self.add_ty(ty);
}
- ty::PredicateAtom::WellFormed(arg) => {
+ ty::PredicateKind::WellFormed(arg) => {
self.add_substs(slice::from_ref(&arg));
}
- ty::PredicateAtom::ObjectSafe(_def_id) => {}
- ty::PredicateAtom::ClosureKind(_def_id, substs, _kind) => {
+ ty::PredicateKind::ObjectSafe(_def_id) => {}
+ ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
self.add_substs(substs);
}
- ty::PredicateAtom::ConstEvaluatable(_def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
self.add_substs(substs);
}
- ty::PredicateAtom::ConstEquate(expected, found) => {
+ ty::PredicateKind::ConstEquate(expected, found) => {
self.add_const(expected);
self.add_const(found);
}
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
self.add_ty(ty);
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 1399fc7..c6970df 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -17,7 +17,9 @@
pub use self::Variance::*;
use crate::hir::exports::ExportMap;
-use crate::hir::place::Place as HirPlace;
+use crate::hir::place::{
+ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
+};
use crate::ich::StableHashingContext;
use crate::middle::cstore::CrateStoreDyn;
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
@@ -734,6 +736,43 @@
pub info: CaptureInfo<'tcx>,
}
+pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
+ let name = match place.base {
+ HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
+ _ => bug!("Capture_information should only contain upvars"),
+ };
+ let mut curr_string = name;
+
+ for (i, proj) in place.projections.iter().enumerate() {
+ match proj.kind {
+ HirProjectionKind::Deref => {
+ curr_string = format!("*{}", curr_string);
+ }
+ HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
+ ty::Adt(def, ..) => {
+ curr_string = format!(
+ "{}.{}",
+ curr_string,
+ def.variants[variant].fields[idx as usize].ident.name.as_str()
+ );
+ }
+ ty::Tuple(_) => {
+ curr_string = format!("{}.{}", curr_string, idx);
+ }
+ _ => {
+ bug!(
+ "Field projection applied to a type other than Adt or Tuple: {:?}.",
+ place.ty_before_projection(i).kind()
+ )
+ }
+ },
+ proj => bug!("{:?} unexpected because it isn't captured", proj),
+ }
+ }
+
+ curr_string.to_string()
+}
+
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
/// for a particular capture as well as identifying the part of the source code
/// that triggered this capture to occur.
@@ -1030,14 +1069,14 @@
#[derive(Debug)]
crate struct PredicateInner<'tcx> {
- kind: PredicateKind<'tcx>,
+ kind: Binder<PredicateKind<'tcx>>,
flags: TypeFlags,
/// See the comment for the corresponding field of [TyS].
outer_exclusive_binder: ty::DebruijnIndex,
}
#[cfg(target_arch = "x86_64")]
-static_assert_size!(PredicateInner<'_>, 48);
+static_assert_size!(PredicateInner<'_>, 40);
#[derive(Clone, Copy, Lift)]
pub struct Predicate<'tcx> {
@@ -1060,59 +1099,9 @@
impl<'tcx> Eq for Predicate<'tcx> {}
impl<'tcx> Predicate<'tcx> {
- #[inline(always)]
- pub fn kind(self) -> &'tcx PredicateKind<'tcx> {
- &self.inner.kind
- }
-
- /// Returns the inner `PredicateAtom`.
- ///
- /// The returned atom may contain unbound variables bound to binders skipped in this method.
- /// It is safe to reapply binders to the given atom.
- ///
- /// Note that this method panics in case this predicate has unbound variables.
- pub fn skip_binders(self) -> PredicateAtom<'tcx> {
- match self.kind() {
- &PredicateKind::ForAll(binder) => binder.skip_binder(),
- &PredicateKind::Atom(atom) => {
- debug_assert!(!atom.has_escaping_bound_vars());
- atom
- }
- }
- }
-
- /// Returns the inner `PredicateAtom`.
- ///
- /// Note that this method does not check if the predicate has unbound variables.
- ///
- /// Rebinding the returned atom can causes the previously bound variables
- /// to end up at the wrong binding level.
- pub fn skip_binders_unchecked(self) -> PredicateAtom<'tcx> {
- match self.kind() {
- &PredicateKind::ForAll(binder) => binder.skip_binder(),
- &PredicateKind::Atom(atom) => atom,
- }
- }
-
- /// Converts this to a `Binder<PredicateAtom<'tcx>>`. If the value was an
- /// `Atom`, then it is not allowed to contain escaping bound vars.
- pub fn bound_atom(self) -> Binder<PredicateAtom<'tcx>> {
- match self.kind() {
- &PredicateKind::ForAll(binder) => binder,
- &PredicateKind::Atom(atom) => {
- debug_assert!(!atom.has_escaping_bound_vars());
- Binder::dummy(atom)
- }
- }
- }
-
- /// Allows using a `Binder<PredicateAtom<'tcx>>` even if the given predicate previously
- /// contained unbound variables by shifting these variables outwards.
- pub fn bound_atom_with_opt_escaping(self, tcx: TyCtxt<'tcx>) -> Binder<PredicateAtom<'tcx>> {
- match self.kind() {
- &PredicateKind::ForAll(binder) => binder,
- &PredicateKind::Atom(atom) => Binder::wrap_nonbinding(tcx, atom),
- }
+ /// Gets the inner `Binder<PredicateKind<'tcx>>`.
+ pub fn kind(self) -> Binder<PredicateKind<'tcx>> {
+ self.inner.kind
}
}
@@ -1134,14 +1123,6 @@
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum PredicateKind<'tcx> {
- /// `for<'a>: ...`
- ForAll(Binder<PredicateAtom<'tcx>>),
- Atom(PredicateAtom<'tcx>),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable)]
-pub enum PredicateAtom<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
@@ -1187,21 +1168,6 @@
TypeWellFormedFromEnv(Ty<'tcx>),
}
-impl<'tcx> Binder<PredicateAtom<'tcx>> {
- /// Wraps `self` with the given qualifier if this predicate has any unbound variables.
- pub fn potentially_quantified(
- self,
- tcx: TyCtxt<'tcx>,
- qualifier: impl FnOnce(Binder<PredicateAtom<'tcx>>) -> PredicateKind<'tcx>,
- ) -> Predicate<'tcx> {
- match self.no_bound_vars() {
- Some(atom) => PredicateKind::Atom(atom),
- None => qualifier(self),
- }
- .to_predicate(tcx)
- }
-}
-
/// The crate outlives map is computed during typeck and contains the
/// outlives of every item in the local crate. You should not use it
/// directly, because to do so will make your pass dependent on the
@@ -1287,13 +1253,9 @@
// from the substitution and the value being substituted into, and
// this trick achieves that).
let substs = trait_ref.skip_binder().substs;
- let pred = self.skip_binders();
+ let pred = self.kind().skip_binder();
let new = pred.subst(tcx, substs);
- if new != pred {
- ty::Binder::bind(new).potentially_quantified(tcx, PredicateKind::ForAll)
- } else {
- self
- }
+ tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new))
}
}
@@ -1414,24 +1376,23 @@
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
}
-impl ToPredicate<'tcx> for PredicateKind<'tcx> {
+impl ToPredicate<'tcx> for Binder<PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self)
}
}
-impl ToPredicate<'tcx> for PredicateAtom<'tcx> {
+impl ToPredicate<'tcx> for PredicateKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- debug_assert!(!self.has_escaping_bound_vars(), "escaping bound vars for {:?}", self);
- tcx.mk_predicate(PredicateKind::Atom(self))
+ tcx.mk_predicate(Binder::dummy(self))
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- PredicateAtom::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
+ PredicateKind::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
.to_predicate(tcx)
}
}
@@ -1448,66 +1409,62 @@
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.value
- .map_bound(|value| PredicateAtom::Trait(value, self.constness))
- .potentially_quantified(tcx, PredicateKind::ForAll)
+ self.value.map_bound(|value| PredicateKind::Trait(value, self.constness)).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateAtom::RegionOutlives)
- .potentially_quantified(tcx, PredicateKind::ForAll)
+ self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateAtom::TypeOutlives)
- .potentially_quantified(tcx, PredicateKind::ForAll)
+ self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateAtom::Projection).potentially_quantified(tcx, PredicateKind::ForAll)
+ self.map_bound(PredicateKind::Projection).to_predicate(tcx)
}
}
impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
- let predicate = self.bound_atom();
+ let predicate = self.kind();
match predicate.skip_binder() {
- PredicateAtom::Trait(t, constness) => {
+ PredicateKind::Trait(t, constness) => {
Some(ConstnessAnd { constness, value: predicate.rebind(t.trait_ref) })
}
- PredicateAtom::Projection(..)
- | PredicateAtom::Subtype(..)
- | PredicateAtom::RegionOutlives(..)
- | PredicateAtom::WellFormed(..)
- | PredicateAtom::ObjectSafe(..)
- | PredicateAtom::ClosureKind(..)
- | PredicateAtom::TypeOutlives(..)
- | PredicateAtom::ConstEvaluatable(..)
- | PredicateAtom::ConstEquate(..)
- | PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ PredicateKind::Projection(..)
+ | PredicateKind::Subtype(..)
+ | PredicateKind::RegionOutlives(..)
+ | PredicateKind::WellFormed(..)
+ | PredicateKind::ObjectSafe(..)
+ | PredicateKind::ClosureKind(..)
+ | PredicateKind::TypeOutlives(..)
+ | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::ConstEquate(..)
+ | PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
- let predicate = self.bound_atom();
+ let predicate = self.kind();
match predicate.skip_binder() {
- PredicateAtom::TypeOutlives(data) => Some(predicate.rebind(data)),
- PredicateAtom::Trait(..)
- | PredicateAtom::Projection(..)
- | PredicateAtom::Subtype(..)
- | PredicateAtom::RegionOutlives(..)
- | PredicateAtom::WellFormed(..)
- | PredicateAtom::ObjectSafe(..)
- | PredicateAtom::ClosureKind(..)
- | PredicateAtom::ConstEvaluatable(..)
- | PredicateAtom::ConstEquate(..)
- | PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ PredicateKind::TypeOutlives(data) => Some(predicate.rebind(data)),
+ PredicateKind::Trait(..)
+ | PredicateKind::Projection(..)
+ | PredicateKind::Subtype(..)
+ | PredicateKind::RegionOutlives(..)
+ | PredicateKind::WellFormed(..)
+ | PredicateKind::ObjectSafe(..)
+ | PredicateKind::ClosureKind(..)
+ | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::ConstEquate(..)
+ | PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8935727..8911de4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -623,12 +623,8 @@
p!("impl");
for (predicate, _) in bounds {
let predicate = predicate.subst(self.tcx(), substs);
- // Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
- // may contain unbound variables. We therefore do this manually.
- //
- // FIXME(lcnr): Find out why exactly this is the case :)
- let bound_predicate = predicate.bound_atom_with_opt_escaping(self.tcx());
- if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+ let bound_predicate = predicate.kind();
+ if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
@@ -2068,40 +2064,38 @@
}
ty::Predicate<'tcx> {
- match self.kind() {
- &ty::PredicateKind::Atom(atom) => p!(print(atom)),
- ty::PredicateKind::ForAll(binder) => p!(print(binder)),
- }
+ let binder = self.kind();
+ p!(print(binder))
}
- ty::PredicateAtom<'tcx> {
+ ty::PredicateKind<'tcx> {
match *self {
- ty::PredicateAtom::Trait(ref data, constness) => {
+ ty::PredicateKind::Trait(ref data, constness) => {
if let hir::Constness::Const = constness {
p!("const ");
}
p!(print(data))
}
- ty::PredicateAtom::Subtype(predicate) => p!(print(predicate)),
- ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
- ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
- ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
- ty::PredicateAtom::WellFormed(arg) => p!(print(arg), " well-formed"),
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
+ ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)),
+ ty::PredicateKind::Projection(predicate) => p!(print(predicate)),
+ ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
- ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
p!("the closure `",
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
- ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def, substs) => {
p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
p!("the type `", print(ty), "` is found in the environment")
}
}
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index 6003509..cfe4700 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -989,7 +989,7 @@
tcx: TyCtxt<'tcx>,
encoder: &'a mut E,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
- predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+ predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
interpret_allocs: FxIndexSet<interpret::AllocId>,
source_map: CachingSourceMapView<'tcx>,
file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
@@ -1103,7 +1103,7 @@
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
&mut self.type_shorthands
}
- fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize> {
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
&mut self.predicate_shorthands
}
fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7a1ca6a..44c173e 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -231,37 +231,28 @@
impl fmt::Debug for ty::PredicateKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ty::PredicateKind::ForAll(binder) => write!(f, "ForAll({:?})", binder),
- ty::PredicateKind::Atom(atom) => write!(f, "{:?}", atom),
- }
- }
-}
-
-impl fmt::Debug for ty::PredicateAtom<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- ty::PredicateAtom::Trait(ref a, constness) => {
+ ty::PredicateKind::Trait(ref a, constness) => {
if let hir::Constness::Const = constness {
write!(f, "const ")?;
}
a.fmt(f)
}
- ty::PredicateAtom::Subtype(ref pair) => pair.fmt(f),
- ty::PredicateAtom::RegionOutlives(ref pair) => pair.fmt(f),
- ty::PredicateAtom::TypeOutlives(ref pair) => pair.fmt(f),
- ty::PredicateAtom::Projection(ref pair) => pair.fmt(f),
- ty::PredicateAtom::WellFormed(data) => write!(f, "WellFormed({:?})", data),
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
+ ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f),
+ ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f),
+ ty::PredicateKind::Projection(ref pair) => pair.fmt(f),
+ ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data),
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({:?})", trait_def_id)
}
- ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
- ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
}
- ty::PredicateAtom::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
}
@@ -485,46 +476,36 @@
type Lifted = ty::PredicateKind<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
- ty::PredicateKind::ForAll(binder) => tcx.lift(binder).map(ty::PredicateKind::ForAll),
- ty::PredicateKind::Atom(atom) => tcx.lift(atom).map(ty::PredicateKind::Atom),
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for ty::PredicateAtom<'a> {
- type Lifted = ty::PredicateAtom<'tcx>;
- fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
- match self {
- ty::PredicateAtom::Trait(data, constness) => {
- tcx.lift(data).map(|data| ty::PredicateAtom::Trait(data, constness))
+ ty::PredicateKind::Trait(data, constness) => {
+ tcx.lift(data).map(|data| ty::PredicateKind::Trait(data, constness))
}
- ty::PredicateAtom::Subtype(data) => tcx.lift(data).map(ty::PredicateAtom::Subtype),
- ty::PredicateAtom::RegionOutlives(data) => {
- tcx.lift(data).map(ty::PredicateAtom::RegionOutlives)
+ ty::PredicateKind::Subtype(data) => tcx.lift(data).map(ty::PredicateKind::Subtype),
+ ty::PredicateKind::RegionOutlives(data) => {
+ tcx.lift(data).map(ty::PredicateKind::RegionOutlives)
}
- ty::PredicateAtom::TypeOutlives(data) => {
- tcx.lift(data).map(ty::PredicateAtom::TypeOutlives)
+ ty::PredicateKind::TypeOutlives(data) => {
+ tcx.lift(data).map(ty::PredicateKind::TypeOutlives)
}
- ty::PredicateAtom::Projection(data) => {
- tcx.lift(data).map(ty::PredicateAtom::Projection)
+ ty::PredicateKind::Projection(data) => {
+ tcx.lift(data).map(ty::PredicateKind::Projection)
}
- ty::PredicateAtom::WellFormed(ty) => tcx.lift(ty).map(ty::PredicateAtom::WellFormed),
- ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::WellFormed(ty) => tcx.lift(ty).map(ty::PredicateKind::WellFormed),
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
tcx.lift(closure_substs).map(|closure_substs| {
- ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind)
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
})
}
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
- Some(ty::PredicateAtom::ObjectSafe(trait_def_id))
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
+ Some(ty::PredicateKind::ObjectSafe(trait_def_id))
}
- ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
- tcx.lift(substs).map(|substs| ty::PredicateAtom::ConstEvaluatable(def_id, substs))
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+ tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
- tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateAtom::ConstEquate(c1, c2))
+ ty::PredicateKind::ConstEquate(c1, c2) => {
+ tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
}
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
- tcx.lift(ty).map(ty::PredicateAtom::TypeWellFormedFromEnv)
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
+ tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv)
}
}
}
@@ -1036,12 +1017,12 @@
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- let new = ty::PredicateKind::super_fold_with(self.inner.kind, folder);
+ let new = self.inner.kind.fold_with(folder);
folder.tcx().reuse_or_mk_predicate(self, new)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- ty::PredicateKind::super_visit_with(&self.inner.kind, visitor)
+ self.inner.kind.visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d43c513..e53977b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -955,7 +955,9 @@
/// erase, or otherwise "discharge" these bound vars, we change the
/// type from `Binder<T>` to just `T` (see
/// e.g., `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+///
+/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct Binder<T>(T);
impl<T> Binder<T> {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index db02ee6..a5fb8a1 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -141,6 +141,7 @@
self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
let mut is_loop_move = false;
+ let mut in_pattern = false;
for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
@@ -256,6 +257,7 @@
"ref ".to_string(),
Applicability::MachineApplicable,
);
+ in_pattern = true;
}
if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
@@ -302,7 +304,8 @@
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;
- if is_loop_move {
+ // If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
+ if is_loop_move & !in_pattern {
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
err.span_suggestion_verbose(
@@ -1318,21 +1321,30 @@
Applicability::MachineApplicable,
);
- let msg = match category {
+ match category {
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
- format!("{} is returned here", kind)
+ let msg = format!("{} is returned here", kind);
+ err.span_note(constraint_span, &msg);
}
ConstraintCategory::CallArgument => {
fr_name.highlight_region_name(&mut err);
- format!("function requires argument type to outlive `{}`", fr_name)
+ if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
+ err.note(
+ "async blocks are not executed immediately and must either take a \
+ reference or ownership of outside variables they use",
+ );
+ } else {
+ let msg = format!("function requires argument type to outlive `{}`", fr_name);
+ err.span_note(constraint_span, &msg);
+ }
}
_ => bug!(
"report_escaping_closure_capture called with unexpected constraint \
category: `{:?}`",
category
),
- };
- err.span_note(constraint_span, &msg);
+ }
+
err
}
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index 4ebc1cd..9f97d5c 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -103,7 +103,7 @@
let did = did.expect_local();
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
- if let Some((span, name)) =
+ if let Some((span, hir_place)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
{
diag.span_note(
@@ -111,7 +111,7 @@
&format!(
"closure cannot be invoked more than once because it moves the \
variable `{}` out of its environment",
- name,
+ ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
return;
@@ -127,7 +127,7 @@
let did = did.expect_local();
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
- if let Some((span, name)) =
+ if let Some((span, hir_place)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
{
diag.span_note(
@@ -135,7 +135,7 @@
&format!(
"closure cannot be moved more than once as it is not `Copy` due to \
moving the variable `{}` out of its environment",
- name
+ ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
}
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index 78da43c..ab83fc8 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -590,8 +590,8 @@
let mut found = false;
for (bound, _) in bounds {
- if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) =
- bound.skip_binders()
+ if let ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_, r)) =
+ bound.kind().skip_binder()
{
let r = r.subst(self.infcx.tcx, substs);
if let ty::RegionKind::ReStatic = r {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
index b7d22fa..157959b 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
@@ -39,10 +39,8 @@
user_provided_sig = None;
} else {
let typeck_results = self.tcx().typeck(mir_def_id);
- user_provided_sig = match typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id())
- {
- None => None,
- Some(user_provided_poly_sig) => {
+ user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
+ |user_provided_poly_sig| {
// Instantiate the canonicalized variables from
// user-provided signature (e.g., the `_` in the code
// above) with fresh variables.
@@ -54,18 +52,16 @@
// Replace the bound items in the fn sig with fresh
// variables, so that they represent the view from
// "inside" the closure.
- Some(
- self.infcx
- .replace_bound_vars_with_fresh_vars(
- body.span,
- LateBoundRegionConversionTime::FnCall,
- poly_sig,
- )
- .0,
- )
- }
- }
- };
+ self.infcx
+ .replace_bound_vars_with_fresh_vars(
+ body.span,
+ LateBoundRegionConversionTime::FnCall,
+ poly_sig,
+ )
+ .0
+ },
+ );
+ }
debug!(
"equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 5aad752..fb9820e 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1014,7 +1014,7 @@
}
self.prove_predicate(
- ty::PredicateAtom::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
+ ty::PredicateKind::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
Locations::All(span),
ConstraintCategory::TypeAnnotation,
);
@@ -1266,7 +1266,7 @@
obligations.obligations.push(traits::Obligation::new(
ObligationCause::dummy(),
param_env,
- ty::PredicateAtom::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
+ ty::PredicateKind::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
));
obligations.add(
infcx
@@ -1611,7 +1611,7 @@
self.check_call_dest(body, term, &sig, destination, term_location);
self.prove_predicates(
- sig.inputs_and_output.iter().map(|ty| ty::PredicateAtom::WellFormed(ty.into())),
+ sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty.into())),
term_location.to_locations(),
ConstraintCategory::Boring,
);
@@ -2694,7 +2694,7 @@
category: ConstraintCategory,
) {
self.prove_predicates(
- Some(ty::PredicateAtom::Trait(
+ Some(ty::PredicateKind::Trait(
ty::TraitPredicate { trait_ref },
hir::Constness::NotConst,
)),
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
index c1a0d98..02d951b 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
@@ -788,13 +788,13 @@
fn_def_id: DefId,
mut f: impl FnMut(ty::Region<'tcx>),
) {
- if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
- for late_bound in late_bounds.iter() {
- let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound };
+ if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
+ for &late_bound in late_bounds.iter() {
+ let hir_id = HirId { owner, local_id: late_bound };
let name = tcx.hir().name(hir_id);
let region_def_id = tcx.hir().local_def_id(hir_id);
let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: fn_def_id,
+ scope: owner.to_def_id(),
bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
}));
f(liberated_region);
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index d1c07d1..88b2378 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -411,24 +411,24 @@
loop {
let predicates = tcx.predicates_of(current);
for (predicate, _) in predicates.predicates {
- match predicate.skip_binders() {
- ty::PredicateAtom::RegionOutlives(_)
- | ty::PredicateAtom::TypeOutlives(_)
- | ty::PredicateAtom::WellFormed(_)
- | ty::PredicateAtom::Projection(_)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
- ty::PredicateAtom::ObjectSafe(_) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Projection(_)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+ ty::PredicateKind::ObjectSafe(_) => {
bug!("object safe predicate on function: {:#?}", predicate)
}
- ty::PredicateAtom::ClosureKind(..) => {
+ ty::PredicateKind::ClosureKind(..) => {
bug!("closure kind predicate on function: {:#?}", predicate)
}
- ty::PredicateAtom::Subtype(_) => {
+ ty::PredicateKind::Subtype(_) => {
bug!("subtype predicate on function: {:#?}", predicate)
}
- ty::PredicateAtom::Trait(pred, constness) => {
+ ty::PredicateKind::Trait(pred, constness) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index e64955c..0732d25 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -223,13 +223,6 @@
// Check for raw pointer `Deref`.
for (base, proj) in place.iter_projections() {
if proj == ProjectionElem::Deref {
- let source_info = self.source_info; // Backup source_info so we can restore it later.
- if base.projection.is_empty() && decl.internal {
- // Internal locals are used in the `move_val_init` desugaring.
- // We want to check unsafety against the source info of the
- // desugaring, rather than the source info of the RHS.
- self.source_info = self.body.local_decls[place.local].source_info;
- }
let base_ty = base.ty(self.body, self.tcx).ty;
if base_ty.is_unsafe_ptr() {
self.require_unsafe(
@@ -237,7 +230,6 @@
UnsafetyViolationDetails::DerefOfRawPointer,
)
}
- self.source_info = source_info; // Restore backed-up source_info.
}
}
diff --git a/compiler/rustc_mir/src/transform/function_item_references.rs b/compiler/rustc_mir/src/transform/function_item_references.rs
index 7c8c349..8d02ac6 100644
--- a/compiler/rustc_mir/src/transform/function_item_references.rs
+++ b/compiler/rustc_mir/src/transform/function_item_references.rs
@@ -5,7 +5,7 @@
use rustc_middle::ty::{
self,
subst::{GenericArgKind, Subst, SubstsRef},
- PredicateAtom, Ty, TyCtxt, TyS,
+ PredicateKind, Ty, TyCtxt, TyS,
};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{symbol::sym, Span};
@@ -105,7 +105,7 @@
let param_env = self.tcx.param_env(def_id);
let bounds = param_env.caller_bounds();
for bound in bounds {
- if let Some(bound_ty) = self.is_pointer_trait(&bound.skip_binders()) {
+ if let Some(bound_ty) = self.is_pointer_trait(&bound.kind().skip_binder()) {
// Get the argument types as they appear in the function signature.
let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
@@ -131,8 +131,8 @@
}
/// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
- fn is_pointer_trait(&self, bound: &PredicateAtom<'tcx>) -> Option<Ty<'tcx>> {
- if let ty::PredicateAtom::Trait(predicate, _) = bound {
+ fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
+ if let ty::PredicateKind::Trait(predicate, _) = bound {
if self.tcx.is_diagnostic_item(sym::pointer_trait, predicate.def_id()) {
Some(predicate.trait_ref.self_ty())
} else {
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 9777a97..639f2bb 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -10,9 +10,7 @@
use rustc_hir as hir;
use rustc_middle::middle::region;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation};
-use rustc_span::symbol::sym;
-use rustc_target::spec::abi::Abi;
+use rustc_middle::ty::{CanonicalUserTypeAnnotation};
use std::slice;
@@ -219,79 +217,41 @@
},
)
}
- ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
- let intrinsic = match *ty.kind() {
- ty::FnDef(def_id, _) => {
- let f = ty.fn_sig(this.hir.tcx());
- if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
- Some(this.hir.tcx().item_name(def_id))
- } else {
- None
- }
- }
- _ => None,
- };
+ ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => {
let fun = unpack!(block = this.as_local_operand(block, fun));
- if let Some(sym::move_val_init) = intrinsic {
- // `move_val_init` has "magic" semantics - the second argument is
- // always evaluated "directly" into the first one.
+ let args: Vec<_> = args
+ .into_iter()
+ .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
+ .collect();
- let mut args = args.into_iter();
- let ptr = args.next().expect("0 arguments to `move_val_init`");
- let val = args.next().expect("1 argument to `move_val_init`");
- assert!(args.next().is_none(), ">2 arguments to `move_val_init`");
+ let success = this.cfg.start_new_block();
- let ptr = this.hir.mirror(ptr);
- let ptr_ty = ptr.ty;
- // Create an *internal* temp for the pointer, so that unsafety
- // checking won't complain about the raw pointer assignment.
- let ptr_temp = this
- .local_decls
- .push(LocalDecl::with_source_info(ptr_ty, source_info).internal());
- let ptr_temp = Place::from(ptr_temp);
- // No need for a scope, ptr_temp doesn't need drop
- let block = unpack!(this.into(ptr_temp, None, block, ptr));
- // Maybe we should provide a scope here so that
- // `move_val_init` wouldn't leak on panic even with an
- // arbitrary `val` expression, but `schedule_drop`,
- // borrowck and drop elaboration all prevent us from
- // dropping `ptr_temp.deref()`.
- this.into(this.hir.tcx().mk_place_deref(ptr_temp), None, block, val)
- } else {
- let args: Vec<_> = args
- .into_iter()
- .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
- .collect();
+ this.record_operands_moved(&args);
- let success = this.cfg.start_new_block();
+ debug!("into_expr: fn_span={:?}", fn_span);
- this.record_operands_moved(&args);
-
- debug!("into_expr: fn_span={:?}", fn_span);
-
- this.cfg.terminate(
- block,
- source_info,
- TerminatorKind::Call {
- func: fun,
- args,
- cleanup: None,
- // FIXME(varkor): replace this with an uninhabitedness-based check.
- // This requires getting access to the current module to call
- // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
- destination: if expr.ty.is_never() {
- None
- } else {
- Some((destination, success))
- },
- from_hir_call,
- fn_span,
+ this.cfg.terminate(
+ block,
+ source_info,
+ TerminatorKind::Call {
+ func: fun,
+ args,
+ cleanup: None,
+ // FIXME(varkor): replace this with an uninhabitedness-based check.
+ // This requires getting access to the current module to call
+ // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
+ destination: if expr.ty.is_never() {
+ None
+ } else {
+ Some((destination, success))
},
- );
- this.diverge_from(block);
- schedule_drop(this);
- success.unit()
- }
+ from_hir_call,
+ fn_span,
+ },
+ );
+ this.diverge_from(block);
+ schedule_drop(this);
+ success.unit()
}
ExprKind::Use { source } => this.into(destination, scope, block, source),
ExprKind::Borrow { arg, borrow_kind } => {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index fb007c4..66206ca 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -100,19 +100,19 @@
}
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref }, _) => {
self.visit_trait(trait_ref)
}
- ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
+ ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
ty.visit_with(self)?;
self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx()))
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
ty.visit_with(self)
}
- ty::PredicateAtom::RegionOutlives(..) => ControlFlow::CONTINUE,
- ty::PredicateAtom::ConstEvaluatable(..)
+ ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
+ ty::PredicateKind::ConstEvaluatable(..)
if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
{
// FIXME(const_evaluatable_checked): If the constant used here depends on a
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index e96fc18..4ab14c1 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -115,7 +115,7 @@
self.get_module(parent_id)
}
- crate fn get_module(&mut self, def_id: DefId) -> Module<'a> {
+ pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
// If this is a local module, it will be in `module_map`, no need to recalculate it.
if let Some(def_id) = def_id.as_local() {
return self.module_map[&def_id];
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4f8047a..69fb687 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -683,7 +683,7 @@
));
}
Scope::BuiltinAttrs => {
- let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
+ let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
if filter_fn(res) {
suggestions.extend(
BUILTIN_ATTRIBUTES
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9de35a8..97e556f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -14,7 +14,6 @@
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::*;
-use rustc_ast::{unwrap_or, walk_list};
use rustc_ast_lowering::ResolverAstLowering;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::DiagnosticId;
@@ -1911,7 +1910,7 @@
// it needs to be added to the trait map.
if ns == ValueNS {
let item_name = path.last().unwrap().ident;
- let traits = self.get_traits_containing_item(item_name, ns);
+ let traits = self.traits_in_scope(item_name, ns);
self.r.trait_map.insert(id, traits);
}
@@ -2371,12 +2370,12 @@
// field, we need to add any trait methods we find that match
// the field name so that we can do some nice error reporting
// later on in typeck.
- let traits = self.get_traits_containing_item(ident, ValueNS);
+ let traits = self.traits_in_scope(ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
ExprKind::MethodCall(ref segment, ..) => {
debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
- let traits = self.get_traits_containing_item(segment.ident, ValueNS);
+ let traits = self.traits_in_scope(segment.ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
}
_ => {
@@ -2385,64 +2384,13 @@
}
}
- fn get_traits_containing_item(
- &mut self,
- mut ident: Ident,
- ns: Namespace,
- ) -> Vec<TraitCandidate> {
- debug!("(getting traits containing item) looking for '{}'", ident.name);
-
- let mut found_traits = Vec::new();
- // Look for the current trait.
- if let Some((module, _)) = self.current_trait_ref {
- if self
- .r
- .resolve_ident_in_module(
- ModuleOrUniformRoot::Module(module),
- ident,
- ns,
- &self.parent_scope,
- false,
- module.span,
- )
- .is_ok()
- {
- let def_id = module.def_id().unwrap();
- found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
- }
- }
-
- ident.span = ident.span.normalize_to_macros_2_0();
- let mut search_module = self.parent_scope.module;
- loop {
- self.r.get_traits_in_module_containing_item(
- ident,
- ns,
- search_module,
- &mut found_traits,
- &self.parent_scope,
- );
- let mut span_data = ident.span.data();
- search_module = unwrap_or!(
- self.r.hygienic_lexical_parent(search_module, &mut span_data.ctxt),
- break
- );
- ident.span = span_data.span();
- }
-
- if let Some(prelude) = self.r.prelude {
- if !search_module.no_implicit_prelude {
- self.r.get_traits_in_module_containing_item(
- ident,
- ns,
- prelude,
- &mut found_traits,
- &self.parent_scope,
- );
- }
- }
-
- found_traits
+ fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> {
+ self.r.traits_in_scope(
+ self.current_trait_ref.as_ref().map(|(module, _)| *module),
+ &self.parent_scope,
+ ident.span.ctxt(),
+ Some((ident.name, ns)),
+ )
}
}
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index aab5c3c..1be06a4 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -11,7 +11,8 @@
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE};
+use rustc_hir::hir_id::ItemLocalId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind};
@@ -20,6 +21,7 @@
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
+use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use std::borrow::Cow;
@@ -284,7 +286,7 @@
resolve_lifetimes,
named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id),
- is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id),
+ is_late_bound_map,
object_lifetime_defaults_map: |tcx, id| {
tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id)
},
@@ -320,6 +322,32 @@
rl
}
+fn is_late_bound_map<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
+ match tcx.def_kind(def_id) {
+ DefKind::AnonConst => {
+ let mut def_id = tcx
+ .parent(def_id.to_def_id())
+ .unwrap_or_else(|| bug!("anon const or closure without a parent"));
+ // We search for the next outer anon const or fn here
+ // while skipping closures.
+ //
+ // Note that for `AnonConst` we still just recurse until we
+ // find a function body, but who cares :shrug:
+ while tcx.is_closure(def_id) {
+ def_id = tcx
+ .parent(def_id)
+ .unwrap_or_else(|| bug!("anon const or closure without a parent"));
+ }
+
+ tcx.is_late_bound_map(def_id.expect_local())
+ }
+ _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)),
+ }
+}
+
fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
let krate = tcx.hir().krate();
let mut map = NamedRegionMap {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index c5b8f7d..af53416 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -44,9 +44,9 @@
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::hir::exports::ExportMap;
use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
+use rustc_middle::span_bug;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, ResolverOutputs};
-use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::Session;
@@ -1477,52 +1477,79 @@
self.crate_loader.postprocess(krate);
}
- fn get_traits_in_module_containing_item(
+ pub fn traits_in_scope(
&mut self,
- ident: Ident,
- ns: Namespace,
- module: Module<'a>,
- found_traits: &mut Vec<TraitCandidate>,
+ current_trait: Option<Module<'a>>,
parent_scope: &ParentScope<'a>,
+ ctxt: SyntaxContext,
+ assoc_item: Option<(Symbol, Namespace)>,
+ ) -> Vec<TraitCandidate> {
+ let mut found_traits = Vec::new();
+
+ if let Some(module) = current_trait {
+ if self.trait_may_have_item(Some(module), assoc_item) {
+ let def_id = module.def_id().unwrap();
+ found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] });
+ }
+ }
+
+ self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
+ match scope {
+ Scope::Module(module) => {
+ this.traits_in_module(module, assoc_item, &mut found_traits);
+ }
+ Scope::StdLibPrelude => {
+ if let Some(module) = this.prelude {
+ this.traits_in_module(module, assoc_item, &mut found_traits);
+ }
+ }
+ Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {}
+ _ => unreachable!(),
+ }
+ None::<()>
+ });
+
+ found_traits
+ }
+
+ fn traits_in_module(
+ &mut self,
+ module: Module<'a>,
+ assoc_item: Option<(Symbol, Namespace)>,
+ found_traits: &mut Vec<TraitCandidate>,
) {
- assert!(ns == TypeNS || ns == ValueNS);
module.ensure_traits(self);
let traits = module.traits.borrow();
-
- for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
- // Traits have pseudo-modules that can be used to search for the given ident.
- if let Some(module) = binding.module() {
- let mut ident = ident;
- if ident.span.glob_adjust(module.expansion, binding.span).is_none() {
- continue;
- }
- if self
- .resolve_ident_in_module_unadjusted(
- ModuleOrUniformRoot::Module(module),
- ident,
- ns,
- parent_scope,
- false,
- module.span,
- )
- .is_ok()
- {
- let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
- let trait_def_id = module.def_id().unwrap();
- found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
- }
- } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() {
- // For now, just treat all trait aliases as possible candidates, since we don't
- // know if the ident is somewhere in the transitive bounds.
- let import_ids = self.find_transitive_imports(&binding.kind, trait_name);
- let trait_def_id = binding.res().def_id();
- found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids });
- } else {
- bug!("candidate is not trait or trait alias?")
+ for (trait_name, trait_binding) in traits.as_ref().unwrap().iter() {
+ if self.trait_may_have_item(trait_binding.module(), assoc_item) {
+ let def_id = trait_binding.res().def_id();
+ let import_ids = self.find_transitive_imports(&trait_binding.kind, *trait_name);
+ found_traits.push(TraitCandidate { def_id, import_ids });
}
}
}
+ // List of traits in scope is pruned on best effort basis. We reject traits not having an
+ // associated item with the given name and namespace (if specified). This is a conservative
+ // optimization, proper hygienic type-based resolution of associated items is done in typeck.
+ // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
+ // associated items.
+ fn trait_may_have_item(
+ &mut self,
+ trait_module: Option<Module<'a>>,
+ assoc_item: Option<(Symbol, Namespace)>,
+ ) -> bool {
+ match (trait_module, assoc_item) {
+ (Some(trait_module), Some((name, ns))) => {
+ self.resolutions(trait_module).borrow().iter().any(|resolution| {
+ let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution;
+ assoc_ns == ns && assoc_ident.name == name
+ })
+ }
+ _ => true,
+ }
+ }
+
fn find_transitive_imports(
&mut self,
mut kind: &NameBindingKind<'_>,
@@ -3227,34 +3254,6 @@
})
}
- /// This is equivalent to `get_traits_in_module_containing_item`, but without filtering by the associated item.
- ///
- /// This is used by rustdoc for intra-doc links.
- pub fn traits_in_scope(&mut self, module_id: DefId) -> Vec<TraitCandidate> {
- let module = self.get_module(module_id);
- module.ensure_traits(self);
- let traits = module.traits.borrow();
- let to_candidate =
- |this: &mut Self, &(trait_name, binding): &(Ident, &NameBinding<'_>)| TraitCandidate {
- def_id: binding.res().def_id(),
- import_ids: this.find_transitive_imports(&binding.kind, trait_name),
- };
-
- let mut candidates: Vec<_> =
- traits.as_ref().unwrap().iter().map(|x| to_candidate(self, x)).collect();
-
- if let Some(prelude) = self.prelude {
- if !module.no_implicit_prelude {
- prelude.ensure_traits(self);
- candidates.extend(
- prelude.traits.borrow().as_ref().unwrap().iter().map(|x| to_candidate(self, x)),
- );
- }
- }
-
- candidates
- }
-
/// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>`
/// isn't something that can be returned because it can't be made to live that long,
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 5c74094..5d6120c 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -757,7 +757,11 @@
}
Scope::BuiltinAttrs => {
if is_builtin_attr_name(ident.name) {
- ok(Res::NonMacroAttr(NonMacroAttrKind::Builtin), DUMMY_SP, this.arenas)
+ ok(
+ Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)),
+ DUMMY_SP,
+ this.arenas,
+ )
} else {
Err(Determinacy::Determined)
}
@@ -810,13 +814,15 @@
// Found another solution, if the first one was "weak", report an error.
let (res, innermost_res) = (binding.res(), innermost_binding.res());
if res != innermost_res {
- let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
+ let is_builtin = |res| {
+ matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..)))
+ };
let derive_helper_compat =
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
let ambiguity_error_kind = if is_import {
Some(AmbiguityKind::Import)
- } else if innermost_res == builtin || res == builtin {
+ } else if is_builtin(innermost_res) || is_builtin(res) {
Some(AmbiguityKind::BuiltinAttr)
} else if innermost_res == derive_helper_compat
|| res == derive_helper_compat
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index b6cf584..63f95a3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -716,7 +716,6 @@
more_struct_aliases,
movbe_target_feature,
move_ref_pattern,
- move_val_init,
mul,
mul_assign,
mul_with_overflow,
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index f5bc90e..25ba489 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -1153,7 +1153,7 @@
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
for predicate in &bounds {
- if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() {
+ 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 ty_var;
@@ -1251,18 +1251,18 @@
traits::elaborate_predicates(tcx, predicates)
.filter_map(|obligation| {
debug!("required_region_bounds(obligation={:?})", obligation);
- match obligation.predicate.skip_binders() {
- ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::Trait(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
+ match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index f8fe141..6593c10 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -414,9 +414,9 @@
let mut should_add_new = true;
user_computed_preds.retain(|&old_pred| {
if let (
- ty::PredicateAtom::Trait(new_trait, _),
- ty::PredicateAtom::Trait(old_trait, _),
- ) = (new_pred.skip_binders(), old_pred.skip_binders())
+ ty::PredicateKind::Trait(new_trait, _),
+ ty::PredicateKind::Trait(old_trait, _),
+ ) = (new_pred.kind().skip_binder(), old_pred.kind().skip_binder())
{
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.trait_ref.substs;
@@ -633,16 +633,16 @@
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
- let bound_predicate = predicate.bound_atom();
+ let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(p, _) => {
+ ty::PredicateKind::Trait(p, _) => {
// Add this to `predicates` so that we end up calling `select`
// with it. If this predicate ends up being unimplemented,
// then `evaluate_predicates` will handle adding it the `ParamEnv`
// if possible.
predicates.push_back(bound_predicate.rebind(p));
}
- ty::PredicateAtom::Projection(p) => {
+ ty::PredicateKind::Projection(p) => {
let p = bound_predicate.rebind(p);
debug!(
"evaluate_nested_obligations: examining projection predicate {:?}",
@@ -772,13 +772,13 @@
}
}
}
- ty::PredicateAtom::RegionOutlives(binder) => {
+ ty::PredicateKind::RegionOutlives(binder) => {
let binder = bound_predicate.rebind(binder);
if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
return false;
}
}
- ty::PredicateAtom::TypeOutlives(binder) => {
+ ty::PredicateKind::TypeOutlives(binder) => {
let binder = bound_predicate.rebind(binder);
match (
binder.no_bound_vars(),
@@ -801,7 +801,7 @@
_ => {}
};
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
let evaluate = |c: &'tcx ty::Const<'tcx>| {
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
match select.infcx().const_eval_resolve(
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 370ad57..ad229e0 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -41,8 +41,8 @@
// We are looking at a generic abstract constant.
Some(ct) => {
for pred in param_env.caller_bounds() {
- match pred.skip_binders() {
- ty::PredicateAtom::ConstEvaluatable(b_def, b_substs) => {
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
debug!(
"is_const_evaluatable: caller_bound={:?}, {:?}",
b_def, b_substs
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 795cf2e..3eeb503 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -256,9 +256,9 @@
return;
}
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(trait_predicate, _) => {
+ ty::PredicateKind::Trait(trait_predicate, _) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
@@ -517,14 +517,14 @@
err
}
- ty::PredicateAtom::Subtype(predicate) => {
+ ty::PredicateKind::Subtype(predicate) => {
// Errors for Subtype predicates show up as
// `FulfillmentErrorCode::CodeSubtypeError`,
// not selection error.
span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
}
- ty::PredicateAtom::RegionOutlives(predicate) => {
+ ty::PredicateKind::RegionOutlives(predicate) => {
let predicate = bound_predicate.rebind(predicate);
let predicate = self.resolve_vars_if_possible(predicate);
let err = self
@@ -541,7 +541,7 @@
)
}
- ty::PredicateAtom::Projection(..) | ty::PredicateAtom::TypeOutlives(..) => {
+ ty::PredicateKind::Projection(..) | ty::PredicateKind::TypeOutlives(..) => {
let predicate = self.resolve_vars_if_possible(obligation.predicate);
struct_span_err!(
self.tcx.sess,
@@ -552,12 +552,12 @@
)
}
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
report_object_safety_error(self.tcx, span, trait_def_id, violations)
}
- ty::PredicateAtom::ClosureKind(closure_def_id, closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
let found_kind = self.closure_kind(closure_substs).unwrap();
let closure_span =
self.tcx.sess.source_map().guess_head_span(
@@ -589,23 +589,23 @@
if let Some(typeck_results) = self.in_progress_typeck_results {
let typeck_results = typeck_results.borrow();
match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
- (ty::ClosureKind::FnOnce, Some((span, name))) => {
+ (ty::ClosureKind::FnOnce, Some((span, place))) => {
err.span_label(
*span,
format!(
"closure is `FnOnce` because it moves the \
variable `{}` out of its environment",
- name
+ ty::place_to_string_for_capture(tcx, place)
),
);
}
- (ty::ClosureKind::FnMut, Some((span, name))) => {
+ (ty::ClosureKind::FnMut, Some((span, place))) => {
err.span_label(
*span,
format!(
"closure is `FnMut` because it mutates the \
variable `{}` here",
- name
+ ty::place_to_string_for_capture(tcx, place)
),
);
}
@@ -617,7 +617,7 @@
return;
}
- ty::PredicateAtom::WellFormed(ty) => {
+ ty::PredicateKind::WellFormed(ty) => {
if !self.tcx.sess.opts.debugging_opts.chalk {
// WF predicates cannot themselves make
// errors. They can only block due to
@@ -635,7 +635,7 @@
}
}
- ty::PredicateAtom::ConstEvaluatable(..) => {
+ ty::PredicateKind::ConstEvaluatable(..) => {
// Errors for `ConstEvaluatable` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
@@ -646,7 +646,7 @@
)
}
- ty::PredicateAtom::ConstEquate(..) => {
+ ty::PredicateKind::ConstEquate(..) => {
// Errors for `ConstEquate` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
@@ -657,7 +657,7 @@
)
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => span_bug!(
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
span,
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
@@ -1069,9 +1069,9 @@
}
// FIXME: It should be possible to deal with `ForAll` in a cleaner way.
- let bound_error = error.bound_atom();
- let (cond, error) = match (cond.skip_binders(), bound_error.skip_binder()) {
- (ty::PredicateAtom::Trait(..), ty::PredicateAtom::Trait(error, _)) => {
+ let bound_error = error.kind();
+ let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) {
+ (ty::PredicateKind::Trait(..), ty::PredicateKind::Trait(error, _)) => {
(cond, bound_error.rebind(error))
}
_ => {
@@ -1081,8 +1081,8 @@
};
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
- let bound_predicate = obligation.predicate.bound_atom();
- if let ty::PredicateAtom::Trait(implication, _) = bound_predicate.skip_binder() {
+ let bound_predicate = obligation.predicate.kind();
+ if let ty::PredicateKind::Trait(implication, _) = bound_predicate.skip_binder() {
let error = error.to_poly_trait_ref();
let implication = bound_predicate.rebind(implication.trait_ref);
// FIXME: I'm just not taking associated types at all here.
@@ -1162,8 +1162,8 @@
//
// this can fail if the problem was higher-ranked, in which
// cause I have no idea for a good error message.
- let bound_predicate = predicate.bound_atom();
- if let ty::PredicateAtom::Projection(data) = bound_predicate.skip_binder() {
+ let bound_predicate = predicate.kind();
+ if let ty::PredicateKind::Projection(data) = bound_predicate.skip_binder() {
let mut selcx = SelectionContext::new(self);
let (data, _) = self.replace_bound_vars_with_fresh_vars(
obligation.cause.span,
@@ -1452,9 +1452,9 @@
return;
}
- let bound_predicate = predicate.bound_atom();
+ let bound_predicate = predicate.kind();
let mut err = match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(data, _) => {
+ ty::PredicateKind::Trait(data, _) => {
let trait_ref = bound_predicate.rebind(data.trait_ref);
debug!("trait_ref {:?}", trait_ref);
@@ -1559,7 +1559,7 @@
err
}
- ty::PredicateAtom::WellFormed(arg) => {
+ ty::PredicateKind::WellFormed(arg) => {
// Same hacky approach as above to avoid deluging user
// with error messages.
if arg.references_error() || self.tcx.sess.has_errors() {
@@ -1569,7 +1569,7 @@
self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282)
}
- ty::PredicateAtom::Subtype(data) => {
+ ty::PredicateKind::Subtype(data) => {
if data.references_error() || self.tcx.sess.has_errors() {
// no need to overload user in such cases
return;
@@ -1579,7 +1579,7 @@
assert!(a.is_ty_var() && b.is_ty_var());
self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282)
}
- ty::PredicateAtom::Projection(data) => {
+ ty::PredicateKind::Projection(data) => {
let trait_ref = bound_predicate.rebind(data).to_poly_trait_ref(self.tcx);
let self_ty = trait_ref.skip_binder().self_ty();
let ty = data.ty;
@@ -1709,9 +1709,10 @@
obligation: &PredicateObligation<'tcx>,
) {
let (pred, item_def_id, span) =
- match (obligation.predicate.skip_binders(), obligation.cause.code.peel_derives()) {
+ match (obligation.predicate.kind().skip_binder(), obligation.cause.code.peel_derives())
+ {
(
- ty::PredicateAtom::Trait(pred, _),
+ ty::PredicateKind::Trait(pred, _),
&ObligationCauseCode::BindingObligation(item_def_id, span),
) => (pred, item_def_id, span),
_ => return,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 565b8d3..1830aaa 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1292,8 +1292,8 @@
// the type. The last generator (`outer_generator` below) has information about where the
// bound was introduced. At least one generator should be present for this diagnostic to be
// modified.
- let (mut trait_ref, mut target_ty) = match obligation.predicate.skip_binders() {
- ty::PredicateAtom::Trait(p, _) => (Some(p.trait_ref), Some(p.self_ty())),
+ let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(p, _) => (Some(p.trait_ref), Some(p.self_ty())),
_ => (None, None),
};
let mut generator = None;
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index a04f816..d4ced20 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -345,12 +345,13 @@
let infcx = self.selcx.infcx();
- match *obligation.predicate.kind() {
- ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
+ let binder = obligation.predicate.kind();
+ match binder.no_bound_vars() {
+ None => match binder.skip_binder() {
// Evaluation will discard candidates using the leak check.
// This means we need to pass it the bound version of our
// predicate.
- ty::PredicateAtom::Trait(trait_ref, _constness) => {
+ ty::PredicateKind::Trait(trait_ref, _constness) => {
let trait_obligation = obligation.with(binder.rebind(trait_ref));
self.process_trait_obligation(
@@ -359,7 +360,7 @@
&mut pending_obligation.stalled_on,
)
}
- ty::PredicateAtom::Projection(data) => {
+ ty::PredicateKind::Projection(data) => {
let project_obligation = obligation.with(binder.rebind(data));
self.process_projection_obligation(
@@ -367,25 +368,25 @@
&mut pending_obligation.stalled_on,
)
}
- ty::PredicateAtom::RegionOutlives(_)
- | ty::PredicateAtom::TypeOutlives(_)
- | ty::PredicateAtom::WellFormed(_)
- | ty::PredicateAtom::ObjectSafe(_)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(_)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..) => {
+ ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(_)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => {
let pred = infcx.replace_bound_vars_with_placeholders(binder);
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
]))
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
},
- ty::PredicateKind::Atom(atom) => match atom {
- ty::PredicateAtom::Trait(data, _) => {
+ Some(pred) => match pred {
+ ty::PredicateKind::Trait(data, _) => {
let trait_obligation = obligation.with(Binder::dummy(data));
self.process_trait_obligation(
@@ -395,14 +396,14 @@
)
}
- ty::PredicateAtom::RegionOutlives(data) => {
+ ty::PredicateKind::RegionOutlives(data) => {
match infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
}
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => {
if self.register_region_obligations {
self.selcx.infcx().register_region_obligation_with_cause(
t_a,
@@ -413,7 +414,7 @@
ProcessResult::Changed(vec![])
}
- ty::PredicateAtom::Projection(ref data) => {
+ ty::PredicateKind::Projection(ref data) => {
let project_obligation = obligation.with(Binder::dummy(*data));
self.process_projection_obligation(
@@ -422,7 +423,7 @@
)
}
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
if !self.selcx.tcx().is_object_safe(trait_def_id) {
ProcessResult::Error(CodeSelectionError(Unimplemented))
} else {
@@ -430,7 +431,7 @@
}
}
- ty::PredicateAtom::ClosureKind(_, closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
match self.selcx.infcx().closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
@@ -443,7 +444,7 @@
}
}
- ty::PredicateAtom::WellFormed(arg) => {
+ ty::PredicateKind::WellFormed(arg) => {
match wf::obligations(
self.selcx.infcx(),
obligation.param_env,
@@ -461,7 +462,7 @@
}
}
- ty::PredicateAtom::Subtype(subtype) => {
+ ty::PredicateKind::Subtype(subtype) => {
match self.selcx.infcx().subtype_predicate(
&obligation.cause,
obligation.param_env,
@@ -487,7 +488,7 @@
}
}
- ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
match const_evaluatable::is_const_evaluatable(
self.selcx.infcx(),
def_id,
@@ -507,7 +508,7 @@
}
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
debug!(?c1, ?c2, "equating consts");
if self.selcx.tcx().features().const_evaluatable_checked {
// FIXME: we probably should only try to unify abstract constants
@@ -593,7 +594,7 @@
}
}
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
},
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 9c894e9..dbc40a2 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -324,7 +324,7 @@
// TypeOutlives predicates - these are normally used by regionck.
let outlives_predicates: Vec<_> = predicates
.drain_filter(|predicate| {
- matches!(predicate.skip_binders(), ty::PredicateAtom::TypeOutlives(..))
+ matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
})
.collect();
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 8b6e30f..a972361 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -273,12 +273,12 @@
) -> Option<Span> {
let self_ty = tcx.types.self_param;
let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(ref data, _) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(ref data, _) => {
// In the case of a trait predicate, we can skip the "self" type.
if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
}
- ty::PredicateAtom::Projection(ref data) => {
+ ty::PredicateKind::Projection(ref data) => {
// And similarly for projections. This should be redundant with
// the previous check because any projection should have a
// matching `Trait` predicate with the same inputs, but we do
@@ -300,15 +300,15 @@
None
}
}
- ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
@@ -328,20 +328,20 @@
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| {
- match obligation.predicate.skip_binders() {
- ty::PredicateAtom::Trait(ref trait_pred, _) => {
+ match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(ref trait_pred, _) => {
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
}
- ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => false,
+ ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}
})
}
@@ -843,7 +843,7 @@
}
fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- if let ty::PredicateAtom::ConstEvaluatable(def, substs) = pred.skip_binders() {
+ if let ty::PredicateKind::ConstEvaluatable(def, substs) = pred.kind().skip_binder() {
// FIXME(const_evaluatable_checked): We should probably deduplicate the logic for
// `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
// take a `ty::Const` instead.
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index fa05264..75ff931 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -625,7 +625,7 @@
.obligations
.iter()
.filter(|obligation| {
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
// We found a `T: Foo<X = U>` predicate, let's check
// if `U` references any unresolved type
@@ -636,7 +636,7 @@
// indirect obligations (e.g., we project to `?0`,
// but we have `T: Foo<X = ?1>` and `?1: Bar<X =
// ?0>`).
- ty::PredicateAtom::Projection(data) => {
+ ty::PredicateKind::Projection(data) => {
infcx.unresolved_type_vars(&bound_predicate.rebind(data.ty)).is_some()
}
@@ -917,8 +917,8 @@
let infcx = selcx.infcx();
for predicate in env_predicates {
debug!(?predicate);
- let bound_predicate = predicate.bound_atom();
- if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() {
+ let bound_predicate = predicate.kind();
+ if let ty::PredicateKind::Projection(data) = predicate.kind().skip_binder() {
let data = bound_predicate.rebind(data);
let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 93ddcb6..de538c6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -15,7 +15,7 @@
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
// such cases.
- if let ty::PredicateAtom::Trait(trait_ref, _) = key.value.predicate.skip_binders() {
+ if let ty::PredicateKind::Trait(trait_ref, _) = key.value.predicate.kind().skip_binder() {
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized_def_id {
if trait_ref.self_ty().is_trivially_sized(tcx) {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 030c291..3015188 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -432,7 +432,7 @@
.predicates
.into_iter()
{
- if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() {
+ if let ty::PredicateKind::Trait(..) = super_trait.kind().skip_binder() {
let normalized_super_trait = normalize_with_depth_to(
self,
obligation.param_env,
@@ -641,7 +641,7 @@
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
- ty::PredicateAtom::ClosureKind(closure_def_id, substs, kind)
+ ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)
.to_predicate(self.tcx()),
));
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8ca540f..614a551 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -454,16 +454,16 @@
}
let result = ensure_sufficient_stack(|| {
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(t, _) => {
+ ty::PredicateKind::Trait(t, _) => {
let t = bound_predicate.rebind(t);
debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(t);
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
}
- ty::PredicateAtom::Subtype(p) => {
+ ty::PredicateKind::Subtype(p) => {
let p = bound_predicate.rebind(p);
// Does this code ever run?
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
@@ -479,7 +479,7 @@
}
}
- ty::PredicateAtom::WellFormed(arg) => match wf::obligations(
+ ty::PredicateKind::WellFormed(arg) => match wf::obligations(
self.infcx,
obligation.param_env,
obligation.cause.body_id,
@@ -494,12 +494,12 @@
None => Ok(EvaluatedToAmbig),
},
- ty::PredicateAtom::TypeOutlives(..) | ty::PredicateAtom::RegionOutlives(..) => {
+ ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
// We do not consider region relationships when evaluating trait matches.
Ok(EvaluatedToOkModuloRegions)
}
- ty::PredicateAtom::ObjectSafe(trait_def_id) => {
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
if self.tcx().is_object_safe(trait_def_id) {
Ok(EvaluatedToOk)
} else {
@@ -507,7 +507,7 @@
}
}
- ty::PredicateAtom::Projection(data) => {
+ ty::PredicateKind::Projection(data) => {
let data = bound_predicate.rebind(data);
let project_obligation = obligation.with(data);
match project::poly_project_and_unify_type(self, &project_obligation) {
@@ -528,7 +528,7 @@
}
}
- ty::PredicateAtom::ClosureKind(_, closure_substs, kind) => {
+ ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
match self.infcx.closure_kind(closure_substs) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
@@ -541,7 +541,7 @@
}
}
- ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
match const_evaluatable::is_const_evaluatable(
self.infcx,
def_id,
@@ -555,7 +555,7 @@
}
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
let evaluate = |c: &'tcx ty::Const<'tcx>| {
@@ -598,7 +598,7 @@
}
}
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
}
@@ -845,8 +845,8 @@
}
fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
- let result = match predicate.skip_binders() {
- ty::PredicateAtom::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
+ let result = match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
_ => false,
};
debug!(?predicate, ?result, "coinductive_predicate");
@@ -1174,8 +1174,8 @@
.iter()
.enumerate()
.filter_map(|(idx, bound)| {
- let bound_predicate = bound.bound_atom();
- if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+ let bound_predicate = bound.kind();
+ if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
let bound = bound_predicate.rebind(pred.trait_ref);
if self.infcx.probe(|_| {
match self.match_normalize_trait_ref(
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index ef87071..e6ef9b1 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -106,28 +106,28 @@
};
// It's ok to skip the binder here because wf code is prepared for it
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(t, _) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(t, _) => {
wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
}
- ty::PredicateAtom::RegionOutlives(..) => {}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+ ty::PredicateKind::RegionOutlives(..) => {}
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
wf.compute(ty.into());
}
- ty::PredicateAtom::Projection(t) => {
+ ty::PredicateKind::Projection(t) => {
wf.compute_projection(t.projection_ty);
wf.compute(t.ty.into());
}
- ty::PredicateAtom::WellFormed(arg) => {
+ ty::PredicateKind::WellFormed(arg) => {
wf.compute(arg);
}
- ty::PredicateAtom::ObjectSafe(_) => {}
- ty::PredicateAtom::ClosureKind(..) => {}
- ty::PredicateAtom::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
+ ty::PredicateKind::ObjectSafe(_) => {}
+ ty::PredicateKind::ClosureKind(..) => {}
+ ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
wf.compute(a.into());
wf.compute(b.into());
}
- ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+ ty::PredicateKind::ConstEvaluatable(def, substs) => {
let obligations = wf.nominal_obligations(def.did, substs);
wf.out.extend(obligations);
@@ -135,11 +135,11 @@
wf.compute(arg);
}
}
- ty::PredicateAtom::ConstEquate(c1, c2) => {
+ ty::PredicateKind::ConstEquate(c1, c2) => {
wf.compute(c1.into());
wf.compute(c2.into());
}
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
}
@@ -209,8 +209,8 @@
};
// It is fine to skip the binder as we don't care about regions here.
- match pred.skip_binders() {
- ty::PredicateAtom::Projection(proj) => {
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::Projection(proj) => {
// The obligation comes not from the current `impl` nor the `trait` being implemented,
// but rather from a "second order" obligation, where an associated type has a
// projection coming from another associated type. See
@@ -225,7 +225,7 @@
}
}
}
- ty::PredicateAtom::Trait(pred, _) => {
+ ty::PredicateKind::Trait(pred, _) => {
// An associated item obligation born out of the `trait` failed to be met. An example
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
@@ -343,7 +343,7 @@
new_cause,
depth,
param_env,
- ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+ ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
)
}),
);
@@ -393,7 +393,7 @@
cause.clone(),
depth,
param_env,
- ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+ ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
)
}),
);
@@ -436,7 +436,7 @@
let obligations = self.nominal_obligations(def.did, substs);
self.out.extend(obligations);
- let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
+ let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(
@@ -460,7 +460,7 @@
cause,
self.recursion_depth,
self.param_env,
- ty::PredicateAtom::WellFormed(resolved_constant.into())
+ ty::PredicateKind::WellFormed(resolved_constant.into())
.to_predicate(self.tcx()),
));
}
@@ -547,7 +547,7 @@
cause,
depth,
param_env,
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(rty, r))
.to_predicate(self.tcx()),
));
}
@@ -637,7 +637,7 @@
cause.clone(),
depth,
param_env,
- ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
+ ty::PredicateKind::ObjectSafe(did).to_predicate(tcx),
)
}));
}
@@ -664,7 +664,7 @@
cause,
self.recursion_depth,
param_env,
- ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
+ ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
));
} else {
// Yes, resolved, proceed with the result.
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 8aa68e5..48d4705 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -81,39 +81,36 @@
interner: &RustInterner<'tcx>,
) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
let clauses = self.environment.into_iter().map(|predicate| {
- let (predicate, binders, _named_regions) = collect_bound_vars(
- interner,
- interner.tcx,
- predicate.bound_atom_with_opt_escaping(interner.tcx),
- );
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, predicate.kind());
let consequence = match predicate {
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
}
- ty::PredicateAtom::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
+ ty::PredicateKind::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
),
- ty::PredicateAtom::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+ ty::PredicateKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
a: predicate.0.lower_into(interner),
b: predicate.1.lower_into(interner),
}),
),
- ty::PredicateAtom::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+ ty::PredicateKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: predicate.0.lower_into(interner),
lifetime: predicate.1.lower_into(interner),
}),
),
- ty::PredicateAtom::Projection(predicate) => chalk_ir::DomainGoal::Holds(
+ ty::PredicateKind::Projection(predicate) => chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
),
- ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
+ ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
};
let value = chalk_ir::ProgramClauseImplication {
consequence,
@@ -136,19 +133,16 @@
impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predicate<'tcx> {
fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData<RustInterner<'tcx>> {
- let (predicate, binders, _named_regions) = collect_bound_vars(
- interner,
- interner.tcx,
- self.bound_atom_with_opt_escaping(interner.tcx),
- );
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, self.kind());
let value = match predicate {
- ty::PredicateAtom::Trait(predicate, _) => {
+ ty::PredicateKind::Trait(predicate, _) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)),
))
}
- ty::PredicateAtom::RegionOutlives(predicate) => {
+ ty::PredicateKind::RegionOutlives(predicate) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
a: predicate.0.lower_into(interner),
@@ -156,7 +150,7 @@
}),
))
}
- ty::PredicateAtom::TypeOutlives(predicate) => {
+ ty::PredicateKind::TypeOutlives(predicate) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: predicate.0.lower_into(interner),
@@ -164,12 +158,12 @@
}),
))
}
- ty::PredicateAtom::Projection(predicate) => {
+ ty::PredicateKind::Projection(predicate) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
))
}
- ty::PredicateAtom::WellFormed(arg) => match arg.unpack() {
+ ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
GenericArgKind::Type(ty) => match ty.kind() {
// FIXME(chalk): In Chalk, a placeholder is WellFormed if it
// `FromEnv`. However, when we "lower" Params, we don't update
@@ -189,7 +183,7 @@
GenericArgKind::Lifetime(lt) => bug!("unexpect well formed predicate: {:?}", lt),
},
- ty::PredicateAtom::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal(
+ ty::PredicateKind::ObjectSafe(t) => chalk_ir::GoalData::DomainGoal(
chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(t)),
),
@@ -197,13 +191,13 @@
//
// We can defer this, but ultimately we'll want to express
// some of these in terms of chalk operations.
- ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..) => {
+ ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..) => {
chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
}
- ty::PredicateAtom::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
+ ty::PredicateKind::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))),
),
};
@@ -573,38 +567,35 @@
self,
interner: &RustInterner<'tcx>,
) -> Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
- let (predicate, binders, _named_regions) = collect_bound_vars(
- interner,
- interner.tcx,
- self.bound_atom_with_opt_escaping(interner.tcx),
- );
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, self.kind());
let value = match predicate {
- ty::PredicateAtom::Trait(predicate, _) => {
+ ty::PredicateKind::Trait(predicate, _) => {
Some(chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)))
}
- ty::PredicateAtom::RegionOutlives(predicate) => {
+ ty::PredicateKind::RegionOutlives(predicate) => {
Some(chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
a: predicate.0.lower_into(interner),
b: predicate.1.lower_into(interner),
}))
}
- ty::PredicateAtom::TypeOutlives(predicate) => {
+ ty::PredicateKind::TypeOutlives(predicate) => {
Some(chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: predicate.0.lower_into(interner),
lifetime: predicate.1.lower_into(interner),
}))
}
- ty::PredicateAtom::Projection(predicate) => {
+ ty::PredicateKind::Projection(predicate) => {
Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
}
- ty::PredicateAtom::WellFormed(_ty) => None,
+ ty::PredicateKind::WellFormed(_ty) => None,
- ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("unexpected predicate {}", &self)
}
};
@@ -707,32 +698,29 @@
self,
interner: &RustInterner<'tcx>,
) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
- let (predicate, binders, _named_regions) = collect_bound_vars(
- interner,
- interner.tcx,
- self.bound_atom_with_opt_escaping(interner.tcx),
- );
+ let (predicate, binders, _named_regions) =
+ collect_bound_vars(interner, interner.tcx, self.kind());
match predicate {
- ty::PredicateAtom::Trait(predicate, _) => Some(chalk_ir::Binders::new(
+ ty::PredicateKind::Trait(predicate, _) => Some(chalk_ir::Binders::new(
binders,
chalk_solve::rust_ir::InlineBound::TraitBound(
predicate.trait_ref.lower_into(interner),
),
)),
- ty::PredicateAtom::Projection(predicate) => Some(chalk_ir::Binders::new(
+ ty::PredicateKind::Projection(predicate) => Some(chalk_ir::Binders::new(
binders,
chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
)),
- ty::PredicateAtom::TypeOutlives(_predicate) => None,
- ty::PredicateAtom::WellFormed(_ty) => None,
+ ty::PredicateKind::TypeOutlives(_predicate) => None,
+ ty::PredicateKind::WellFormed(_ty) => None,
- ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+ ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("unexpected predicate {}", &self)
}
}
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 97017fb..90ba902 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -94,27 +94,27 @@
// region relationships.
implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
assert!(!obligation.has_escaping_bound_vars());
- match obligation.predicate.kind() {
- &ty::PredicateKind::ForAll(..) => vec![],
- &ty::PredicateKind::Atom(atom) => match atom {
- ty::PredicateAtom::Trait(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => vec![],
- ty::PredicateAtom::WellFormed(arg) => {
+ match obligation.predicate.kind().no_bound_vars() {
+ None => vec![],
+ Some(pred) => match pred {
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
+ ty::PredicateKind::WellFormed(arg) => {
wf_args.push(arg);
vec![]
}
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
let ty_a = infcx.resolve_vars_if_possible(ty_a);
let mut components = smallvec![];
tcx.push_outlives_components(ty_a, &mut components);
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 4841e42..1213e55 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -46,16 +46,16 @@
}
fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
- match p.skip_binders() {
- ty::PredicateAtom::RegionOutlives(..) | ty::PredicateAtom::TypeOutlives(..) => false,
- ty::PredicateAtom::Trait(..)
- | ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => true,
+ match p.kind().skip_binder() {
+ ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
}
}
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 0addde5..6304f69 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -140,7 +140,7 @@
self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
self.prove_predicate(
- ty::PredicateAtom::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
+ ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
);
}
@@ -155,7 +155,7 @@
// them? This would only be relevant if some input
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
- self.prove_predicate(ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()));
+ self.prove_predicate(ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()));
Ok(())
}
}
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index b28cc76..bd1d9cc 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -5,7 +5,7 @@
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{
- self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
+ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
};
use rustc_session::CrateDisambiguator;
use rustc_span::symbol::Symbol;
@@ -378,8 +378,8 @@
let input_clauses = inputs.into_iter().filter_map(|arg| {
match arg.unpack() {
GenericArgKind::Type(ty) => {
- let binder = Binder::dummy(PredicateAtom::TypeWellFormedFromEnv(ty));
- Some(tcx.mk_predicate(PredicateKind::ForAll(binder)))
+ let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty));
+ Some(tcx.mk_predicate(binder))
}
// FIXME(eddyb) no WF conditions from lifetimes?
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 9a2f69d..059f9b4 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1177,9 +1177,9 @@
obligation.predicate
);
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(pred, _) => {
+ ty::PredicateKind::Trait(pred, _) => {
let pred = bound_predicate.rebind(pred);
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
@@ -1188,7 +1188,7 @@
.map(|item| item.def_id),
);
}
- ty::PredicateAtom::Projection(pred) => {
+ ty::PredicateKind::Projection(pred) => {
let pred = bound_predicate.rebind(pred);
// A `Self` within the original bound will be substituted with a
// `trait_object_dummy_self`, so check for that.
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 322ec96..30e0e3e 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -544,9 +544,9 @@
self.infcx.instantiate_opaque_types(id, self.body_id, self.param_env, ty, span);
let mut suggest_box = !impl_trait_ret_ty.obligations.is_empty();
for o in impl_trait_ret_ty.obligations {
- match o.predicate.skip_binders_unchecked() {
- ty::PredicateAtom::Trait(t, constness) => {
- let pred = ty::PredicateAtom::Trait(
+ match o.predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(t, constness) => {
+ let pred = ty::PredicateKind::Trait(
ty::TraitPredicate {
trait_ref: ty::TraitRef {
def_id: t.def_id(),
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 7470c1a..f34aaec 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -192,9 +192,9 @@
obligation.predicate
);
- let bound_predicate = obligation.predicate.bound_atom();
- if let ty::PredicateAtom::Projection(proj_predicate) =
- obligation.predicate.skip_binders()
+ let bound_predicate = obligation.predicate.kind();
+ if let ty::PredicateKind::Projection(proj_predicate) =
+ obligation.predicate.kind().skip_binder()
{
// Given a Projection predicate, we can potentially infer
// the complete signature.
@@ -622,8 +622,8 @@
// where R is the return type we are expecting. This type `T`
// will be our output.
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
- let bound_predicate = obligation.predicate.bound_atom();
- if let ty::PredicateAtom::Projection(proj_predicate) = bound_predicate.skip_binder() {
+ let bound_predicate = obligation.predicate.kind();
+ if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
self.deduce_future_output_from_projection(
obligation.cause.span,
bound_predicate.rebind(proj_predicate),
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 0d21c56..34ad8ec 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -583,9 +583,9 @@
while !queue.is_empty() {
let obligation = queue.remove(0);
debug!("coerce_unsized resolve step: {:?}", obligation);
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
let trait_pred = match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(trait_pred, _)
+ ty::PredicateKind::Trait(trait_pred, _)
if traits.contains(&trait_pred.def_id()) =>
{
if unsize_did == trait_pred.def_id() {
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 0036edd..d37d6bc 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -365,12 +365,10 @@
let item_kind = assoc_item_kind_str(impl_m);
let def_span = tcx.sess.source_map().guess_head_span(span);
let span = tcx.hir().get_generics(impl_m.def_id).map_or(def_span, |g| g.span);
- let generics_span = if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) {
+ let generics_span = tcx.hir().span_if_local(trait_m.def_id).map(|sp| {
let def_sp = tcx.sess.source_map().guess_head_span(sp);
- Some(tcx.hir().get_generics(trait_m.def_id).map_or(def_sp, |g| g.span))
- } else {
- None
- };
+ tcx.hir().get_generics(trait_m.def_id).map_or(def_sp, |g| g.span)
+ });
tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
span,
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs
index be19919..4c3c4fd 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_typeck/src/check/dropck.rs
@@ -226,13 +226,13 @@
// could be extended easily also to the other `Predicate`.
let predicate_matches_closure = |p: Predicate<'tcx>| {
let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
- let predicate = predicate.bound_atom();
- let p = p.bound_atom();
+ let predicate = predicate.kind();
+ let p = p.kind();
match (predicate.skip_binder(), p.skip_binder()) {
- (ty::PredicateAtom::Trait(a, _), ty::PredicateAtom::Trait(b, _)) => {
+ (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
}
- (ty::PredicateAtom::Projection(a), ty::PredicateAtom::Projection(b)) => {
+ (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
}
_ => predicate == p,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 47799c9..5a372c0 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -542,7 +542,7 @@
self.register_predicate(traits::Obligation::new(
cause,
self.param_env,
- ty::PredicateAtom::WellFormed(arg).to_predicate(self.tcx),
+ ty::PredicateKind::WellFormed(arg).to_predicate(self.tcx),
));
}
@@ -764,21 +764,21 @@
.pending_obligations()
.into_iter()
.filter_map(move |obligation| {
- let bound_predicate = obligation.predicate.bound_atom();
+ let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Projection(data) => {
+ ty::PredicateKind::Projection(data) => {
Some((bound_predicate.rebind(data).to_poly_trait_ref(self.tcx), obligation))
}
- ty::PredicateAtom::Trait(data, _) => {
+ ty::PredicateKind::Trait(data, _) => {
Some((bound_predicate.rebind(data).to_poly_trait_ref(), obligation))
}
- ty::PredicateAtom::Subtype(..) => None,
- ty::PredicateAtom::RegionOutlives(..) => None,
- ty::PredicateAtom::TypeOutlives(..) => None,
- ty::PredicateAtom::WellFormed(..) => None,
- ty::PredicateAtom::ObjectSafe(..) => None,
- ty::PredicateAtom::ConstEvaluatable(..) => None,
- ty::PredicateAtom::ConstEquate(..) => None,
+ ty::PredicateKind::Subtype(..) => None,
+ ty::PredicateKind::RegionOutlives(..) => None,
+ ty::PredicateKind::TypeOutlives(..) => None,
+ ty::PredicateKind::WellFormed(..) => None,
+ ty::PredicateKind::ObjectSafe(..) => None,
+ ty::PredicateKind::ConstEvaluatable(..) => None,
+ ty::PredicateKind::ConstEquate(..) => None,
// N.B., this predicate is created by breaking down a
// `ClosureType: FnFoo()` predicate, where
// `ClosureType` represents some `Closure`. It can't
@@ -787,8 +787,8 @@
// this closure yet; this is exactly why the other
// code is looking for a self type of a unresolved
// inference variable.
- ty::PredicateAtom::ClosureKind(..) => None,
- ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::ClosureKind(..) => None,
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
})
.filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 6177e39..6df9e3a 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -923,8 +923,8 @@
continue;
}
- if let ty::PredicateAtom::Trait(predicate, _) =
- error.obligation.predicate.skip_binders()
+ if let ty::PredicateKind::Trait(predicate, _) =
+ error.obligation.predicate.kind().skip_binder()
{
// Collect the argument position for all arguments that could have caused this
// `FulfillmentError`.
@@ -974,8 +974,8 @@
if let hir::ExprKind::Path(qpath) = &path.kind {
if let hir::QPath::Resolved(_, path) = &qpath {
for error in errors {
- if let ty::PredicateAtom::Trait(predicate, _) =
- error.obligation.predicate.skip_binders()
+ if let ty::PredicateKind::Trait(predicate, _) =
+ error.obligation.predicate.kind().skip_binder()
{
// If any of the type arguments in this path segment caused the
// `FullfillmentError`, point at its span (#61860).
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
index f635e0b..6d09043 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
@@ -194,8 +194,8 @@
parent: None,
predicates: tcx.arena.alloc_from_iter(
self.param_env.caller_bounds().iter().filter_map(|predicate| {
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(data, _) if data.self_ty().is_param(index) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(data, _) if data.self_ty().is_param(index) => {
// HACK(eddyb) should get the original `Span`.
let span = tcx.def_span(def_id);
Some((predicate, span))
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index e4e6cf7..e99db7a 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -157,7 +157,6 @@
}
sym::forget => (1, vec![param(0)], tcx.mk_unit()),
sym::transmute => (2, vec![param(0)], param(1)),
- sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::prefetch_read_data
| sym::prefetch_write_data
| sym::prefetch_read_instruction
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index e604419..af91514 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -478,8 +478,8 @@
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
// We don't care about regions here.
- .filter_map(|obligation| match obligation.predicate.skip_binders() {
- ty::PredicateAtom::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
+ .filter_map(|obligation| match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
let span = predicates
.predicates
.iter()
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index 8e13b37..4434323 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -399,7 +399,7 @@
obligations.push(traits::Obligation::new(
cause,
self.param_env,
- ty::PredicateAtom::WellFormed(method_ty.into()).to_predicate(tcx),
+ ty::PredicateKind::WellFormed(method_ty.into()).to_predicate(tcx),
));
let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig };
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index d4631c4..be80b63 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -795,9 +795,9 @@
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
- let bound_predicate = predicate.bound_atom();
+ let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(trait_predicate, _) => {
+ ty::PredicateKind::Trait(trait_predicate, _) => {
match *trait_predicate.trait_ref.self_ty().kind() {
ty::Param(p) if p == param_ty => {
Some(bound_predicate.rebind(trait_predicate.trait_ref))
@@ -805,16 +805,16 @@
_ => None,
}
}
- ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::RegionOutlives(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::TypeOutlives(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::RegionOutlives(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::TypeOutlives(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
});
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index e6bfa5e..c553fda 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -582,8 +582,8 @@
let mut collect_type_param_suggestions =
|self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
// We don't care about regions here, so it's fine to skip the binder here.
- if let (ty::Param(_), ty::PredicateAtom::Trait(p, _)) =
- (self_ty.kind(), parent_pred.skip_binders())
+ if let (ty::Param(_), ty::PredicateKind::Trait(p, _)) =
+ (self_ty.kind(), parent_pred.kind().skip_binder())
{
if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
let node = def.did.as_local().map(|def_id| {
@@ -637,9 +637,9 @@
}
};
let mut format_pred = |pred: ty::Predicate<'tcx>| {
- let bound_predicate = pred.bound_atom();
+ let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Projection(pred) => {
+ ty::PredicateKind::Projection(pred) => {
let pred = bound_predicate.rebind(pred);
// `<Foo as Iterator>::Item = String`.
let trait_ref =
@@ -658,7 +658,7 @@
bound_span_label(trait_ref.self_ty(), &obligation, &quiet);
Some((obligation, trait_ref.self_ty()))
}
- ty::PredicateAtom::Trait(poly_trait_ref, _) => {
+ ty::PredicateKind::Trait(poly_trait_ref, _) => {
let p = poly_trait_ref.trait_ref;
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
@@ -992,11 +992,11 @@
// implementing a trait would be legal but is rejected
// here).
unsatisfied_predicates.iter().all(|(p, _)| {
- match p.skip_binders() {
+ match p.kind().skip_binder() {
// Hide traits if they are present in predicates as they can be fixed without
// having to implement them.
- ty::PredicateAtom::Trait(t, _) => t.def_id() == info.def_id,
- ty::PredicateAtom::Projection(p) => {
+ ty::PredicateKind::Trait(t, _) => t.def_id() == info.def_id,
+ ty::PredicateKind::Projection(p) => {
p.projection_ty.item_def_id == info.def_id
}
_ => false,
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 8177b36..52276ed 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -864,9 +864,9 @@
let mut projections = vec![];
for (predicate, _) in predicates.predicates {
debug!("predicate {:?}", predicate);
- let bound_predicate = predicate.bound_atom();
+ let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(trait_predicate, _) => {
+ ty::PredicateKind::Trait(trait_predicate, _) => {
let entry = types.entry(trait_predicate.self_ty()).or_default();
let def_id = trait_predicate.def_id();
if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -875,7 +875,7 @@
entry.push(trait_predicate.def_id());
}
}
- ty::PredicateAtom::Projection(projection_pred) => {
+ ty::PredicateKind::Projection(projection_pred) => {
projections.push(bound_predicate.rebind(projection_pred));
}
_ => {}
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index e8cbefd..feda35d 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -176,7 +176,17 @@
self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
// If we have an origin, store it.
- if let Some(origin) = delegate.current_origin {
+ if let Some(origin) = delegate.current_origin.clone() {
+ let origin = if self.tcx.features().capture_disjoint_fields {
+ origin
+ } else {
+ // FIXME(project-rfc-2229#26): Once rust-lang#80092 is merged, we should restrict the
+ // precision of origin as well. Otherwise, this will cause issues when project-rfc-2229#26
+ // is fixed as we might see Index projections in the origin, which we can't print because
+ // we don't store enough information.
+ (origin.0, Place { projections: vec![], ..origin.1 })
+ };
+
self.typeck_results
.borrow_mut()
.closure_kind_origins_mut()
@@ -563,7 +573,7 @@
// If we modified `current_closure_kind`, this field contains a `Some()` with the
// variable access that caused us to do so.
- current_origin: Option<(Span, Symbol)>,
+ current_origin: Option<(Span, Place<'tcx>)>,
/// For each Place that is captured by the closure, we track the minimal kind of
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
@@ -628,7 +638,7 @@
upvar_id.closure_expr_id,
ty::ClosureKind::FnOnce,
usage_span,
- var_name(tcx, upvar_id.var_path.hir_id),
+ place_with_id.place.clone(),
);
let capture_info = ty::CaptureInfo {
@@ -720,7 +730,7 @@
upvar_id.closure_expr_id,
ty::ClosureKind::FnMut,
tcx.hir().span(diag_expr_id),
- var_name(tcx, upvar_id.var_path.hir_id),
+ place_with_id.place.clone(),
);
}
}
@@ -765,11 +775,11 @@
closure_id: LocalDefId,
new_kind: ty::ClosureKind,
upvar_span: Span,
- var_name: Symbol,
+ place: Place<'tcx>,
) {
debug!(
- "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
- closure_id, new_kind, upvar_span, var_name
+ "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
+ closure_id, new_kind, upvar_span, place
);
// Is this the closure whose kind is currently being inferred?
@@ -797,7 +807,7 @@
| (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
// new kind is stronger than the old kind
self.current_closure_kind = new_kind;
- self.current_origin = Some((upvar_span, var_name));
+ self.current_origin = Some((upvar_span, place));
}
}
}
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 2c720ce..c90db47 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -532,7 +532,7 @@
fcx.register_predicate(traits::Obligation::new(
cause,
fcx.param_env,
- ty::PredicateAtom::ConstEvaluatable(
+ ty::PredicateKind::ConstEvaluatable(
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
discr_substs,
)
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 7c9cfe6..6edce62 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -384,9 +384,11 @@
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
let common_hir_owner = fcx_typeck_results.hir_owner;
- for (&id, &origin) in fcx_typeck_results.closure_kind_origins().iter() {
- let hir_id = hir::HirId { owner: common_hir_owner, local_id: id };
- self.typeck_results.closure_kind_origins_mut().insert(hir_id, origin);
+ for (id, origin) in fcx_typeck_results.closure_kind_origins().iter() {
+ let hir_id = hir::HirId { owner: common_hir_owner, local_id: *id };
+ let place_span = origin.0;
+ let place = self.resolve(origin.1.clone(), &place_span);
+ self.typeck_results.closure_kind_origins_mut().insert(hir_id, (place_span, place));
}
}
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index a667732..d589989 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -562,8 +562,8 @@
let extra_predicates = extend.into_iter().chain(
icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
.into_iter()
- .filter(|(predicate, _)| match predicate.skip_binders() {
- ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
+ .filter(|(predicate, _)| match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
_ => false,
}),
);
@@ -1027,7 +1027,7 @@
// which will, in turn, reach indirect supertraits.
for &(pred, span) in superbounds {
debug!("superbound: {:?}", pred);
- if let ty::PredicateAtom::Trait(bound, _) = pred.skip_binders() {
+ if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
tcx.at(span).super_predicates_of(bound.def_id());
}
}
@@ -1946,13 +1946,10 @@
} else {
let span = bound_pred.bounded_ty.span;
let re_root_empty = tcx.lifetimes.re_root_empty;
- let predicate = ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
+ let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives(
ty::OutlivesPredicate(ty, re_root_empty),
));
- predicates.insert((
- predicate.potentially_quantified(tcx, ty::PredicateKind::ForAll),
- span,
- ));
+ predicates.insert((predicate.to_predicate(tcx), span));
}
}
@@ -1993,10 +1990,10 @@
hir::GenericBound::Outlives(lifetime) => {
let region = AstConv::ast_region_to_region(&icx, lifetime, None);
predicates.insert((
- ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
+ ty::Binder::bind(ty::PredicateKind::TypeOutlives(
ty::OutlivesPredicate(ty, region),
))
- .potentially_quantified(tcx, ty::PredicateKind::ForAll),
+ .to_predicate(tcx),
lifetime.span,
));
}
@@ -2013,7 +2010,7 @@
}
_ => bug!(),
};
- let pred = ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+ let pred = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
.to_predicate(icx.tcx);
(pred, span)
@@ -2078,7 +2075,7 @@
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
let span = self.tcx.hir().span(c.hir_id);
self.preds.insert((
- ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+ ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx),
span,
));
}
@@ -2097,7 +2094,7 @@
fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
self.preds.insert((
- ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+ ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx),
self.span,
));
}
@@ -2183,12 +2180,12 @@
.predicates
.iter()
.copied()
- .filter(|(pred, _)| match pred.skip_binders() {
- ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
- ty::PredicateAtom::Projection(proj) => {
+ .filter(|(pred, _)| match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
+ ty::PredicateKind::Projection(proj) => {
!is_assoc_item_ty(proj.projection_ty.self_ty())
}
- ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
+ ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
_ => true,
})
.collect();
@@ -2217,7 +2214,8 @@
let (ty_def_id, item_def_id) = key;
let mut projection_ty = None;
for (predicate, _) in tcx.predicates_of(ty_def_id).predicates {
- if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+ if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder()
+ {
if item_def_id == projection_predicate.projection_ty.item_def_id {
projection_ty = Some(projection_predicate.projection_ty);
break;
@@ -2264,7 +2262,7 @@
}
hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None);
- let pred = ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
+ let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
.to_predicate(astconv.tcx());
vec![(pred, lifetime.span)]
}
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
index e596dd1..537a583 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -36,13 +36,14 @@
let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
- let bounds_from_parent =
- trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() {
- ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty,
- ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
- ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty,
+ let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(tr, _) => tr.self_ty() == item_ty,
+ ty::PredicateKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+ ty::PredicateKind::TypeOutlives(outlives) => outlives.0 == item_ty,
_ => false,
- });
+ }
+ });
let all_bounds = tcx
.arena
diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs
index e389fd4..95670b9 100644
--- a/compiler/rustc_typeck/src/constrained_generic_params.rs
+++ b/compiler/rustc_typeck/src/constrained_generic_params.rs
@@ -183,7 +183,8 @@
for j in i..predicates.len() {
// Note that we don't have to care about binders here,
// as the impl trait ref never contains any late-bound regions.
- if let ty::PredicateAtom::Projection(projection) = predicates[j].0.skip_binders() {
+ if let ty::PredicateKind::Projection(projection) = predicates[j].0.kind().skip_binder()
+ {
// Special case: watch out for some kind of sneaky attempt
// to project out an associated type defined by this very
// trait.
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index 5db9ff9..505d9a5 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -198,7 +198,7 @@
// the functions in `cgp` add the constrained parameters to a list of
// unconstrained parameters.
for (predicate, _) in impl_generic_predicates.predicates.iter() {
- if let ty::PredicateAtom::Projection(proj) = predicate.skip_binders() {
+ if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() {
let projection_ty = proj.projection_ty;
let projected_ty = proj.ty;
@@ -360,13 +360,13 @@
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
debug!("can_specialize_on(predicate = {:?})", predicate);
- match predicate.skip_binders() {
+ match predicate.kind().skip_binder() {
// Global predicates are either always true or always false, so we
// are fine to specialize on.
_ if predicate.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
- ty::PredicateAtom::Trait(pred, hir::Constness::NotConst) => {
+ ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
if !matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::Marker)
@@ -393,20 +393,20 @@
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
) -> Option<TraitSpecializationKind> {
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(pred, hir::Constness::NotConst) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {
Some(tcx.trait_def(pred.def_id()).specialization_kind)
}
- ty::PredicateAtom::Trait(_, hir::Constness::Const)
- | ty::PredicateAtom::RegionOutlives(_)
- | ty::PredicateAtom::TypeOutlives(_)
- | ty::PredicateAtom::Projection(_)
- | ty::PredicateAtom::WellFormed(_)
- | ty::PredicateAtom::Subtype(_)
- | ty::PredicateAtom::ObjectSafe(_)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+ ty::PredicateKind::Trait(_, hir::Constness::Const)
+ | ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::Projection(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Subtype(_)
+ | ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs
index ae336cc..6e5be87 100644
--- a/compiler/rustc_typeck/src/outlives/explicit.rs
+++ b/compiler/rustc_typeck/src/outlives/explicit.rs
@@ -29,8 +29,8 @@
// process predicates and convert to `RequiredPredicates` entry, see below
for &(predicate, span) in predicates.predicates {
- match predicate.skip_binders() {
- ty::PredicateAtom::TypeOutlives(OutlivesPredicate(ref ty, ref reg)) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::TypeOutlives(OutlivesPredicate(ref ty, ref reg)) => {
insert_outlives_predicate(
tcx,
(*ty).into(),
@@ -40,7 +40,7 @@
)
}
- ty::PredicateAtom::RegionOutlives(OutlivesPredicate(ref reg1, ref reg2)) => {
+ ty::PredicateKind::RegionOutlives(OutlivesPredicate(ref reg1, ref reg2)) => {
insert_outlives_predicate(
tcx,
(*reg1).into(),
@@ -50,15 +50,15 @@
)
}
- ty::PredicateAtom::Trait(..)
- | ty::PredicateAtom::Projection(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => (),
+ ty::PredicateKind::Trait(..)
+ | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
}
}
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs
index b1f7933..e94b845 100644
--- a/compiler/rustc_typeck/src/outlives/mod.rs
+++ b/compiler/rustc_typeck/src/outlives/mod.rs
@@ -30,13 +30,9 @@
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec<String> = predicates
.iter()
- .map(|(out_pred, _)| match out_pred.kind() {
- ty::PredicateKind::Atom(ty::PredicateAtom::RegionOutlives(p)) => {
- p.to_string()
- }
- ty::PredicateKind::Atom(ty::PredicateAtom::TypeOutlives(p)) => {
- p.to_string()
- }
+ .map(|(out_pred, _)| match out_pred.kind().skip_binder() {
+ ty::PredicateKind::RegionOutlives(p) => p.to_string(),
+ ty::PredicateKind::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected predicate {:?}", err),
})
.collect();
@@ -89,12 +85,12 @@
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
.to_predicate(tcx),
span,
)),
GenericArgKind::Lifetime(region1) => Some((
- ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
+ ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
region1, region2,
))
.to_predicate(tcx),
diff --git a/config.toml.example b/config.toml.example
index 9e08ce9..55b20ad 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -35,9 +35,11 @@
# Unless you're developing for a target where Rust CI doesn't build a compiler
# toolchain or changing LLVM locally, you probably want to set this to true.
#
-# It's currently false by default due to being newly added; please file bugs if
-# enabling this did not work for you on x86_64-unknown-linux-gnu.
-# Other target triples are currently not supported; see #77084.
+# This is false by default so that distributions don't unexpectedly download
+# LLVM from the internet.
+#
+# All tier 1 targets are currently supported; set this to `"if-supported"` if
+# you are not sure whether you're on a tier 1 target.
#
# We also currently only support this when building LLVM for the build triple.
#
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 76051d9..3c515af 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -161,7 +161,10 @@
/// It is a logic error for an item to be modified in such a way that the
/// item's ordering relative to any other item, as determined by the `Ord`
/// trait, changes while it is in the heap. This is normally only possible
-/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
+/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The
+/// behavior resulting from such a logic error is not specified, but will
+/// not result in undefined behavior. This could include panics, incorrect
+/// results, aborts, memory leaks, and non-termination.
///
/// # Examples
///
@@ -630,10 +633,16 @@
// and about 2 * (len1 + len2) comparisons in the worst case
// while `extend` takes O(len2 * log(len1)) operations
// and about 1 * len2 * log_2(len1) comparisons in the worst case,
- // assuming len1 >= len2.
+ // assuming len1 >= len2. For larger heaps, the crossover point
+ // no longer follows this reasoning and was determined empirically.
#[inline]
fn better_to_rebuild(len1: usize, len2: usize) -> bool {
- 2 * (len1 + len2) < len2 * log2_fast(len1)
+ let tot_len = len1 + len2;
+ if tot_len <= 2048 {
+ 2 * tot_len < len2 * log2_fast(len1)
+ } else {
+ 2 * tot_len < len2 * 11
+ }
}
if better_to_rebuild(self.len(), other.len()) {
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 944e0e6..5e63a30 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -51,6 +51,9 @@
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will not result in
+/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
+/// non-termination.
///
/// [`Cell`]: core::cell::Cell
/// [`RefCell`]: core::cell::RefCell
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index f91db53..097e3e6 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -142,8 +142,17 @@
}
impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
+ fn new_internal(child: Root<K, V>) -> Self {
+ let mut new_node = Box::new(unsafe { InternalNode::new() });
+ new_node.edges[0].write(child.node);
+ NodeRef::from_new_internal(new_node, child.height + 1)
+ }
+
fn from_new_internal(internal: Box<InternalNode<K, V>>, height: usize) -> Self {
- NodeRef { height, node: NonNull::from(Box::leak(internal)).cast(), _marker: PhantomData }
+ let node = NonNull::from(Box::leak(internal)).cast();
+ let mut this = NodeRef { height, node, _marker: PhantomData };
+ this.borrow_mut().correct_all_childrens_parent_links();
+ this
}
}
@@ -167,11 +176,7 @@
/// make that new node the root node, and return it. This increases the height by 1
/// and is the opposite of `pop_internal_level`.
pub fn push_internal_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
- let mut new_node = Box::new(unsafe { InternalNode::new() });
- new_node.edges[0].write(self.node);
- let mut new_root = NodeRef::from_new_internal(new_node, self.height + 1);
- new_root.borrow_mut().first_edge().correct_parent_link();
- *self = new_root.forget_type();
+ super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type());
// `self.borrow_mut()`, except that we just forgot we're internal now:
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
@@ -179,7 +184,7 @@
/// Removes the internal root node, using its first child as the new root node.
/// As it is intended only to be called when the root node has only one child,
- /// no cleanup is done on any of the other children.
+ /// no cleanup is done on any of the keys, values and other children.
/// This decreases the height by 1 and is the opposite of `push_internal_level`.
///
/// Requires exclusive access to the `Root` object but not to the root node;
@@ -220,7 +225,7 @@
/// - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`,
/// but does not have a destructor, and must be cleaned up manually.
/// Since any `NodeRef` allows navigating through the tree, `BorrowType`
-/// effectively applies to the entire tree, not just the node itself.
+/// effectively applies to the entire tree, not just to the node itself.
/// - `K` and `V`: These are the types of keys and values stored in the nodes.
/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
@@ -420,7 +425,7 @@
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
/// Similar to `ascend`, gets a reference to a node's parent node, but also
- /// deallocate the current node in the process. This is unsafe because the
+ /// deallocates the current node in the process. This is unsafe because the
/// current node will still be accessible despite being deallocated.
pub unsafe fn deallocate_and_ascend(
self,
@@ -656,7 +661,10 @@
/// Removes a key-value pair from the end of the node and returns the pair.
/// Also removes the edge that was to the right of that pair and, if the node
/// is internal, returns the orphaned subtree that this edge owned.
- fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
+ ///
+ /// # Safety
+ /// The node must not be empty.
+ unsafe fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
debug_assert!(self.len() > 0);
let idx = self.len() - 1;
@@ -1193,9 +1201,7 @@
);
let height = self.node.height;
- let mut right = NodeRef::from_new_internal(new_node, height);
-
- right.borrow_mut().correct_childrens_parent_links(0..new_len + 1);
+ let right = NodeRef::from_new_internal(new_node, height);
SplitResult { left: self.node, kv, right }
}
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index 7fe8ff7..48ce9f2 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -79,10 +79,8 @@
#[test]
fn test_partial_cmp_eq() {
let mut root1 = NodeRef::new_leaf();
- let mut leaf1 = root1.borrow_mut();
- leaf1.push(1, ());
- let mut root1 = root1.forget_type();
- root1.push_internal_level();
+ root1.borrow_mut().push(1, ());
+ let mut root1 = NodeRef::new_internal(root1.forget_type()).forget_type();
let root2 = Root::new();
root1.reborrow().assert_back_pointers();
root2.reborrow().assert_back_pointers();
diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs
index ed7f95f..efe94ef 100644
--- a/library/alloc/src/collections/btree/search.rs
+++ b/library/alloc/src/collections/btree/search.rs
@@ -12,8 +12,7 @@
/// Looks up a given key in a (sub)tree headed by the given node, recursively.
/// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
-/// returns a `GoDown` with the handle of the possible leaf edge where the key
-/// belongs.
+/// returns a `GoDown` with the handle of the leaf edge where the key belongs.
///
/// The result is meaningful only if the tree is ordered by key, like the tree
/// in a `BTreeMap` is.
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index c72e305..c2a96dd 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -22,6 +22,9 @@
/// It is a logic error for an item to be modified in such a way that the item's ordering relative
/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will not result in
+/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
+/// non-termination.
///
/// [`Ord`]: core::cmp::Ord
/// [`Cell`]: core::cell::Cell
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index cfad111..14a10aa 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -120,6 +120,7 @@
#![feature(receiver_trait)]
#![cfg_attr(bootstrap, feature(min_const_generics))]
#![feature(min_specialization)]
+#![feature(set_ptr_value)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(staged_api)]
@@ -139,6 +140,7 @@
#![feature(type_alias_impl_trait)]
#![feature(associated_type_bounds)]
#![feature(slice_group_by)]
+#![feature(decl_macro)]
// Allow testing this library
#[cfg(test)]
@@ -192,4 +194,11 @@
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
pub mod __export {
pub use core::format_args;
+
+ /// Force AST node to an expression to improve diagnostics in pattern position.
+ #[rustc_macro_transparency = "semitransparent"]
+ #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
+ pub macro force_expr($e:expr) {
+ $e
+ }
}
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index 7d4eff6..3a46763 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -37,16 +37,16 @@
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable(box_syntax)]
+#[allow_internal_unstable(box_syntax, liballoc_internals)]
macro_rules! vec {
() => (
- $crate::vec::Vec::new()
+ $crate::__export::force_expr!($crate::vec::Vec::new())
);
($elem:expr; $n:expr) => (
- $crate::vec::from_elem($elem, $n)
+ $crate::__export::force_expr!($crate::vec::from_elem($elem, $n))
);
($($x:expr),+ $(,)?) => (
- <[_]>::into_vec(box [$($x),+])
+ $crate::__export::force_expr!(<[_]>::into_vec(box [$($x),+]))
);
}
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 0973a6e..ee03f15 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -353,6 +353,26 @@
/// to upgrade the weak reference before this function returns will result
/// in a `None` value. However, the weak reference may be cloned freely and
/// stored for use at a later time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(arc_new_cyclic)]
+ /// #![allow(dead_code)]
+ /// use std::rc::{Rc, Weak};
+ ///
+ /// struct Gadget {
+ /// self_weak: Weak<Self>,
+ /// // ... more fields
+ /// }
+ /// impl Gadget {
+ /// pub fn new() -> Rc<Self> {
+ /// Rc::new_cyclic(|self_weak| {
+ /// Gadget { self_weak: self_weak.clone(), /* ... */ }
+ /// })
+ /// }
+ /// }
+ /// ```
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
// Construct the inner in the "uninitialized" state with a single
@@ -829,8 +849,8 @@
let offset = unsafe { data_offset(ptr) };
// Reverse the offset to find the original RcBox.
- let fake_ptr = ptr as *mut RcBox<T>;
- let rc_ptr = unsafe { set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)) };
+ let rc_ptr =
+ unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) };
unsafe { Self::from_ptr(rc_ptr) }
}
@@ -850,7 +870,7 @@
pub fn downgrade(this: &Self) -> Weak<T> {
this.inner().inc_weak();
// Make sure we do not create a dangling Weak
- debug_assert!(!is_dangling(this.ptr));
+ debug_assert!(!is_dangling(this.ptr.as_ptr()));
Weak { ptr: this.ptr }
}
@@ -1164,7 +1184,7 @@
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
+ |mem| (ptr as *mut RcBox<T>).set_ptr_value(mem),
)
}
}
@@ -1203,20 +1223,7 @@
)
}
}
-}
-/// Sets the data pointer of a `?Sized` raw pointer.
-///
-/// For a slice/trait object, this sets the `data` field and leaves the rest
-/// unchanged. For a sized raw pointer, this simply sets the pointer.
-unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
- unsafe {
- ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
- }
- ptr
-}
-
-impl<T> Rc<[T]> {
/// Copy elements from slice into newly allocated Rc<\[T\]>
///
/// Unsafe because the caller must either take ownership or bind `T: Copy`
@@ -1860,8 +1867,8 @@
}
}
-pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
- let address = ptr.as_ptr() as *mut () as usize;
+pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
+ let address = ptr as *mut () as usize;
address == usize::MAX
}
@@ -1872,7 +1879,7 @@
strong: &'a Cell<usize>,
}
-impl<T> Weak<T> {
+impl<T: ?Sized> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1902,15 +1909,15 @@
pub fn as_ptr(&self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
- // SAFETY: we must offset the pointer manually, and said pointer may be
- // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
- // because we know that a pointer to unsized T was derived from a real
- // unsized T, as dangling weaks are only created for sized T. wrapping_offset
- // is used so that we can use the same code path for the non-dangling
- // unsized case and the potentially dangling sized case.
- unsafe {
- let offset = data_offset(ptr as *mut T);
- set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
+ if is_dangling(ptr) {
+ // If the pointer is dangling, we return the sentinel directly. This cannot be
+ // a valid payload address, as the payload is at least as aligned as RcBox (usize).
+ ptr as *const T
+ } else {
+ // SAFETY: if is_dangling returns false, then the pointer is dereferencable.
+ // The payload may be dropped at this point, and we have to maintain provenance,
+ // so use raw pointer manipulation.
+ unsafe { &raw const (*ptr).value }
}
}
@@ -1992,22 +1999,24 @@
/// [`new`]: Weak::new
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
- // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
// See Weak::as_ptr for context on how the input pointer is derived.
- let offset = unsafe { data_offset(ptr) };
- // Reverse the offset to find the original RcBox.
- // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
- let ptr = unsafe {
- set_data_ptr(ptr as *mut RcBox<T>, (ptr as *mut u8).wrapping_offset(-offset))
+ let ptr = if is_dangling(ptr as *mut T) {
+ // This is a dangling Weak.
+ ptr as *mut RcBox<T>
+ } else {
+ // Otherwise, we're guaranteed the pointer came from a nondangling Weak.
+ // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
+ let offset = unsafe { data_offset(ptr) };
+ // Thus, we reverse the offset to get the whole RcBox.
+ // SAFETY: the pointer originated from a Weak, so this offset is safe.
+ unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
};
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
}
-}
-impl<T: ?Sized> Weak<T> {
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
/// dropping of the inner value if successful.
///
@@ -2070,7 +2079,7 @@
/// (i.e., when this `Weak` was created by `Weak::new`).
#[inline]
fn inner(&self) -> Option<WeakInner<'_>> {
- if is_dangling(self.ptr) {
+ if is_dangling(self.ptr.as_ptr()) {
None
} else {
// We are careful to *not* create a reference covering the "data" field, as
@@ -2325,21 +2334,19 @@
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Rc<T> {}
-/// Get the offset within an `RcBox` for
-/// a payload of type described by a pointer.
+/// Get the offset within an `RcBox` for the payload behind a pointer.
///
/// # Safety
///
-/// This has the same safety requirements as `align_of_val_raw`. In effect:
-///
-/// - This function is safe for any argument if `T` is sized, and
-/// - if `T` is unsized, the pointer must have appropriate pointer metadata
-/// acquired from the real instance that you are getting this offset for.
+/// The pointer must point to (and have valid metadata for) a previously
+/// valid instance of T, but the T is allowed to be dropped.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
- // Align the unsized value to the end of the `RcBox`.
- // Because it is ?Sized, it will always be the last field in memory.
- // Note: This is a detail of the current implementation of the compiler,
- // and is not a guaranteed language detail. Do not rely on it outside of std.
+ // Align the unsized value to the end of the RcBox.
+ // Because RcBox is repr(C), it will always be the last field in memory.
+ // SAFETY: since the only unsized types possible are slices, trait objects,
+ // and extern types, the input safety requirement is currently enough to
+ // satisfy the requirements of align_of_val_raw; this is an implementation
+ // detail of the language that may not be relied upon outside of std.
unsafe { data_offset_align(align_of_val_raw(ptr)) }
}
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index 2d183a8..843a9b0 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -209,6 +209,30 @@
}
#[test]
+fn test_into_from_weak_raw_unsized() {
+ use std::fmt::Display;
+ use std::string::ToString;
+
+ let arc: Rc<str> = Rc::from("foo");
+ let weak: Weak<str> = Rc::downgrade(&arc);
+
+ let ptr = Weak::into_raw(weak.clone());
+ let weak2 = unsafe { Weak::from_raw(ptr) };
+
+ assert_eq!(unsafe { &*ptr }, "foo");
+ assert!(weak.ptr_eq(&weak2));
+
+ let arc: Rc<dyn Display> = Rc::new(123);
+ let weak: Weak<dyn Display> = Rc::downgrade(&arc);
+
+ let ptr = Weak::into_raw(weak.clone());
+ let weak2 = unsafe { Weak::from_raw(ptr) };
+
+ assert_eq!(unsafe { &*ptr }.to_string(), "123");
+ assert!(weak.ptr_eq(&weak2));
+}
+
+#[test]
fn get_mut() {
let mut x = Rc::new(3);
*Rc::get_mut(&mut x).unwrap() = 4;
@@ -295,6 +319,23 @@
}
#[test]
+fn test_maybe_thin_unsized() {
+ // If/when custom thin DSTs exist, this test should be updated to use one
+ use std::ffi::{CStr, CString};
+
+ let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+ assert_eq!(format!("{:?}", x), "\"swordfish\"");
+ let y: Weak<CStr> = Rc::downgrade(&x);
+ drop(x);
+
+ // At this point, the weak points to a dropped DST
+ assert!(y.upgrade().is_none());
+ // But we still need to be able to get the alloc layout to drop.
+ // CStr has no drop glue, but custom DSTs might, and need to work.
+ drop(y);
+}
+
+#[test]
fn test_from_owned() {
let foo = 123;
let foo_rc = Rc::from(foo);
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 05bfecc..c0d684f 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -846,8 +846,7 @@
let offset = data_offset(ptr);
// Reverse the offset to find the original ArcInner.
- let fake_ptr = ptr as *mut ArcInner<T>;
- let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
+ let arc_ptr = (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset));
Self::from_ptr(arc_ptr)
}
@@ -888,7 +887,7 @@
match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) {
Ok(_) => {
// Make sure we do not create a dangling Weak
- debug_assert!(!is_dangling(this.ptr));
+ debug_assert!(!is_dangling(this.ptr.as_ptr()));
return Weak { ptr: this.ptr };
}
Err(old) => cur = old,
@@ -1131,7 +1130,7 @@
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>,
+ |mem| (ptr as *mut ArcInner<T>).set_ptr_value(mem) as *mut ArcInner<T>,
)
}
}
@@ -1170,20 +1169,7 @@
)
}
}
-}
-/// Sets the data pointer of a `?Sized` raw pointer.
-///
-/// For a slice/trait object, this sets the `data` field and leaves the rest
-/// unchanged. For a sized raw pointer, this simply sets the pointer.
-unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
- unsafe {
- ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
- }
- ptr
-}
-
-impl<T> Arc<[T]> {
/// Copy elements from slice into newly allocated Arc<\[T\]>
///
/// Unsafe because the caller must either take ownership or bind `T: Copy`.
@@ -1653,7 +1639,7 @@
strong: &'a atomic::AtomicUsize,
}
-impl<T> Weak<T> {
+impl<T: ?Sized> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1683,15 +1669,15 @@
pub fn as_ptr(&self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
- // SAFETY: we must offset the pointer manually, and said pointer may be
- // a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
- // because we know that a pointer to unsized T was derived from a real
- // unsized T, as dangling weaks are only created for sized T. wrapping_offset
- // is used so that we can use the same code path for the non-dangling
- // unsized case and the potentially dangling sized case.
- unsafe {
- let offset = data_offset(ptr as *mut T);
- set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
+ if is_dangling(ptr) {
+ // If the pointer is dangling, we return the sentinel directly. This cannot be
+ // a valid payload address, as the payload is at least as aligned as ArcInner (usize).
+ ptr as *const T
+ } else {
+ // SAFETY: if is_dangling returns false, then the pointer is dereferencable.
+ // The payload may be dropped at this point, and we have to maintain provenance,
+ // so use raw pointer manipulation.
+ unsafe { &raw mut (*ptr).data }
}
}
@@ -1773,18 +1759,22 @@
/// [`forget`]: std::mem::forget
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
- // SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
// See Weak::as_ptr for context on how the input pointer is derived.
- let offset = unsafe { data_offset(ptr) };
- // Reverse the offset to find the original ArcInner.
- // SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized)
- let ptr = unsafe {
- set_data_ptr(ptr as *mut ArcInner<T>, (ptr as *mut u8).wrapping_offset(-offset))
+ let ptr = if is_dangling(ptr as *mut T) {
+ // This is a dangling Weak.
+ ptr as *mut ArcInner<T>
+ } else {
+ // Otherwise, we're guaranteed the pointer came from a nondangling Weak.
+ // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
+ let offset = unsafe { data_offset(ptr) };
+ // Thus, we reverse the offset to get the whole RcBox.
+ // SAFETY: the pointer originated from a Weak, so this offset is safe.
+ unsafe { (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
};
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
- unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } }
+ Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
}
}
@@ -1889,7 +1879,7 @@
/// (i.e., when this `Weak` was created by `Weak::new`).
#[inline]
fn inner(&self) -> Option<WeakInner<'_>> {
- if is_dangling(self.ptr) {
+ if is_dangling(self.ptr.as_ptr()) {
None
} else {
// We are careful to *not* create a reference covering the "data" field, as
@@ -2469,21 +2459,19 @@
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Arc<T> {}
-/// Get the offset within an `ArcInner` for
-/// a payload of type described by a pointer.
+/// Get the offset within an `ArcInner` for the payload behind a pointer.
///
/// # Safety
///
-/// This has the same safety requirements as `align_of_val_raw`. In effect:
-///
-/// - This function is safe for any argument if `T` is sized, and
-/// - if `T` is unsized, the pointer must have appropriate pointer metadata
-/// acquired from the real instance that you are getting this offset for.
+/// The pointer must point to (and have valid metadata for) a previously
+/// valid instance of T, but the T is allowed to be dropped.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
- // Align the unsized value to the end of the `ArcInner`.
- // Because it is `?Sized`, it will always be the last field in memory.
- // Note: This is a detail of the current implementation of the compiler,
- // and is not a guaranteed language detail. Do not rely on it outside of std.
+ // Align the unsized value to the end of the ArcInner.
+ // Because RcBox is repr(C), it will always be the last field in memory.
+ // SAFETY: since the only unsized types possible are slices, trait objects,
+ // and extern types, the input safety requirement is currently enough to
+ // satisfy the requirements of align_of_val_raw; this is an implementation
+ // detail of the language that may not be relied upon outside of std.
unsafe { data_offset_align(align_of_val_raw(ptr)) }
}
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 5067af1..4ccb32f 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -159,6 +159,30 @@
}
#[test]
+fn test_into_from_weak_raw_unsized() {
+ use std::fmt::Display;
+ use std::string::ToString;
+
+ let arc: Arc<str> = Arc::from("foo");
+ let weak: Weak<str> = Arc::downgrade(&arc);
+
+ let ptr = Weak::into_raw(weak.clone());
+ let weak2 = unsafe { Weak::from_raw(ptr) };
+
+ assert_eq!(unsafe { &*ptr }, "foo");
+ assert!(weak.ptr_eq(&weak2));
+
+ let arc: Arc<dyn Display> = Arc::new(123);
+ let weak: Weak<dyn Display> = Arc::downgrade(&arc);
+
+ let ptr = Weak::into_raw(weak.clone());
+ let weak2 = unsafe { Weak::from_raw(ptr) };
+
+ assert_eq!(unsafe { &*ptr }.to_string(), "123");
+ assert!(weak.ptr_eq(&weak2));
+}
+
+#[test]
fn test_cowarc_clone_make_mut() {
let mut cow0 = Arc::new(75);
let mut cow1 = cow0.clone();
@@ -330,6 +354,23 @@
}
#[test]
+fn test_maybe_thin_unsized() {
+ // If/when custom thin DSTs exist, this test should be updated to use one
+ use std::ffi::{CStr, CString};
+
+ let x: Arc<CStr> = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+ assert_eq!(format!("{:?}", x), "\"swordfish\"");
+ let y: Weak<CStr> = Arc::downgrade(&x);
+ drop(x);
+
+ // At this point, the weak points to a dropped DST
+ assert!(y.upgrade().is_none());
+ // But we still need to be able to get the alloc layout to drop.
+ // CStr has no drop glue, but custom DSTs might, and need to work.
+ drop(y);
+}
+
+#[test]
fn test_from_owned() {
let foo = 123;
let foo_arc = Arc::from(foo);
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index fcab3fd..6969049 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -33,7 +33,8 @@
}
}
-#[allow(rustc::ineffective_unstable_trait_impl)]
+#[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
+#[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
#[unstable(feature = "wake_trait", issue = "69912")]
impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker {
fn from(waker: Arc<W>) -> Waker {
@@ -43,7 +44,8 @@
}
}
-#[allow(rustc::ineffective_unstable_trait_impl)]
+#[cfg_attr(bootstrap, allow(rustc::ineffective_unstable_trait_impl))]
+#[cfg_attr(not(bootstrap), allow(ineffective_unstable_trait_impl))]
#[unstable(feature = "wake_trait", issue = "69912")]
impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
fn from(waker: Arc<W>) -> RawWaker {
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c5ab7a3..fa0fbaa 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1261,6 +1261,40 @@
Ref { value: f(orig.value), borrow: orig.borrow }
}
+ /// Makes a new `Ref` for an optional component of the borrowed data. The
+ /// original guard is returned as an `Err(..)` if the closure returns
+ /// `None`.
+ ///
+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as
+ /// `Ref::filter_map(...)`. A method would interfere with methods of the same
+ /// name on the contents of a `RefCell` used through `Deref`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(cell_filter_map)]
+ ///
+ /// use std::cell::{RefCell, Ref};
+ ///
+ /// let c = RefCell::new(vec![1, 2, 3]);
+ /// let b1: Ref<Vec<u32>> = c.borrow();
+ /// let b2: Result<Ref<u32>, _> = Ref::filter_map(b1, |v| v.get(1));
+ /// assert_eq!(*b2.unwrap(), 2);
+ /// ```
+ #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+ #[inline]
+ pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
+ where
+ F: FnOnce(&T) -> Option<&U>,
+ {
+ match f(orig.value) {
+ Some(value) => Ok(Ref { value, borrow: orig.borrow }),
+ None => Err(orig),
+ }
+ }
+
/// Splits a `Ref` into multiple `Ref`s for different components of the
/// borrowed data.
///
@@ -1372,6 +1406,58 @@
RefMut { value: f(value), borrow }
}
+ /// Makes a new `RefMut` for an optional component of the borrowed data. The
+ /// original guard is returned as an `Err(..)` if the closure returns
+ /// `None`.
+ ///
+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as
+ /// `RefMut::filter_map(...)`. A method would interfere with methods of the
+ /// same name on the contents of a `RefCell` used through `Deref`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(cell_filter_map)]
+ ///
+ /// use std::cell::{RefCell, RefMut};
+ ///
+ /// let c = RefCell::new(vec![1, 2, 3]);
+ ///
+ /// {
+ /// let b1: RefMut<Vec<u32>> = c.borrow_mut();
+ /// let mut b2: Result<RefMut<u32>, _> = RefMut::filter_map(b1, |v| v.get_mut(1));
+ ///
+ /// if let Ok(mut b2) = b2 {
+ /// *b2 += 2;
+ /// }
+ /// }
+ ///
+ /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
+ /// ```
+ #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+ #[inline]
+ pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Result<RefMut<'b, U>, Self>
+ where
+ F: FnOnce(&mut T) -> Option<&mut U>,
+ {
+ // FIXME(nll-rfc#40): fix borrow-check
+ let RefMut { value, borrow } = orig;
+ let value = value as *mut T;
+ // SAFETY: function holds onto an exclusive reference for the duration
+ // of its call through `orig`, and the pointer is only de-referenced
+ // inside of the function call never allowing the exclusive reference to
+ // escape.
+ match f(unsafe { &mut *value }) {
+ Some(value) => Ok(RefMut { value, borrow }),
+ None => {
+ // SAFETY: same as above.
+ Err(RefMut { value: unsafe { &mut *value }, borrow })
+ }
+ }
+ }
+
/// Splits a `RefMut` into multiple `RefMut`s for different components of the
/// borrowed data.
///
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 0130586..fa5f0d5 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -768,13 +768,6 @@
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
pub fn size_of<T>() -> usize;
- /// Moves a value to an uninitialized memory location.
- ///
- /// Drop glue is not run on the destination.
- ///
- /// The stabilized version of this intrinsic is [`core::ptr::write`](crate::ptr::write).
- pub fn move_val_init<T>(dst: *mut T, src: T);
-
/// The minimum alignment of a type.
///
/// The stabilized version of this intrinsic is [`core::mem::align_of`](crate::mem::align_of).
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 5766fd3..98b8dca 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -286,6 +286,7 @@
#[inline]
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
+ let idx = self.index + idx;
// SAFETY: the caller must uphold the contract for
// `Iterator::__iterator_get_unchecked`.
unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index ba8918b..111feb7 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -286,3 +286,43 @@
NonZeroU128(u128);
NonZeroUsize(usize);
}
+
+macro_rules! nonzero_unsigned_is_power_of_two {
+ ( $( $Ty: ident )+ ) => {
+ $(
+ impl $Ty {
+
+ /// Returns `true` if and only if `self == (1 << k)` for some `k`.
+ ///
+ /// On many architectures, this function can perform better than `is_power_of_two()`
+ /// on the underlying integer type, as special handling of zero can be avoided.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(nonzero_is_power_of_two)]
+ ///
+ #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
+ /// assert!(eight.is_power_of_two());
+ #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
+ /// assert!(!ten.is_power_of_two());
+ /// ```
+ #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")]
+ #[inline]
+ pub const fn is_power_of_two(self) -> bool {
+ // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
+ // On the basic x86-64 target, this saves 3 instructions for the zero check.
+ // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
+ // compared to the `POPCNT` implementation on the underlying integer type.
+
+ intrinsics::ctpop(self.get()) < 2
+ }
+
+ }
+ )+
+ }
+}
+
+nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize }
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 807f114..d2e1bac 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -883,12 +883,19 @@
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn write<T>(dst: *mut T, src: T) {
- if cfg!(debug_assertions) && !is_aligned_and_not_null(dst) {
- // Not panicking to keep codegen impact smaller.
- abort();
+ // We are calling the intrinsics directly to avoid function calls in the generated code
+ // as `intrinsics::copy_nonoverlapping` is a wrapper function.
+ extern "rust-intrinsic" {
+ fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}
- // SAFETY: the caller must uphold the safety contract for `move_val_init`.
- unsafe { intrinsics::move_val_init(&mut *dst, src) }
+
+ // SAFETY: the caller must guarantee that `dst` is valid for writes.
+ // `dst` cannot overlap `src` because the caller has mutable access
+ // to `dst` while `src` is owned by this function.
+ unsafe {
+ copy_nonoverlapping(&src as *const T, dst, 1);
+ intrinsics::forget(src);
+ }
}
/// Overwrites a memory location with the given value without reading or
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 6de2714..de8d7fc 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -889,6 +889,46 @@
}
/// Splits the slice into a slice of `N`-element arrays,
+ /// assuming that there's no remainder.
+ ///
+ /// # Safety
+ ///
+ /// This may only be called when
+ /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
+ /// - `N != 0`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
+ /// let chunks: &[[char; 1]] =
+ /// // SAFETY: 1-element chunks never have remainder
+ /// unsafe { slice.as_chunks_unchecked() };
+ /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+ /// let chunks: &[[char; 3]] =
+ /// // SAFETY: The slice length (6) is a multiple of 3
+ /// unsafe { slice.as_chunks_unchecked() };
+ /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
+ ///
+ /// // These would be unsound:
+ /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
+ /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+ debug_assert_ne!(N, 0);
+ debug_assert_eq!(self.len() % N, 0);
+ let new_len =
+ // SAFETY: Our precondition is exactly what's needed to call this
+ unsafe { crate::intrinsics::exact_div(self.len(), N) };
+ // SAFETY: We cast a slice of `new_len * N` elements into
+ // a slice of `new_len` many `N` elements chunks.
+ unsafe { from_raw_parts(self.as_ptr().cast(), new_len) }
+ }
+
+ /// Splits the slice into a slice of `N`-element arrays,
/// starting at the beginning of the slice,
/// and a remainder slice with length strictly less than `N`.
///
@@ -912,12 +952,42 @@
assert_ne!(N, 0);
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at(len * N);
- // SAFETY: We cast a slice of `len * N` elements into
- // a slice of `len` many `N` elements chunks.
- let array_slice: &[[T; N]] = unsafe { from_raw_parts(multiple_of_n.as_ptr().cast(), len) };
+ // SAFETY: We already panicked for zero, and ensured by construction
+ // that the length of the subslice is a multiple of N.
+ let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
(array_slice, remainder)
}
+ /// Splits the slice into a slice of `N`-element arrays,
+ /// starting at the end of the slice,
+ /// and a remainder slice with length strictly less than `N`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
+ /// error before this method gets stabilized.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let (remainder, chunks) = slice.as_rchunks();
+ /// assert_eq!(remainder, &['l']);
+ /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
+ assert_ne!(N, 0);
+ let len = self.len() / N;
+ let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
+ // SAFETY: We already panicked for zero, and ensured by construction
+ // that the length of the subslice is a multiple of N.
+ let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
+ (remainder, array_slice)
+ }
+
/// Returns an iterator over `N` elements of the slice at a time, starting at the
/// beginning of the slice.
///
@@ -953,6 +1023,48 @@
}
/// Splits the slice into a slice of `N`-element arrays,
+ /// assuming that there's no remainder.
+ ///
+ /// # Safety
+ ///
+ /// This may only be called when
+ /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
+ /// - `N != 0`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
+ /// let chunks: &mut [[char; 1]] =
+ /// // SAFETY: 1-element chunks never have remainder
+ /// unsafe { slice.as_chunks_unchecked_mut() };
+ /// chunks[0] = ['L'];
+ /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
+ /// let chunks: &mut [[char; 3]] =
+ /// // SAFETY: The slice length (6) is a multiple of 3
+ /// unsafe { slice.as_chunks_unchecked_mut() };
+ /// chunks[1] = ['a', 'x', '?'];
+ /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
+ ///
+ /// // These would be unsound:
+ /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
+ /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+ debug_assert_ne!(N, 0);
+ debug_assert_eq!(self.len() % N, 0);
+ let new_len =
+ // SAFETY: Our precondition is exactly what's needed to call this
+ unsafe { crate::intrinsics::exact_div(self.len(), N) };
+ // SAFETY: We cast a slice of `new_len * N` elements into
+ // a slice of `new_len` many `N` elements chunks.
+ unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), new_len) }
+ }
+
+ /// Splits the slice into a slice of `N`-element arrays,
/// starting at the beginning of the slice,
/// and a remainder slice with length strictly less than `N`.
///
@@ -982,13 +1094,48 @@
assert_ne!(N, 0);
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at_mut(len * N);
- let array_slice: &mut [[T; N]] =
- // SAFETY: We cast a slice of `len * N` elements into
- // a slice of `len` many `N` elements chunks.
- unsafe { from_raw_parts_mut(multiple_of_n.as_mut_ptr().cast(), len) };
+ // SAFETY: We already panicked for zero, and ensured by construction
+ // that the length of the subslice is a multiple of N.
+ let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
(array_slice, remainder)
}
+ /// Splits the slice into a slice of `N`-element arrays,
+ /// starting at the end of the slice,
+ /// and a remainder slice with length strictly less than `N`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
+ /// error before this method gets stabilized.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let v = &mut [0, 0, 0, 0, 0];
+ /// let mut count = 1;
+ ///
+ /// let (remainder, chunks) = v.as_rchunks_mut();
+ /// remainder[0] = 9;
+ /// for chunk in chunks {
+ /// *chunk = [count; 2];
+ /// count += 1;
+ /// }
+ /// assert_eq!(v, &[9, 1, 1, 2, 2]);
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
+ assert_ne!(N, 0);
+ let len = self.len() / N;
+ let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
+ // SAFETY: We already panicked for zero, and ensured by construction
+ // that the length of the subslice is a multiple of N.
+ let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
+ (remainder, array_slice)
+ }
+
/// Returns an iterator over `N` elements of the slice at a time, starting at the
/// beginning of the slice.
///
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 6851f3f..42c9d9f 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -84,7 +84,7 @@
impl<T, E> Poll<Option<Result<T, E>>> {
/// Changes the success value of this `Poll` with the closure provided.
- #[unstable(feature = "poll_map", issue = "63514")]
+ #[stable(feature = "poll_map", since = "1.51.0")]
pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
where
F: FnOnce(T) -> U,
@@ -98,7 +98,7 @@
}
/// Changes the error value of this `Poll` with the closure provided.
- #[unstable(feature = "poll_map", issue = "63514")]
+ #[stable(feature = "poll_map", since = "1.51.0")]
pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
where
F: FnOnce(E) -> U,
diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs
index 691767e..bc5421b 100644
--- a/library/core/tests/iter.rs
+++ b/library/core/tests/iter.rs
@@ -2,6 +2,7 @@
use core::cell::Cell;
use core::convert::TryFrom;
+use core::iter::TrustedRandomAccess;
use core::iter::*;
/// An iterator wrapper that panics whenever `next` or `next_back` is called
@@ -602,6 +603,26 @@
}
#[test]
+fn test_zip_trusted_random_access_composition() {
+ let a = [0, 1, 2, 3, 4];
+ let b = a;
+ let c = a;
+
+ let a = a.iter().copied();
+ let b = b.iter().copied();
+ let mut c = c.iter().copied();
+ c.next();
+
+ let mut z1 = a.zip(b);
+ assert_eq!(z1.next().unwrap(), (0, 0));
+
+ let mut z2 = z1.zip(c);
+ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
+ assert_trusted_random_access(&z2);
+ assert_eq!(z2.next().unwrap(), ((1, 1), 1));
+}
+
+#[test]
fn test_iterator_step_by() {
// Identity
let mut it = (0..).step_by(1).take(3);
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index bc737cd..98f5982 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -75,6 +75,7 @@
#![feature(const_option)]
#![feature(integer_atomics)]
#![feature(slice_group_by)]
+#![feature(trusted_random_access)]
#![deny(unsafe_op_in_unsafe_fn)]
extern crate test;
diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs
index 1c172f4..32f05d1 100644
--- a/library/core/tests/num/dec2flt/mod.rs
+++ b/library/core/tests/num/dec2flt/mod.rs
@@ -21,7 +21,6 @@
}};
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn ordinary() {
test_literal!(1.0);
@@ -38,7 +37,6 @@
test_literal!(2.2250738585072014e-308);
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn special_code_paths() {
test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand
diff --git a/library/core/tests/num/dec2flt/rawfp.rs b/library/core/tests/num/dec2flt/rawfp.rs
index c098b9c..34a3720 100644
--- a/library/core/tests/num/dec2flt/rawfp.rs
+++ b/library/core/tests/num/dec2flt/rawfp.rs
@@ -81,7 +81,6 @@
assert_eq!(rounded.k, adjusted_k + 1);
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn prev_float_monotonic() {
let mut x = 1.0;
@@ -117,7 +116,6 @@
assert_eq!(next_float(f64::INFINITY), f64::INFINITY);
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn next_prev_identity() {
for &x in &SOME_FLOATS {
@@ -128,7 +126,6 @@
}
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn next_float_monotonic() {
let mut x = 0.49999999999999;
diff --git a/library/core/tests/num/flt2dec/strategy/dragon.rs b/library/core/tests/num/flt2dec/strategy/dragon.rs
index 3d985c6..fc2e724 100644
--- a/library/core/tests/num/flt2dec/strategy/dragon.rs
+++ b/library/core/tests/num/flt2dec/strategy/dragon.rs
@@ -13,7 +13,6 @@
}
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn shortest_sanity_test() {
f64_shortest_sanity_test(format_shortest);
diff --git a/library/core/tests/num/flt2dec/strategy/grisu.rs b/library/core/tests/num/flt2dec/strategy/grisu.rs
index 7e6c8ad..b59a3b9 100644
--- a/library/core/tests/num/flt2dec/strategy/grisu.rs
+++ b/library/core/tests/num/flt2dec/strategy/grisu.rs
@@ -33,7 +33,6 @@
}
}
-#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
#[test]
fn shortest_sanity_test() {
f64_shortest_sanity_test(format_shortest);
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 0680b1f..829fc38 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -52,6 +52,9 @@
/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
/// the [`Eq`] trait, changes while it is in the map. This is normally only
/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
+/// The behavior resulting from such a logic error is not specified, but will
+/// not result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
///
/// The hash table implementation is a Rust port of Google's [SwissTable].
/// The original C++ version of SwissTable can be found [here], and this
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index f49e580..baa3026 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -37,7 +37,9 @@
/// item's hash, as determined by the [`Hash`] trait, or its equality, as
/// determined by the [`Eq`] trait, changes while it is in the set. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code.
+/// unsafe code. The behavior resulting from such a logic error is not
+/// specified, but will not result in undefined behavior. This could include
+/// panics, incorrect results, aborts, memory leaks, and non-termination.
///
/// # Examples
///
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 16c18d6..8bae3da 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -271,6 +271,20 @@
Ok(nread)
}
+ // Small read_exacts from a BufReader are extremely common when used with a deserializer.
+ // The default implementation calls read in a loop, which results in surprisingly poor code
+ // generation for the common path where the buffer has enough bytes to fill the passed-in
+ // buffer.
+ fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+ if self.buffer().len() >= buf.len() {
+ buf.copy_from_slice(&self.buffer()[..buf.len()]);
+ self.consume(buf.len());
+ return Ok(());
+ }
+
+ crate::io::default_read_exact(self, buf)
+ }
+
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
if self.pos == self.cap && total_len >= self.buf.len() {
diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs
index 66a64f6..f6c2b49 100644
--- a/library/std/src/io/buffered/tests.rs
+++ b/library/std/src/io/buffered/tests.rs
@@ -444,6 +444,18 @@
}
#[bench]
+fn bench_buffered_reader_small_reads(b: &mut test::Bencher) {
+ let data = (0..u8::MAX).cycle().take(1024 * 4).collect::<Vec<_>>();
+ b.iter(|| {
+ let mut reader = BufReader::new(&data[..]);
+ let mut buf = [0u8; 4];
+ for _ in 0..1024 {
+ reader.read_exact(&mut buf).unwrap();
+ }
+ });
+}
+
+#[bench]
fn bench_buffered_writer(b: &mut test::Bencher) {
b.iter(|| BufWriter::new(io::sink()));
}
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 3f5b7c0..c87a565 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -416,6 +416,25 @@
write(buf)
}
+pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
+ while !buf.is_empty() {
+ match this.read(buf) {
+ Ok(0) => break,
+ Ok(n) => {
+ let tmp = buf;
+ buf = &mut tmp[n..];
+ }
+ Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
+ }
+ if !buf.is_empty() {
+ Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+ } else {
+ Ok(())
+ }
+}
+
/// The `Read` trait allows for reading bytes from a source.
///
/// Implementors of the `Read` trait are called 'readers'.
@@ -766,23 +785,8 @@
/// }
/// ```
#[stable(feature = "read_exact", since = "1.6.0")]
- fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
- while !buf.is_empty() {
- match self.read(buf) {
- Ok(0) => break,
- Ok(n) => {
- let tmp = buf;
- buf = &mut tmp[n..];
- }
- Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
- Err(e) => return Err(e),
- }
- }
- if !buf.is_empty() {
- Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
- } else {
- Ok(())
- }
+ fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
+ default_read_exact(self, buf)
}
/// Creates a "by reference" adaptor for this instance of `Read`.
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 945b436..ddcb404 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -314,10 +314,20 @@
) -> libc::c_int
}
let addchdir = match self.get_cwd() {
- Some(cwd) => match posix_spawn_file_actions_addchdir_np.get() {
- Some(f) => Some((f, cwd)),
- None => return Ok(None),
- },
+ Some(cwd) => {
+ if cfg!(target_os = "macos") {
+ // There is a bug in macOS where a relative executable
+ // path like "../myprogram" will cause `posix_spawn` to
+ // successfully launch the program, but erroneously return
+ // ENOENT when used with posix_spawn_file_actions_addchdir_np
+ // which was introduced in macOS 10.15.
+ return Ok(None);
+ }
+ match posix_spawn_file_actions_addchdir_np.get() {
+ Some(f) => Some((f, cwd)),
+ None => return Ok(None),
+ }
+ }
None => None,
};
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 6d2d7bb..5350c9e 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -465,8 +465,21 @@
def downloading_llvm(self):
opt = self.get_toml('download-ci-llvm', 'llvm')
+ # This is currently all tier 1 targets (since others may not have CI
+ # artifacts)
+ # https://doc.rust-lang.org/rustc/platform-support.html#tier-1
+ supported_platforms = [
+ "aarch64-unknown-linux-gnu",
+ "i686-pc-windows-gnu",
+ "i686-pc-windows-msvc",
+ "i686-unknown-linux-gnu",
+ "x86_64-unknown-linux-gnu",
+ "x86_64-apple-darwin",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc",
+ ]
return opt == "true" \
- or (opt == "if-available" and self.build == "x86_64-unknown-linux-gnu")
+ or (opt == "if-available" and self.build in supported_platforms)
def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None):
if date is None:
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index ec9ce4c..62065e2 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -814,12 +814,22 @@
cargo.env("REAL_LIBRARY_PATH", e);
}
+ // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
+ // from out of tree it shouldn't matter, since x.py is only used for
+ // building in-tree.
+ let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
match self.build.config.color {
Color::Always => {
cargo.arg("--color=always");
+ for log in &color_logs {
+ cargo.env(log, "always");
+ }
}
Color::Never => {
cargo.arg("--color=never");
+ for log in &color_logs {
+ cargo.env(log, "never");
+ }
}
Color::Auto => {} // nothing to do
}
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 72a9793..c19bb53 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -73,7 +73,7 @@
fn run(self, builder: &Builder<'_>) {
let target = self.target;
- let compiler = builder.compiler(0, builder.config.build);
+ let compiler = builder.compiler(builder.top_stage, builder.config.build);
let mut cargo = builder.cargo(
compiler,
@@ -84,7 +84,10 @@
);
std_cargo(builder, target, compiler.stage, &mut cargo);
- builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
+ builder.info(&format!(
+ "Checking stage{} std artifacts ({} -> {})",
+ builder.top_stage, &compiler.host, target
+ ));
run_cargo(
builder,
cargo,
@@ -94,9 +97,13 @@
true,
);
- let libdir = builder.sysroot_libdir(compiler, target);
- let hostdir = builder.sysroot_libdir(compiler, compiler.host);
- add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
+ // We skip populating the sysroot in non-zero stage because that'll lead
+ // to rlib/rmeta conflicts if std gets built during this session.
+ if compiler.stage == 0 {
+ let libdir = builder.sysroot_libdir(compiler, target);
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
+ }
// Then run cargo again, once we've put the rmeta files for the library
// crates into the sysroot. This is needed because e.g., core's tests
@@ -124,8 +131,8 @@
}
builder.info(&format!(
- "Checking std test/bench/example targets ({} -> {})",
- &compiler.host, target
+ "Checking stage{} std test/bench/example targets ({} -> {})",
+ builder.top_stage, &compiler.host, target
));
run_cargo(
builder,
@@ -163,10 +170,20 @@
/// the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory.
fn run(self, builder: &Builder<'_>) {
- let compiler = builder.compiler(0, builder.config.build);
+ let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
- builder.ensure(Std { target });
+ if compiler.stage != 0 {
+ // If we're not in stage 0, then we won't have a std from the beta
+ // compiler around. That means we need to make sure there's one in
+ // the sysroot for the compiler to find. Otherwise, we're going to
+ // fail when building crates that need to generate code (e.g., build
+ // scripts and their dependencies).
+ builder.ensure(crate::compile::Std { target: compiler.host, compiler });
+ builder.ensure(crate::compile::Std { target, compiler });
+ } else {
+ builder.ensure(Std { target });
+ }
let mut cargo = builder.cargo(
compiler,
@@ -187,7 +204,10 @@
cargo.arg("-p").arg(krate.name);
}
- builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
+ builder.info(&format!(
+ "Checking stage{} compiler artifacts ({} -> {})",
+ builder.top_stage, &compiler.host, target
+ ));
run_cargo(
builder,
cargo,
@@ -225,7 +245,7 @@
}
fn run(self, builder: &Builder<'_>) {
- let compiler = builder.compiler(0, builder.config.build);
+ let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
let backend = self.backend;
@@ -244,8 +264,8 @@
rustc_cargo_env(builder, &mut cargo, target);
builder.info(&format!(
- "Checking {} artifacts ({} -> {})",
- backend, &compiler.host.triple, target.triple
+ "Checking stage{} {} artifacts ({} -> {})",
+ builder.top_stage, backend, &compiler.host.triple, target.triple
));
run_cargo(
@@ -280,7 +300,7 @@
}
fn run(self, builder: &Builder<'_>) {
- let compiler = builder.compiler(0, builder.config.build);
+ let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
builder.ensure(Rustc { target });
@@ -301,7 +321,8 @@
}
builder.info(&format!(
- "Checking {} artifacts ({} -> {})",
+ "Checking stage{} {} artifacts ({} -> {})",
+ builder.top_stage,
stringify!($name).to_lowercase(),
&compiler.host.triple,
target.triple
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index f4d89a8..ec1308a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -377,6 +377,7 @@
configure_args: Option<Vec<String>>,
local_rebuild: Option<bool>,
print_step_timings: Option<bool>,
+ check_stage: Option<u32>,
doc_stage: Option<u32>,
build_stage: Option<u32>,
test_stage: Option<u32>,
@@ -676,6 +677,7 @@
// See https://github.com/rust-lang/compiler-team/issues/326
config.stage = match config.cmd {
+ Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0),
Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0),
Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1),
Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1),
@@ -685,7 +687,6 @@
// These are all bootstrap tools, which don't depend on the compiler.
// The stage we pass shouldn't matter, but use 0 just in case.
Subcommand::Clean { .. }
- | Subcommand::Check { .. }
| Subcommand::Clippy { .. }
| Subcommand::Fix { .. }
| Subcommand::Run { .. }
@@ -816,8 +817,10 @@
check_ci_llvm!(llvm.allow_old_toolchain);
check_ci_llvm!(llvm.polly);
- // CI-built LLVM is shared
- config.llvm_link_shared = true;
+ // CI-built LLVM can be either dynamic or static.
+ let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
+ let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt")));
+ config.llvm_link_shared = link_type == "dynamic";
}
if config.llvm_thin_lto {
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e2c2e19..af9c0fb 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1800,19 +1800,11 @@
}
}
-/// Maybe add libLLVM.so to the given destination lib-dir. It will only have
-/// been built if LLVM tools are linked dynamically.
+/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
///
-/// Note: This function does not yet support Windows, but we also don't support
-/// linking LLVM tools dynamically on Windows yet.
-fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
- if !builder.config.llvm_link_shared {
- // We do not need to copy LLVM files into the sysroot if it is not
- // dynamically linked; it is already included into librustc_llvm
- // statically.
- return;
- }
+/// Returns whether the files were actually copied.
+fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
if let Some(config) = builder.config.target_config.get(&target) {
if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
// If the LLVM was externally provided, then we don't currently copy
@@ -1828,7 +1820,7 @@
//
// If the LLVM is coming from ourselves (just from CI) though, we
// still want to install it, as it otherwise won't be available.
- return;
+ return false;
}
}
@@ -1837,31 +1829,48 @@
// clear why this is the case, though. llvm-config will emit the versioned
// paths and we don't want those in the sysroot (as we're expecting
// unversioned paths).
- if target.contains("apple-darwin") {
+ if target.contains("apple-darwin") && builder.config.llvm_link_shared {
let src_libdir = builder.llvm_out(target).join("lib");
let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
if llvm_dylib_path.exists() {
builder.install(&llvm_dylib_path, dst_libdir, 0o644);
}
+ !builder.config.dry_run
} else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
- let files = output(Command::new(llvm_config).arg("--libfiles"));
- for file in files.lines() {
+ let mut cmd = Command::new(llvm_config);
+ cmd.arg("--libfiles");
+ builder.verbose(&format!("running {:?}", cmd));
+ let files = output(&mut cmd);
+ for file in files.trim_end().split(' ') {
builder.install(Path::new(file), dst_libdir, 0o644);
}
+ !builder.config.dry_run
+ } else {
+ false
}
}
/// Maybe add libLLVM.so to the target lib-dir for linking.
pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
- maybe_install_llvm(builder, target, &dst_libdir);
+ // We do not need to copy LLVM files into the sysroot if it is not
+ // dynamically linked; it is already included into librustc_llvm
+ // statically.
+ if builder.config.llvm_link_shared {
+ maybe_install_llvm(builder, target, &dst_libdir);
+ }
}
/// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir =
sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
- maybe_install_llvm(builder, target, &dst_libdir);
+ // We do not need to copy LLVM files into the sysroot if it is not
+ // dynamically linked; it is already included into librustc_llvm
+ // statically.
+ if builder.config.llvm_link_shared {
+ maybe_install_llvm(builder, target, &dst_libdir);
+ }
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
@@ -1973,7 +1982,10 @@
// `$ORIGIN/../lib` can find it. It may also be used as a dependency
// of `rustc-dev` to support the inherited `-lLLVM` when using the
// compiler libraries.
- maybe_install_llvm(builder, target, &tarball.image_dir().join("lib"));
+ let dst_libdir = tarball.image_dir().join("lib");
+ maybe_install_llvm(builder, target, &dst_libdir);
+ let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" };
+ t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
Some(tarball.generate())
}
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index b29ecd6..fb5b058 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/80087
+Last change is for: https://github.com/rust-lang/rust/pull/80932
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index d6a45f1..55062e1 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -614,14 +614,10 @@
};
if let Subcommand::Check { .. } = &cmd {
- if matches.opt_str("stage").is_some() {
- println!("--stage not supported for x.py check, always treated as stage 0");
- process::exit(1);
- }
if matches.opt_str("keep-stage").is_some()
|| matches.opt_str("keep-stage-std").is_some()
{
- println!("--keep-stage not supported for x.py check, only one stage available");
+ println!("--keep-stage not yet supported for x.py check");
process::exit(1);
}
}
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 6412df3..609ac8b 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -171,7 +171,6 @@
.define("LLVM_TARGETS_TO_BUILD", llvm_targets)
.define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets)
.define("LLVM_INCLUDE_EXAMPLES", "OFF")
- .define("LLVM_INCLUDE_TESTS", "OFF")
.define("LLVM_INCLUDE_DOCS", "OFF")
.define("LLVM_INCLUDE_BENCHMARKS", "OFF")
.define("LLVM_ENABLE_TERMINFO", "OFF")
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 43fb53b..83114a7 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -313,12 +313,12 @@
tcx: TyCtxt<'tcx>,
pred: ty::Predicate<'tcx>,
) -> FxHashSet<GenericParamDef> {
- let bound_predicate = pred.bound_atom();
+ let bound_predicate = pred.kind();
let regions = match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(poly_trait_pred, _) => {
+ ty::PredicateKind::Trait(poly_trait_pred, _) => {
tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred))
}
- ty::PredicateAtom::Projection(poly_proj_pred) => {
+ ty::PredicateKind::Projection(poly_proj_pred) => {
tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_proj_pred))
}
_ => return FxHashSet::default(),
@@ -463,8 +463,8 @@
.iter()
.filter(|p| {
!orig_bounds.contains(p)
- || match p.skip_binders() {
- ty::PredicateAtom::Trait(pred, _) => pred.def_id() == sized_trait,
+ || match p.kind().skip_binder() {
+ ty::PredicateKind::Trait(pred, _) => pred.def_id() == sized_trait,
_ => false,
}
})
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 545f432..3ddb2ad 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -219,7 +219,6 @@
impl Clean<Item> for doctree::Module<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let mut items: Vec<Item> = vec![];
- items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
items.extend(self.mods.iter().map(|x| x.clean(cx)));
items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
@@ -466,20 +465,20 @@
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
- let bound_predicate = self.bound_atom();
+ let bound_predicate = self.kind();
match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
- ty::PredicateAtom::RegionOutlives(pred) => pred.clean(cx),
- ty::PredicateAtom::TypeOutlives(pred) => pred.clean(cx),
- ty::PredicateAtom::Projection(pred) => Some(pred.clean(cx)),
+ ty::PredicateKind::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
+ ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
+ ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
+ ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
- ty::PredicateAtom::Subtype(..)
- | ty::PredicateAtom::WellFormed(..)
- | ty::PredicateAtom::ObjectSafe(..)
- | ty::PredicateAtom::ClosureKind(..)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => panic!("not user writable"),
+ ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
}
}
}
@@ -744,19 +743,19 @@
.flat_map(|(p, _)| {
let mut projection = None;
let param_idx = (|| {
- let bound_p = p.bound_atom();
+ let bound_p = p.kind();
match bound_p.skip_binder() {
- ty::PredicateAtom::Trait(pred, _constness) => {
+ ty::PredicateKind::Trait(pred, _constness) => {
if let ty::Param(param) = pred.self_ty().kind() {
return Some(param.index);
}
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
if let ty::Param(param) = ty.kind() {
return Some(param.index);
}
}
- ty::PredicateAtom::Projection(p) => {
+ ty::PredicateKind::Projection(p) => {
if let ty::Param(param) = p.projection_ty.self_ty().kind() {
projection = Some(bound_p.rebind(p));
return Some(param.index);
@@ -1685,14 +1684,12 @@
let mut bounds = bounds
.iter()
.filter_map(|bound| {
- // Note: The substs of opaque types can contain unbound variables,
- // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
- let bound_predicate = bound.bound_atom_with_opt_escaping(cx.tcx);
+ let bound_predicate = bound.kind();
let trait_ref = match bound_predicate.skip_binder() {
- ty::PredicateAtom::Trait(tr, _constness) => {
+ ty::PredicateKind::Trait(tr, _constness) => {
bound_predicate.rebind(tr.trait_ref)
}
- ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
if let Some(r) = reg.clean(cx) {
regions.push(GenericBound::Outlives(r));
}
@@ -1711,8 +1708,8 @@
let bounds: Vec<_> = bounds
.iter()
.filter_map(|bound| {
- if let ty::PredicateAtom::Projection(proj) =
- bound.bound_atom_with_opt_escaping(cx.tcx).skip_binder()
+ if let ty::PredicateKind::Projection(proj) =
+ bound.kind().skip_binder()
{
if proj.projection_ty.trait_ref(cx.tcx)
== trait_ref.skip_binder()
@@ -2015,7 +2012,7 @@
ItemKind::Fn(ref sig, ref generics, body_id) => {
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
}
- hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
+ ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
let items = item_ids
.iter()
.map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
@@ -2034,6 +2031,9 @@
ItemKind::ExternCrate(orig_name) => {
return clean_extern_crate(item, name, orig_name, cx);
}
+ ItemKind::Use(path, kind) => {
+ return clean_use_statement(item, name, path, kind, cx);
+ }
_ => unreachable!("not yet converted"),
};
@@ -2155,105 +2155,97 @@
}]
}
-impl Clean<Vec<Item>> for doctree::Import<'_> {
- fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
- // We need this comparison because some imports (for std types for example)
- // are "inserted" as well but directly by the compiler and they should not be
- // taken into account.
- if self.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
- return Vec::new();
- }
-
- let (doc_meta_item, please_inline) = self.attrs.lists(sym::doc).get_word_attr(sym::inline);
- let pub_underscore = self.vis.node.is_pub() && self.name == kw::Underscore;
-
- if pub_underscore && please_inline {
- rustc_errors::struct_span_err!(
- cx.tcx.sess,
- doc_meta_item.unwrap().span(),
- E0780,
- "anonymous imports cannot be inlined"
- )
- .span_label(self.span, "anonymous import")
- .emit();
- }
-
- // We consider inlining the documentation of `pub use` statements, but we
- // forcefully don't inline if this is not public or if the
- // #[doc(no_inline)] attribute is present.
- // Don't inline doc(hidden) imports so they can be stripped at a later stage.
- let mut denied = !self.vis.node.is_pub()
- || pub_underscore
- || self.attrs.iter().any(|a| {
- a.has_name(sym::doc)
- && match a.meta_item_list() {
- Some(l) => {
- attr::list_contains_name(&l, sym::no_inline)
- || attr::list_contains_name(&l, sym::hidden)
- }
- None => false,
- }
- });
- // Also check whether imports were asked to be inlined, in case we're trying to re-export a
- // crate in Rust 2018+
- let path = self.path.clean(cx);
- let inner = if self.glob {
- if !denied {
- let mut visited = FxHashSet::default();
- if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
- return items;
- }
- }
- Import::new_glob(resolve_use_source(cx, path), true)
- } else {
- let name = self.name;
- if !please_inline {
- if let Res::Def(DefKind::Mod, did) = path.res {
- if !did.is_local() && did.index == CRATE_DEF_INDEX {
- // if we're `pub use`ing an extern crate root, don't inline it unless we
- // were specifically asked for it
- denied = true;
- }
- }
- }
- if !denied {
- let mut visited = FxHashSet::default();
-
- if let Some(mut items) = inline::try_inline(
- cx,
- cx.tcx.parent_module(self.id).to_def_id(),
- path.res,
- name,
- Some(self.attrs),
- &mut visited,
- ) {
- items.push(Item {
- name: None,
- attrs: box self.attrs.clean(cx),
- source: self.span.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
- visibility: self.vis.clean(cx),
- kind: box ImportItem(Import::new_simple(
- self.name,
- resolve_use_source(cx, path),
- false,
- )),
- });
- return items;
- }
- }
- Import::new_simple(name, resolve_use_source(cx, path), true)
- };
-
- vec![Item {
- name: None,
- attrs: box self.attrs.clean(cx),
- source: self.span.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
- visibility: self.vis.clean(cx),
- kind: box ImportItem(inner),
- }]
+fn clean_use_statement(
+ import: &hir::Item<'_>,
+ name: Symbol,
+ path: &hir::Path<'_>,
+ kind: hir::UseKind,
+ cx: &DocContext<'_>,
+) -> Vec<Item> {
+ // We need this comparison because some imports (for std types for example)
+ // are "inserted" as well but directly by the compiler and they should not be
+ // taken into account.
+ if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
+ return Vec::new();
}
+
+ let (doc_meta_item, please_inline) = import.attrs.lists(sym::doc).get_word_attr(sym::inline);
+ let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore;
+
+ if pub_underscore && please_inline {
+ rustc_errors::struct_span_err!(
+ cx.tcx.sess,
+ doc_meta_item.unwrap().span(),
+ E0780,
+ "anonymous imports cannot be inlined"
+ )
+ .span_label(import.span, "anonymous import")
+ .emit();
+ }
+
+ // We consider inlining the documentation of `pub use` statements, but we
+ // forcefully don't inline if this is not public or if the
+ // #[doc(no_inline)] attribute is present.
+ // Don't inline doc(hidden) imports so they can be stripped at a later stage.
+ let mut denied = !import.vis.node.is_pub()
+ || pub_underscore
+ || import.attrs.iter().any(|a| {
+ a.has_name(sym::doc)
+ && match a.meta_item_list() {
+ Some(l) => {
+ attr::list_contains_name(&l, sym::no_inline)
+ || attr::list_contains_name(&l, sym::hidden)
+ }
+ None => false,
+ }
+ });
+
+ // Also check whether imports were asked to be inlined, in case we're trying to re-export a
+ // crate in Rust 2018+
+ let def_id = cx.tcx.hir().local_def_id(import.hir_id).to_def_id();
+ let path = path.clean(cx);
+ let inner = if kind == hir::UseKind::Glob {
+ if !denied {
+ let mut visited = FxHashSet::default();
+ if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
+ return items;
+ }
+ }
+ Import::new_glob(resolve_use_source(cx, path), true)
+ } else {
+ if !please_inline {
+ if let Res::Def(DefKind::Mod, did) = path.res {
+ if !did.is_local() && did.index == CRATE_DEF_INDEX {
+ // if we're `pub use`ing an extern crate root, don't inline it unless we
+ // were specifically asked for it
+ denied = true;
+ }
+ }
+ }
+ if !denied {
+ let mut visited = FxHashSet::default();
+
+ if let Some(mut items) = inline::try_inline(
+ cx,
+ cx.tcx.parent_module(import.hir_id).to_def_id(),
+ path.res,
+ name,
+ Some(import.attrs),
+ &mut visited,
+ ) {
+ items.push(Item::from_def_id_and_parts(
+ def_id,
+ None,
+ ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
+ cx,
+ ));
+ return items;
+ }
+ }
+ Import::new_simple(name, resolve_use_source(cx, path), true)
+ };
+
+ vec![Item::from_def_id_and_parts(def_id, None, ImportItem(inner), cx)]
}
impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 16aaa9c..d4d0a8c 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -129,7 +129,7 @@
.predicates
.iter()
.filter_map(|(pred, _)| {
- if let ty::PredicateAtom::Trait(pred, _) = pred.skip_binders() {
+ if let ty::PredicateKind::Trait(pred, _) = pred.kind().skip_binder() {
if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None }
} else {
None
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index cf51162..3de97f2 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -500,6 +500,12 @@
}
}
+ // Reset errors so that they won't be reported as compiler bugs when dropping the
+ // handler. Any errors in the tests will be reported when the test file is compiled,
+ // Note that we still need to cancel the errors above otherwise `DiagnosticBuilder`
+ // will panic on drop.
+ sess.span_diagnostic.reset_err_count();
+
(found_main, found_extern_crate, found_macro)
})
});
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 4710c91..f90623c 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -2,7 +2,6 @@
//! manner (and with prettier names) before cleaning.
crate use self::StructType::*;
-use rustc_ast as ast;
use rustc_span::{self, Span, Symbol};
use rustc_hir as hir;
@@ -11,7 +10,6 @@
crate name: Option<Symbol>,
crate where_outer: Span,
crate where_inner: Span,
- crate imports: Vec<Import<'hir>>,
crate mods: Vec<Module<'hir>>,
crate id: hir::HirId,
// (item, renamed)
@@ -28,7 +26,6 @@
id: hir::CRATE_HIR_ID,
where_outer: rustc_span::DUMMY_SP,
where_inner: rustc_span::DUMMY_SP,
- imports: Vec::new(),
mods: Vec::new(),
items: Vec::new(),
foreigns: Vec::new(),
@@ -48,17 +45,6 @@
Unit,
}
-#[derive(Debug)]
-crate struct Import<'hir> {
- crate name: Symbol,
- crate id: hir::HirId,
- crate vis: &'hir hir::Visibility<'hir>,
- crate attrs: &'hir [ast::Attribute],
- crate path: &'hir hir::Path<'hir>,
- crate glob: bool,
- crate span: Span,
-}
-
crate fn struct_type_from_def(vdata: &hir::VariantData<'_>) -> StructType {
match *vdata {
hir::VariantData::Struct(..) => Plain,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 708d771..2809840 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -19,7 +19,7 @@
builtin::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS},
Lint,
};
-use rustc_span::hygiene::MacroKind;
+use rustc_span::hygiene::{MacroKind, SyntaxContext};
use rustc_span::symbol::Ident;
use rustc_span::symbol::Symbol;
use rustc_span::DUMMY_SP;
@@ -770,7 +770,12 @@
let mut cache = cx.module_trait_cache.borrow_mut();
let in_scope_traits = cache.entry(module).or_insert_with(|| {
cx.enter_resolver(|resolver| {
- resolver.traits_in_scope(module).into_iter().map(|candidate| candidate.def_id).collect()
+ let parent_scope = &ParentScope::module(resolver.get_module(module), resolver);
+ resolver
+ .traits_in_scope(None, parent_scope, SyntaxContext::root(), None)
+ .into_iter()
+ .map(|candidate| candidate.def_id)
+ .collect()
})
});
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f701352..7d161ca 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -316,15 +316,7 @@
}
}
- om.imports.push(Import {
- name,
- id: item.hir_id,
- vis: &item.vis,
- attrs: &item.attrs,
- path,
- glob: is_glob,
- span: item.span,
- });
+ om.items.push((item, renamed))
}
hir::ItemKind::Mod(ref m) => {
om.mods.push(self.visit_mod_contents(
diff --git a/src/test/codegen/intrinsics/move-val-init.rs b/src/test/codegen/intrinsics/move-val-init.rs
deleted file mode 100644
index 6222536..0000000
--- a/src/test/codegen/intrinsics/move-val-init.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![feature(core_intrinsics)]
-#![crate_type = "lib"]
-
-// test that `move_val_init` actually avoids big allocas
-
-use std::intrinsics::move_val_init;
-
-pub struct Big {
- pub data: [u8; 65536]
-}
-
-// CHECK-LABEL: @test_mvi
-#[no_mangle]
-pub unsafe fn test_mvi(target: *mut Big, make_big: fn() -> Big) {
- // CHECK: call void %make_big(%Big*{{[^%]*}} %target)
- move_val_init(target, make_big());
-}
diff --git a/src/test/codegen/slice-as_chunks.rs b/src/test/codegen/slice-as_chunks.rs
new file mode 100644
index 0000000..48e3f73
--- /dev/null
+++ b/src/test/codegen/slice-as_chunks.rs
@@ -0,0 +1,33 @@
+// no-system-llvm
+// compile-flags: -O
+// only-64bit (because the LLVM type of i64 for usize shows up)
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(slice_as_chunks)]
+
+// CHECK-LABEL: @chunks4
+#[no_mangle]
+pub fn chunks4(x: &[u8]) -> &[[u8; 4]] {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: lshr i64 %x.1, 2
+ // CHECK-NOT: shl
+ // CHECK-NOT: mul
+ // CHECK-NOT: udiv
+ // CHECK-NOT: urem
+ // CHECK: ret
+ x.as_chunks().0
+}
+
+// CHECK-LABEL: @chunks4_with_remainder
+#[no_mangle]
+pub fn chunks4_with_remainder(x: &[u8]) -> (&[[u8; 4]], &[u8]) {
+ // CHECK: and i64 %x.1, -4
+ // CHECK: and i64 %x.1, 3
+ // CHECK: lshr exact
+ // CHECK-NOT: mul
+ // CHECK-NOT: udiv
+ // CHECK-NOT: urem
+ // CHECK: ret
+ x.as_chunks()
+}
diff --git a/src/test/rustdoc-json/compare.py b/src/test/rustdoc-json/compare.py
index b0c5b16..6a92126 100644
--- a/src/test/rustdoc-json/compare.py
+++ b/src/test/rustdoc-json/compare.py
@@ -7,6 +7,9 @@
# and then create `yourtest.expected` by stripping unnecessary details from `yourtest.json`. If
# you're on windows, replace `\` with `/`.
+# WARNING: The error messages produced by this may be misleading, in the case of list re-ordering
+# it may point to apparently unrelated keys.
+
import copy
import sys
import json
diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected
index 65bb0c5..80070e7 100644
--- a/src/test/rustdoc-json/nested.expected
+++ b/src/test/rustdoc-json/nested.expected
@@ -41,8 +41,8 @@
"inner": {
"is_crate": false,
"items": [
- "0:7",
- "0:4"
+ "0:4",
+ "0:7"
]
},
"kind": "module",
diff --git a/src/test/rustdoc-ui/issue-80992.rs b/src/test/rustdoc-ui/issue-80992.rs
new file mode 100644
index 0000000..8983439
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+pub fn test() -> Result<(), ()> {
+ //! ```compile_fail
+ //! fn test() -> Result< {}
+ //! ```
+ Ok(())
+}
diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout
new file mode 100644
index 0000000..1dd19f4
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-80992.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/issue-80992.rs - test (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/issues/issue-28676.rs b/src/test/ui/abi/issue-28676.rs
similarity index 100%
rename from src/test/ui/issues/issue-28676.rs
rename to src/test/ui/abi/issue-28676.rs
diff --git a/src/test/ui/issues/issue-15730.rs b/src/test/ui/array-slice-vec/issue-15730.rs
similarity index 100%
rename from src/test/ui/issues/issue-15730.rs
rename to src/test/ui/array-slice-vec/issue-15730.rs
diff --git a/src/test/ui/associated-item/associated-item-two-bounds.rs b/src/test/ui/associated-item/associated-item-two-bounds.rs
new file mode 100644
index 0000000..25b0d5a
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-two-bounds.rs
@@ -0,0 +1,16 @@
+// This test is a regression test for #34792
+
+// check-pass
+
+pub struct A;
+pub struct B;
+
+pub trait Foo {
+ type T: PartialEq<A> + PartialEq<B>;
+}
+
+pub fn generic<F: Foo>(t: F::T, a: A, b: B) -> bool {
+ t == a && t == b
+}
+
+pub fn main() {}
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/associated-types/issue-24338.rs
similarity index 100%
rename from src/test/ui/issues/issue-24338.rs
rename to src/test/ui/associated-types/issue-24338.rs
diff --git a/src/test/ui/issues/issue-48551.rs b/src/test/ui/associated-types/issue-48551.rs
similarity index 100%
rename from src/test/ui/issues/issue-48551.rs
rename to src/test/ui/associated-types/issue-48551.rs
diff --git a/src/test/ui/issues/issue-50301.rs b/src/test/ui/associated-types/issue-50301.rs
similarity index 100%
rename from src/test/ui/issues/issue-50301.rs
rename to src/test/ui/associated-types/issue-50301.rs
diff --git a/src/test/ui/object-method-numbering.rs b/src/test/ui/associated-types/object-method-numbering.rs
similarity index 100%
rename from src/test/ui/object-method-numbering.rs
rename to src/test/ui/associated-types/object-method-numbering.rs
diff --git a/src/test/ui/issues/issue-76547.nll.stderr b/src/test/ui/async-await/issue-76547.nll.stderr
similarity index 100%
rename from src/test/ui/issues/issue-76547.nll.stderr
rename to src/test/ui/async-await/issue-76547.nll.stderr
diff --git a/src/test/ui/issues/issue-76547.rs b/src/test/ui/async-await/issue-76547.rs
similarity index 100%
rename from src/test/ui/issues/issue-76547.rs
rename to src/test/ui/async-await/issue-76547.rs
diff --git a/src/test/ui/issues/issue-76547.stderr b/src/test/ui/async-await/issue-76547.stderr
similarity index 100%
rename from src/test/ui/issues/issue-76547.stderr
rename to src/test/ui/async-await/issue-76547.stderr
diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.rs b/src/test/ui/async-await/issues/issue-78938-async-block.rs
new file mode 100644
index 0000000..36f7160
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-78938-async-block.rs
@@ -0,0 +1,33 @@
+// edition:2018
+
+use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}};
+
+async fn f() {
+ let room_ref = Arc::new(Vec::new());
+
+ let gameloop_handle = spawn(async { //~ ERROR E0373
+ game_loop(Arc::clone(&room_ref))
+ });
+ gameloop_handle.await;
+}
+
+fn game_loop(v: Arc<Vec<usize>>) {}
+
+fn spawn<F>(future: F) -> JoinHandle
+where
+ F: Future + Send + 'static,
+ F::Output: Send + 'static,
+{
+ loop {}
+}
+
+struct JoinHandle;
+
+impl Future for JoinHandle {
+ type Output = ();
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ loop {}
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-78938-async-block.stderr b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
new file mode 100644
index 0000000..01ffc48
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-78938-async-block.stderr
@@ -0,0 +1,21 @@
+error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
+ --> $DIR/issue-78938-async-block.rs:8:39
+ |
+LL | let gameloop_handle = spawn(async {
+ | _______________________________________^
+LL | | game_loop(Arc::clone(&room_ref))
+ | | -------- `room_ref` is borrowed here
+LL | | });
+ | |_____^ may outlive borrowed value `room_ref`
+ |
+ = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use
+help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword
+ |
+LL | let gameloop_handle = spawn(async move {
+LL | game_loop(Arc::clone(&room_ref))
+LL | });
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/autoref-autoderef/issue-38940.rs
similarity index 100%
rename from src/test/ui/issues/issue-38940.rs
rename to src/test/ui/autoref-autoderef/issue-38940.rs
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr
similarity index 100%
rename from src/test/ui/issues/issue-38940.stderr
rename to src/test/ui/autoref-autoderef/issue-38940.stderr
diff --git a/src/test/ui/issues/issue-25916.rs b/src/test/ui/binop/issue-25916.rs
similarity index 100%
rename from src/test/ui/issues/issue-25916.rs
rename to src/test/ui/binop/issue-25916.rs
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/binop/issue-28837.rs
similarity index 100%
rename from src/test/ui/issues/issue-28837.rs
rename to src/test/ui/binop/issue-28837.rs
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28837.stderr
rename to src/test/ui/binop/issue-28837.stderr
diff --git a/src/test/ui/issues/issue-17263.rs b/src/test/ui/borrowck/issue-17263.rs
similarity index 100%
rename from src/test/ui/issues/issue-17263.rs
rename to src/test/ui/borrowck/issue-17263.rs
diff --git a/src/test/ui/issues/issue-17545.rs b/src/test/ui/borrowck/issue-17545.rs
similarity index 100%
rename from src/test/ui/issues/issue-17545.rs
rename to src/test/ui/borrowck/issue-17545.rs
diff --git a/src/test/ui/issues/issue-17545.stderr b/src/test/ui/borrowck/issue-17545.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17545.stderr
rename to src/test/ui/borrowck/issue-17545.stderr
diff --git a/src/test/ui/issues/issue-20801.rs b/src/test/ui/borrowck/issue-20801.rs
similarity index 100%
rename from src/test/ui/issues/issue-20801.rs
rename to src/test/ui/borrowck/issue-20801.rs
diff --git a/src/test/ui/issues/issue-20801.stderr b/src/test/ui/borrowck/issue-20801.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20801.stderr
rename to src/test/ui/borrowck/issue-20801.stderr
diff --git a/src/test/ui/issues/issue-24267-flow-exit.rs b/src/test/ui/borrowck/issue-24267-flow-exit.rs
similarity index 100%
rename from src/test/ui/issues/issue-24267-flow-exit.rs
rename to src/test/ui/borrowck/issue-24267-flow-exit.rs
diff --git a/src/test/ui/issues/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
similarity index 100%
rename from src/test/ui/issues/issue-24267-flow-exit.stderr
rename to src/test/ui/borrowck/issue-24267-flow-exit.stderr
diff --git a/src/test/ui/issues/issue-25793.rs b/src/test/ui/borrowck/issue-25793.rs
similarity index 100%
rename from src/test/ui/issues/issue-25793.rs
rename to src/test/ui/borrowck/issue-25793.rs
diff --git a/src/test/ui/issues/issue-25793.stderr b/src/test/ui/borrowck/issue-25793.stderr
similarity index 100%
rename from src/test/ui/issues/issue-25793.stderr
rename to src/test/ui/borrowck/issue-25793.stderr
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs b/src/test/ui/borrowck/issue-27282-move-match-input-into-guard.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-move-match-input-into-guard.rs
rename to src/test/ui/borrowck/issue-27282-move-match-input-into-guard.rs
diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/borrowck/issue-27282-move-match-input-into-guard.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr
rename to src/test/ui/borrowck/issue-27282-move-match-input-into-guard.stderr
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.rs
rename to src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.rs
diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-mutate-before-diverging-arm-2.stderr
rename to src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.rs
similarity index 100%
rename from src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs
rename to src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.rs
diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr
similarity index 100%
rename from src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.stderr
rename to src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr
diff --git a/src/test/ui/issues/issue-45199.rs b/src/test/ui/borrowck/issue-45199.rs
similarity index 100%
rename from src/test/ui/issues/issue-45199.rs
rename to src/test/ui/borrowck/issue-45199.rs
diff --git a/src/test/ui/issues/issue-45199.stderr b/src/test/ui/borrowck/issue-45199.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45199.stderr
rename to src/test/ui/borrowck/issue-45199.stderr
diff --git a/src/test/ui/issues/issue-46471.rs b/src/test/ui/borrowck/issue-46471.rs
similarity index 100%
rename from src/test/ui/issues/issue-46471.rs
rename to src/test/ui/borrowck/issue-46471.rs
diff --git a/src/test/ui/issues/issue-46471.stderr b/src/test/ui/borrowck/issue-46471.stderr
similarity index 100%
rename from src/test/ui/issues/issue-46471.stderr
rename to src/test/ui/borrowck/issue-46471.stderr
diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs
new file mode 100644
index 0000000..4b42f9d
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs
@@ -0,0 +1,10 @@
+// Regression test for #80913.
+
+fn main() {
+ let mut x = 42_i32;
+ let mut opt = Some(&mut x);
+ for _ in 0..5 {
+ if let Some(mut _x) = opt {}
+ //~^ ERROR: use of moved value
+ }
+}
diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
new file mode 100644
index 0000000..9373e4d
--- /dev/null
+++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value
+ --> $DIR/move-in-pattern-mut-in-loop.rs:7:21
+ |
+LL | if let Some(mut _x) = opt {}
+ | ^^^^^^ value moved here, in previous iteration of loop
+ |
+ = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait
+help: borrow this field in the pattern to avoid moving `opt.0`
+ |
+LL | if let Some(ref mut _x) = opt {}
+ | ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs
new file mode 100644
index 0000000..2916d8c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs
@@ -0,0 +1,31 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+
+enum MultiVariant {
+ Point(i32, i32),
+ Meta(i32)
+}
+
+fn main() {
+ let mut point = MultiVariant::Point(10, -10,);
+
+ let mut meta = MultiVariant::Meta(1);
+
+ let c = || {
+ if let MultiVariant::Point(ref mut x, _) = point {
+ *x += 1;
+ }
+
+ if let MultiVariant::Meta(ref mut v) = meta {
+ *v += 1;
+ }
+ };
+
+ let a = c;
+ let b = c; //~ ERROR use of moved value: `c` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
new file mode 100644
index 0000000..de0bfe3
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12
+ |
+LL | #![feature(capture_disjoint_fields)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `c`
+ --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13
+ |
+LL | let a = c;
+ | - value moved here
+LL | let b = c;
+ | ^ value used here after move
+ |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
+ --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52
+ |
+LL | if let MultiVariant::Point(ref mut x, _) = point {
+ | ^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs
new file mode 100644
index 0000000..8486f03
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs
@@ -0,0 +1,26 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+enum SingleVariant {
+ Point(i32, i32),
+}
+
+fn main() {
+ let mut point = SingleVariant::Point(10, -10);
+
+ let c = || {
+ // FIXME(project-rfc-2229#24): Change this to be a destructure pattern
+ // once this is fixed, to remove the warning.
+ if let SingleVariant::Point(ref mut x, _) = point {
+ //~^ WARNING: irrefutable if-let pattern
+ *x += 1;
+ }
+ };
+
+ let b = c;
+ let a = c; //~ ERROR use of moved value: `c` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
new file mode 100644
index 0000000..ad66f6d
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
@@ -0,0 +1,37 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12
+ |
+LL | #![feature(capture_disjoint_fields)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+warning: irrefutable if-let pattern
+ --> $DIR/closure-origin-single-variant-diagnostics.rs:18:9
+ |
+LL | / if let SingleVariant::Point(ref mut x, _) = point {
+LL | |
+LL | | *x += 1;
+LL | | }
+ | |_________^
+ |
+ = note: `#[warn(irrefutable_let_patterns)]` on by default
+
+error[E0382]: use of moved value: `c`
+ --> $DIR/closure-origin-single-variant-diagnostics.rs:25:13
+ |
+LL | let b = c;
+ | - value moved here
+LL | let a = c;
+ | ^ value used here after move
+ |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment
+ --> $DIR/closure-origin-single-variant-diagnostics.rs:18:53
+ |
+LL | if let SingleVariant::Point(ref mut x, _) = point {
+ | ^^^^^
+
+error: aborting due to previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs
new file mode 100644
index 0000000..103890f
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs
@@ -0,0 +1,25 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+struct Y {
+ y: X
+}
+
+struct X {
+ a: u32,
+ b: u32,
+}
+
+fn main() {
+ let mut x = Y { y: X { a: 5, b: 0 } };
+ let hello = || {
+ x.y.a += 1;
+ };
+
+ let b = hello;
+ let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
new file mode 100644
index 0000000..474d77b
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closure-origin-struct-diagnostics.rs:1:12
+ |
+LL | #![feature(capture_disjoint_fields)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `hello`
+ --> $DIR/closure-origin-struct-diagnostics.rs:24:13
+ |
+LL | let b = hello;
+ | ----- value moved here
+LL | let c = hello;
+ | ^^^^^ value used here after move
+ |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment
+ --> $DIR/closure-origin-struct-diagnostics.rs:20:9
+ |
+LL | x.y.a += 1;
+ | ^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs
new file mode 100644
index 0000000..6b078d2
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs
@@ -0,0 +1,16 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+
+// Check that precise paths are being reported back in the error message.
+
+fn main() {
+ let mut x = (5, 0);
+ let hello = || {
+ x.0 += 1;
+ };
+
+ let b = hello;
+ let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
new file mode 100644
index 0000000..716728e
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
@@ -0,0 +1,26 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12
+ |
+LL | #![feature(capture_disjoint_fields)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0382]: use of moved value: `hello`
+ --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13
+ |
+LL | let b = hello;
+ | ----- value moved here
+LL | let c = hello;
+ | ^^^^^ value used here after move
+ |
+note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment
+ --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9
+ |
+LL | x.0 += 1;
+ | ^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs
new file mode 100644
index 0000000..0638db6
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs
@@ -0,0 +1,15 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
+//~| `#[warn(incomplete_features)]` on by default
+//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
+struct S(String, String);
+
+fn expect_fn<F: Fn()>(_f: F) {}
+
+fn main() {
+ let s = S(format!("s"), format!("s"));
+ let c = || { //~ ERROR expected a closure that implements the `Fn`
+ let s = s.1;
+ };
+ expect_fn(c);
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
new file mode 100644
index 0000000..77eb2a9
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
@@ -0,0 +1,23 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closure-origin-tuple-diagnostics.rs:1:12
+ |
+LL | #![feature(capture_disjoint_fields)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+ --> $DIR/closure-origin-tuple-diagnostics.rs:11:13
+ |
+LL | let c = || {
+ | ^^ this closure implements `FnOnce`, not `Fn`
+LL | let s = s.1;
+ | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment
+LL | };
+LL | expect_fn(c);
+ | --------- the requirement to implement `Fn` derives from here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0525`.
diff --git a/src/test/ui/command/command-current-dir.rs b/src/test/ui/command/command-current-dir.rs
new file mode 100644
index 0000000..91d8e4f
--- /dev/null
+++ b/src/test/ui/command/command-current-dir.rs
@@ -0,0 +1,49 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::Command;
+
+fn main() {
+ // Checks the behavior of current_dir when used with a relative exe path.
+ let me = env::current_exe().unwrap();
+ if matches!(env::args().skip(1).next().as_deref(), Some("current-dir")) {
+ let cwd = env::current_dir().unwrap();
+ assert_eq!(cwd.file_name().unwrap(), "bar");
+ std::process::exit(0);
+ }
+ let exe = me.file_name().unwrap();
+ let cwd = me.parent().unwrap();
+ eprintln!("cwd={:?}", cwd);
+ // Change directory to where the exectuable is located, since this test
+ // fundamentally needs to use relative paths. In some cases (like
+ // remote-test-server), the current_dir can be somewhere else, so make
+ // sure it is something we can use. We assume we can write to this
+ // directory.
+ env::set_current_dir(&cwd).unwrap();
+ let foo = cwd.join("foo");
+ let bar = cwd.join("bar");
+ fs::create_dir_all(&foo).unwrap();
+ fs::create_dir_all(&bar).unwrap();
+ fs::copy(&me, foo.join(exe)).unwrap();
+
+ // Unfortunately this is inconsistent based on the platform, see
+ // https://github.com/rust-lang/rust/issues/37868. On Windows,
+ // it is relative *before* changing the directory, and on Unix
+ // it is *after* changing the directory.
+ let relative_exe = if cfg!(windows) {
+ Path::new("foo").join(exe)
+ } else {
+ Path::new("../foo").join(exe)
+ };
+
+ let status = Command::new(relative_exe)
+ .arg("current-dir")
+ .current_dir("bar")
+ .status()
+ .unwrap();
+ assert!(status.success());
+}
diff --git a/src/test/ui/issues/issue-73899.rs b/src/test/ui/const-generics/issue-73899.rs
similarity index 100%
rename from src/test/ui/issues/issue-73899.rs
rename to src/test/ui/const-generics/issue-73899.rs
diff --git a/src/test/ui/issues/issue-75763.rs b/src/test/ui/const-generics/issue-75763.rs
similarity index 100%
rename from src/test/ui/issues/issue-75763.rs
rename to src/test/ui/const-generics/issue-75763.rs
diff --git a/src/test/ui/const-generics/late-bound-vars/in_closure.rs b/src/test/ui/const-generics/late-bound-vars/in_closure.rs
new file mode 100644
index 0000000..0aaeaff
--- /dev/null
+++ b/src/test/ui/const-generics/late-bound-vars/in_closure.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+const fn inner<'a>() -> usize where &'a (): Sized {
+ 3
+}
+
+fn test<'a>() {
+ let _ = || {
+ let _: [u8; inner::<'a>()];
+ let _ = [0; inner::<'a>()];
+ };
+}
+
+fn main() {
+ test();
+}
diff --git a/src/test/ui/const-generics/late-bound-vars/simple.rs b/src/test/ui/const-generics/late-bound-vars/simple.rs
new file mode 100644
index 0000000..2c411a3
--- /dev/null
+++ b/src/test/ui/const-generics/late-bound-vars/simple.rs
@@ -0,0 +1,16 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+const fn inner<'a>() -> usize where &'a (): Sized {
+ 3
+}
+
+fn test<'a>() {
+ let _: [u8; inner::<'a>()];
+ let _ = [0; inner::<'a>()];
+}
+
+fn main() {
+ test();
+}
diff --git a/src/test/ui/check_const-feature-gated.rs b/src/test/ui/consts/check_const-feature-gated.rs
similarity index 100%
rename from src/test/ui/check_const-feature-gated.rs
rename to src/test/ui/consts/check_const-feature-gated.rs
diff --git a/src/test/ui/const-suggest-feature.rs b/src/test/ui/consts/const-suggest-feature.rs
similarity index 100%
rename from src/test/ui/const-suggest-feature.rs
rename to src/test/ui/consts/const-suggest-feature.rs
diff --git a/src/test/ui/const-suggest-feature.stderr b/src/test/ui/consts/const-suggest-feature.stderr
similarity index 100%
rename from src/test/ui/const-suggest-feature.stderr
rename to src/test/ui/consts/const-suggest-feature.stderr
diff --git a/src/test/ui/issues/issue-17718-borrow-interior.rs b/src/test/ui/consts/issue-17718-borrow-interior.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-borrow-interior.rs
rename to src/test/ui/consts/issue-17718-borrow-interior.rs
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/consts/issue-17718-const-bad-values.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-bad-values.rs
rename to src/test/ui/consts/issue-17718-const-bad-values.rs
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/consts/issue-17718-const-bad-values.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-bad-values.stderr
rename to src/test/ui/consts/issue-17718-const-bad-values.stderr
diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/consts/issue-17718-const-borrow.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-borrow.rs
rename to src/test/ui/consts/issue-17718-const-borrow.rs
diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/consts/issue-17718-const-borrow.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-borrow.stderr
rename to src/test/ui/consts/issue-17718-const-borrow.stderr
diff --git a/src/test/ui/issues/issue-21562.rs b/src/test/ui/consts/issue-21562.rs
similarity index 100%
rename from src/test/ui/issues/issue-21562.rs
rename to src/test/ui/consts/issue-21562.rs
diff --git a/src/test/ui/issues/issue-21721.rs b/src/test/ui/consts/issue-21721.rs
similarity index 100%
rename from src/test/ui/issues/issue-21721.rs
rename to src/test/ui/consts/issue-21721.rs
diff --git a/src/test/ui/issues/issue-27890.rs b/src/test/ui/consts/issue-27890.rs
similarity index 100%
rename from src/test/ui/issues/issue-27890.rs
rename to src/test/ui/consts/issue-27890.rs
diff --git a/src/test/ui/issues/issue-28113.rs b/src/test/ui/consts/issue-28113.rs
similarity index 100%
rename from src/test/ui/issues/issue-28113.rs
rename to src/test/ui/consts/issue-28113.rs
diff --git a/src/test/ui/issues/issue-28113.stderr b/src/test/ui/consts/issue-28113.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28113.stderr
rename to src/test/ui/consts/issue-28113.stderr
diff --git a/src/test/ui/issues/issue-29914-2.rs b/src/test/ui/consts/issue-29914-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914-2.rs
rename to src/test/ui/consts/issue-29914-2.rs
diff --git a/src/test/ui/issues/issue-29914-3.rs b/src/test/ui/consts/issue-29914-3.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914-3.rs
rename to src/test/ui/consts/issue-29914-3.rs
diff --git a/src/test/ui/issues/issue-29914.rs b/src/test/ui/consts/issue-29914.rs
similarity index 100%
rename from src/test/ui/issues/issue-29914.rs
rename to src/test/ui/consts/issue-29914.rs
diff --git a/src/test/ui/issues/issue-29927-1.rs b/src/test/ui/consts/issue-29927-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-29927-1.rs
rename to src/test/ui/consts/issue-29927-1.rs
diff --git a/src/test/ui/issues/issue-29927.rs b/src/test/ui/consts/issue-29927.rs
similarity index 100%
rename from src/test/ui/issues/issue-29927.rs
rename to src/test/ui/consts/issue-29927.rs
diff --git a/src/test/ui/issues/issue-32829-2.rs b/src/test/ui/consts/issue-32829-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-32829-2.rs
rename to src/test/ui/consts/issue-32829-2.rs
diff --git a/src/test/ui/issues/issue-32829-2.stderr b/src/test/ui/consts/issue-32829-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-32829-2.stderr
rename to src/test/ui/consts/issue-32829-2.stderr
diff --git a/src/test/ui/issues/issue-36163.rs b/src/test/ui/consts/issue-36163.rs
similarity index 100%
rename from src/test/ui/issues/issue-36163.rs
rename to src/test/ui/consts/issue-36163.rs
diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr
similarity index 100%
rename from src/test/ui/issues/issue-36163.stderr
rename to src/test/ui/consts/issue-36163.stderr
diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/consts/issue-43105.rs
similarity index 100%
rename from src/test/ui/issues/issue-43105.rs
rename to src/test/ui/consts/issue-43105.rs
diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/consts/issue-43105.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43105.stderr
rename to src/test/ui/consts/issue-43105.stderr
diff --git a/src/test/ui/issues/issue-47789.rs b/src/test/ui/consts/issue-47789.rs
similarity index 100%
rename from src/test/ui/issues/issue-47789.rs
rename to src/test/ui/consts/issue-47789.rs
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs b/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
similarity index 100%
rename from src/test/ui/issues/issue-52023-array-size-pointer-cast.rs
rename to src/test/ui/consts/issue-52023-array-size-pointer-cast.rs
diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
similarity index 100%
rename from src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr
rename to src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr
diff --git a/src/test/ui/issues/issue-58435-ice-with-assoc-const.rs b/src/test/ui/consts/issue-58435-ice-with-assoc-const.rs
similarity index 100%
rename from src/test/ui/issues/issue-58435-ice-with-assoc-const.rs
rename to src/test/ui/consts/issue-58435-ice-with-assoc-const.rs
diff --git a/src/test/ui/issues/issue-6991.rs b/src/test/ui/consts/issue-6991.rs
similarity index 100%
rename from src/test/ui/issues/issue-6991.rs
rename to src/test/ui/consts/issue-6991.rs
diff --git a/src/test/ui/rustc-args-required-const.rs b/src/test/ui/consts/rustc-args-required-const.rs
similarity index 100%
rename from src/test/ui/rustc-args-required-const.rs
rename to src/test/ui/consts/rustc-args-required-const.rs
diff --git a/src/test/ui/rustc-args-required-const.stderr b/src/test/ui/consts/rustc-args-required-const.stderr
similarity index 100%
rename from src/test/ui/rustc-args-required-const.stderr
rename to src/test/ui/consts/rustc-args-required-const.stderr
diff --git a/src/test/ui/issues/issue-30018-nopanic.rs b/src/test/ui/drop/issue-30018-nopanic.rs
similarity index 100%
rename from src/test/ui/issues/issue-30018-nopanic.rs
rename to src/test/ui/drop/issue-30018-nopanic.rs
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs b/src/test/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs
similarity index 100%
rename from src/test/ui/issues/issue-28498-ugeh-with-lifetime-param.rs
rename to src/test/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs b/src/test/ui/dropck/issue-28498-ugeh-with-trait-bound.rs
similarity index 100%
rename from src/test/ui/issues/issue-28498-ugeh-with-trait-bound.rs
rename to src/test/ui/dropck/issue-28498-ugeh-with-trait-bound.rs
diff --git a/src/test/ui/issues/issue-29844.rs b/src/test/ui/dropck/issue-29844.rs
similarity index 100%
rename from src/test/ui/issues/issue-29844.rs
rename to src/test/ui/dropck/issue-29844.rs
diff --git a/src/test/ui/issues/issue-43398.rs b/src/test/ui/enum-discriminant/issue-43398.rs
similarity index 100%
rename from src/test/ui/issues/issue-43398.rs
rename to src/test/ui/enum-discriminant/issue-43398.rs
diff --git a/src/test/ui/issues/issue-43398.stderr b/src/test/ui/enum-discriminant/issue-43398.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43398.stderr
rename to src/test/ui/enum-discriminant/issue-43398.stderr
diff --git a/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs
similarity index 100%
rename from src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs
rename to src/test/ui/feature-gates/feature-gate-const_refs_to_cell.rs
diff --git a/src/test/ui/feature-gate-edition_macro_pats.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs
similarity index 100%
rename from src/test/ui/feature-gate-edition_macro_pats.rs
rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.rs
diff --git a/src/test/ui/feature-gate-edition_macro_pats.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr
similarity index 100%
rename from src/test/ui/feature-gate-edition_macro_pats.stderr
rename to src/test/ui/feature-gates/feature-gate-edition_macro_pats.stderr
diff --git a/src/test/ui/trace_macros-gate.rs b/src/test/ui/feature-gates/trace_macros-gate.rs
similarity index 100%
rename from src/test/ui/trace_macros-gate.rs
rename to src/test/ui/feature-gates/trace_macros-gate.rs
diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/feature-gates/trace_macros-gate.stderr
similarity index 100%
rename from src/test/ui/trace_macros-gate.stderr
rename to src/test/ui/feature-gates/trace_macros-gate.stderr
diff --git a/src/test/ui/issues/issue-2936.rs b/src/test/ui/generics/issue-2936.rs
similarity index 100%
rename from src/test/ui/issues/issue-2936.rs
rename to src/test/ui/generics/issue-2936.rs
diff --git a/src/test/ui/hygiene/traits-in-scope.rs b/src/test/ui/hygiene/traits-in-scope.rs
new file mode 100644
index 0000000..548bb22
--- /dev/null
+++ b/src/test/ui/hygiene/traits-in-scope.rs
@@ -0,0 +1,53 @@
+// Macros with def-site hygiene still bring traits into scope.
+// It is not clear whether this is desirable behavior or not.
+// It is also not clear how to prevent it if it is not desirable.
+
+// check-pass
+
+#![feature(decl_macro)]
+#![feature(trait_alias)]
+
+mod traits {
+ pub trait Trait1 {
+ fn simple_import(&self) {}
+ }
+ pub trait Trait2 {
+ fn renamed_import(&self) {}
+ }
+ pub trait Trait3 {
+ fn underscore_import(&self) {}
+ }
+ pub trait Trait4 {
+ fn trait_alias(&self) {}
+ }
+
+ impl Trait1 for () {}
+ impl Trait2 for () {}
+ impl Trait3 for () {}
+ impl Trait4 for () {}
+}
+
+macro m1() {
+ use traits::Trait1;
+}
+macro m2() {
+ use traits::Trait2 as Alias;
+}
+macro m3() {
+ use traits::Trait3 as _;
+}
+macro m4() {
+ trait Alias = traits::Trait4;
+}
+
+fn main() {
+ m1!();
+ m2!();
+ m3!();
+ m4!();
+
+ ().simple_import();
+ ().renamed_import();
+ ().underscore_import();
+ ().trait_alias();
+}
diff --git a/src/test/ui/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
similarity index 100%
rename from src/test/ui/nested_impl_trait.rs
rename to src/test/ui/impl-trait/nested_impl_trait.rs
diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
similarity index 100%
rename from src/test/ui/nested_impl_trait.stderr
rename to src/test/ui/impl-trait/nested_impl_trait.stderr
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
similarity index 100%
rename from src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
rename to src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
similarity index 100%
rename from src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
rename to src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
diff --git a/src/test/ui/issues/issue-26873-onefile.rs b/src/test/ui/imports/issue-26873-onefile.rs
similarity index 100%
rename from src/test/ui/issues/issue-26873-onefile.rs
rename to src/test/ui/imports/issue-26873-onefile.rs
diff --git a/src/test/ui/issues/issue-32119.rs b/src/test/ui/imports/issue-32119.rs
similarity index 100%
rename from src/test/ui/issues/issue-32119.rs
rename to src/test/ui/imports/issue-32119.rs
diff --git a/src/test/ui/issues/issue-32222.rs b/src/test/ui/imports/issue-32222.rs
similarity index 100%
rename from src/test/ui/issues/issue-32222.rs
rename to src/test/ui/imports/issue-32222.rs
diff --git a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
deleted file mode 100644
index 9804c42..0000000
--- a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-// run-pass
-#![allow(unused_braces)]
-#![allow(unused_unsafe)]
-#![allow(unreachable_code)]
-// ignore-emscripten no threads support
-#![allow(stable_features)]
-
-// This test is checking that the move_val_init intrinsic is
-// respecting cleanups for both of its argument expressions.
-//
-// In other words, if either DEST or SOURCE in
-//
-// `intrinsics::move_val_init(DEST, SOURCE)
-//
-// introduce temporaries that require cleanup, and SOURCE panics, then
-// make sure the cleanups still occur.
-
-#![feature(core_intrinsics, sync_poison)]
-
-use std::cell::RefCell;
-use std::intrinsics;
-use std::sync::{Arc, LockResult, Mutex, MutexGuard};
-use std::thread;
-
-type LogEntry = (&'static str, i32);
-type Guarded = RefCell<Vec<LogEntry>>;
-#[derive(Clone)]
-struct Log(Arc<Mutex<Guarded>>);
-struct Acquired<'a>(MutexGuard<'a, Guarded>);
-type LogState = (MutexWas, &'static [LogEntry]);
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum MutexWas { Poisoned, NotPoisoned }
-
-impl Log {
- fn lock(&self) -> LockResult<MutexGuard<RefCell<Vec<LogEntry>>>> { self.0.lock() }
- fn acquire(&self) -> Acquired { Acquired(self.0.lock().unwrap()) }
-}
-
-impl<'a> Acquired<'a> {
- fn log(&self, s: &'static str, i: i32) { self.0.borrow_mut().push((s, i)); }
-}
-
-const TEST1_EXPECT: LogState = (MutexWas::NotPoisoned,
- &[("double-check non-poisoning path", 1)
- ]);
-
-fn test1(log: Log) {
- {
- let acq = log.acquire();
- acq.log("double-check non-poisoning path", 1);
- }
- panic!("every test ends in a panic");
-}
-
-const TEST2_EXPECT: LogState = (MutexWas::Poisoned,
- &[("double-check poisoning path", 1),
- ("and multiple log entries", 2),
- ]);
-fn test2(log: Log) {
- let acq = log.acquire();
- acq.log("double-check poisoning path", 1);
- acq.log("and multiple log entries", 2);
- panic!("every test ends in a panic");
-}
-
-struct LogOnDrop<'a>(&'a Acquired<'a>, &'static str, i32);
-impl<'a> Drop for LogOnDrop<'a> {
- fn drop(&mut self) {
- self.0.log(self.1, self.2);
- }
-}
-
-const TEST3_EXPECT: LogState = (MutexWas::Poisoned,
- &[("double-check destructors can log", 1),
- ("drop d2", 2),
- ("drop d1", 3),
- ]);
-fn test3(log: Log) {
- let acq = log.acquire();
- acq.log("double-check destructors can log", 1);
- let _d1 = LogOnDrop(&acq, "drop d1", 3);
- let _d2 = LogOnDrop(&acq, "drop d2", 2);
- panic!("every test ends in a panic");
-}
-
-// The *real* tests of panic-handling for move_val_init intrinsic
-// start here.
-
-const TEST4_EXPECT: LogState = (MutexWas::Poisoned,
- &[("neither arg panics", 1),
- ("drop temp LOD", 2),
- ("drop temp LOD", 3),
- ("drop dest_b", 4),
- ("drop dest_a", 5),
- ]);
-fn test4(log: Log) {
- let acq = log.acquire();
- acq.log("neither arg panics", 1);
- let mut dest_a = LogOnDrop(&acq, "a will be overwritten, not dropped", 0);
- let mut dest_b = LogOnDrop(&acq, "b will be overwritten, not dropped", 0);
- unsafe {
- intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
- LogOnDrop(&acq, "drop dest_a", 5));
- intrinsics::move_val_init(&mut dest_b, { LogOnDrop(&acq, "drop temp LOD", 3);
- LogOnDrop(&acq, "drop dest_b", 4) });
- }
- panic!("every test ends in a panic");
-}
-
-
-// Check that move_val_init(PANIC, SOURCE_EXPR) never evaluates SOURCE_EXPR
-const TEST5_EXPECT: LogState = (MutexWas::Poisoned,
- &[("first arg panics", 1),
- ("drop orig dest_a", 2),
- ]);
-fn test5(log: Log) {
- let acq = log.acquire();
- acq.log("first arg panics", 1);
- let mut _dest_a = LogOnDrop(&acq, "drop orig dest_a", 2);
- unsafe {
- intrinsics::move_val_init({ panic!("every test ends in a panic") },
- LogOnDrop(&acq, "we never get here", 0));
- }
-}
-
-// Check that move_val_init(DEST_EXPR, PANIC) cleans up temps from DEST_EXPR.
-const TEST6_EXPECT: LogState = (MutexWas::Poisoned,
- &[("second arg panics", 1),
- ("drop temp LOD", 2),
- ("drop orig dest_a", 3),
- ]);
-fn test6(log: Log) {
- let acq = log.acquire();
- acq.log("second arg panics", 1);
- let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 3);
- unsafe {
- intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
- { panic!("every test ends in a panic"); });
- }
-}
-
-// Check that move_val_init(DEST_EXPR, COMPLEX_PANIC) cleans up temps from COMPLEX_PANIC.
-const TEST7_EXPECT: LogState = (MutexWas::Poisoned,
- &[("second arg panics", 1),
- ("drop temp LOD", 2),
- ("drop temp LOD", 3),
- ("drop orig dest_a", 4),
- ]);
-fn test7(log: Log) {
- let acq = log.acquire();
- acq.log("second arg panics", 1);
- let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 4);
- unsafe {
- intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
- { LogOnDrop(&acq, "drop temp LOD", 3);
- panic!("every test ends in a panic"); });
- }
-}
-
-const TEST_SUITE: &'static [(&'static str, fn (Log), LogState)] =
- &[("test1", test1, TEST1_EXPECT),
- ("test2", test2, TEST2_EXPECT),
- ("test3", test3, TEST3_EXPECT),
- ("test4", test4, TEST4_EXPECT),
- ("test5", test5, TEST5_EXPECT),
- ("test6", test6, TEST6_EXPECT),
- ("test7", test7, TEST7_EXPECT),
- ];
-
-fn main() {
- for &(name, test, expect) in TEST_SUITE {
- let log = Log(Arc::new(Mutex::new(RefCell::new(Vec::new()))));
- let ret = { let log = log.clone(); thread::spawn(move || test(log)).join() };
- assert!(ret.is_err(), "{} must end with panic", name);
- {
- let l = log.lock();
- match l {
- Ok(acq) => {
- assert_eq!((MutexWas::NotPoisoned, &acq.borrow()[..]), expect);
- println!("{} (unpoisoned) log: {:?}", name, *acq);
- }
- Err(e) => {
- let acq = e.into_inner();
- assert_eq!((MutexWas::Poisoned, &acq.borrow()[..]), expect);
- println!("{} (poisoned) log: {:?}", name, *acq);
- }
- }
- }
- }
-}
diff --git a/src/test/ui/intrinsics/intrinsic-move-val.rs b/src/test/ui/intrinsics/intrinsic-move-val.rs
deleted file mode 100644
index b672f1e..0000000
--- a/src/test/ui/intrinsics/intrinsic-move-val.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// run-pass
-
-#![feature(box_syntax)]
-#![feature(intrinsics)]
-
-mod rusti {
- extern "rust-intrinsic" {
- pub fn move_val_init<T>(dst: *mut T, src: T);
- }
-}
-
-pub fn main() {
- unsafe {
- // sanity check
- check_drops_state(0, None);
-
- let mut x: Option<Box<D>> = Some(box D(1));
- assert_eq!(x.as_ref().unwrap().0, 1);
-
- // A normal overwrite, to demonstrate `check_drops_state`.
- x = Some(box D(2));
-
- // At this point, one destructor has run, because the
- // overwrite of `x` drops its initial value.
- check_drops_state(1, Some(1));
-
- let mut y: Option<Box<D>> = std::mem::zeroed();
-
- // An initial binding does not overwrite anything.
- check_drops_state(1, Some(1));
-
- // Since `y` has been initialized via the `init` intrinsic, it
- // would be unsound to directly overwrite its value via normal
- // assignment.
- //
- // The code currently generated by the compiler is overly
- // accepting, however, in that it will check if `y` is itself
- // null and thus avoid the unsound action of attempting to
- // free null. In other words, if we were to do a normal
- // assignment like `y = box D(4);` here, it probably would not
- // crash today. But the plan is that it may well crash in the
- // future, (I believe).
-
- // `x` is moved here; the manner in which this is tracked by the
- // compiler is hidden.
- rusti::move_val_init(&mut y, x);
-
- // But what we *can* observe is how many times the destructor
- // for `D` is invoked, and what the last value we saw was
- // during such a destructor call. We do so after the end of
- // this scope.
-
- assert_eq!(y.as_ref().unwrap().0, 2);
- y.as_mut().unwrap().0 = 3;
- assert_eq!(y.as_ref().unwrap().0, 3);
-
- check_drops_state(1, Some(1));
- }
-
- check_drops_state(2, Some(3));
-}
-
-static mut NUM_DROPS: i32 = 0;
-static mut LAST_DROPPED: Option<i32> = None;
-
-fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
- unsafe {
- assert_eq!(NUM_DROPS, num_drops);
- assert_eq!(LAST_DROPPED, last_dropped);
- }
-}
-
-struct D(i32);
-impl Drop for D {
- fn drop(&mut self) {
- unsafe {
- NUM_DROPS += 1;
- LAST_DROPPED = Some(self.0);
- }
- }
-}
diff --git a/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs b/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs
deleted file mode 100644
index dee7f25..0000000
--- a/src/test/ui/issues/issue-15881-model-lexer-dotdotdot.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// run-pass
-#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
-#![allow(ellipsis_inclusive_range_patterns)]
-
-// regression test for the model lexer handling the DOTDOTDOT syntax (#15877)
-
-
-pub fn main() {
- match 5_usize {
- 1_usize...5_usize => {}
- _ => panic!("should match range"),
- }
- match 5_usize {
- 6_usize...7_usize => panic!("shouldn't match range"),
- _ => {}
- }
- match 5_usize {
- 1_usize => panic!("should match non-first range"),
- 2_usize...6_usize => {}
- _ => panic!("math is broken")
- }
- match 'c' {
- 'a'...'z' => {}
- _ => panic!("should support char ranges")
- }
- match -3_isize {
- -7...5 => {}
- _ => panic!("should match signed range")
- }
- match 3.0f64 {
- 1.0...5.0 => {}
- _ => panic!("should match float range")
- }
- match -1.5f64 {
- -3.6...3.6 => {}
- _ => panic!("should match negative float range")
- }
-}
diff --git a/src/test/ui/expr_attr_paren_order.rs b/src/test/ui/lint/expr_attr_paren_order.rs
similarity index 100%
rename from src/test/ui/expr_attr_paren_order.rs
rename to src/test/ui/lint/expr_attr_paren_order.rs
diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/lint/expr_attr_paren_order.stderr
similarity index 100%
rename from src/test/ui/expr_attr_paren_order.stderr
rename to src/test/ui/lint/expr_attr_paren_order.stderr
diff --git a/src/test/ui/issues/issue-17718-const-naming.rs b/src/test/ui/lint/issue-17718-const-naming.rs
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-naming.rs
rename to src/test/ui/lint/issue-17718-const-naming.rs
diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
similarity index 100%
rename from src/test/ui/issues/issue-17718-const-naming.stderr
rename to src/test/ui/lint/issue-17718-const-naming.stderr
diff --git a/src/test/ui/issues/issue-30302.rs b/src/test/ui/lint/issue-30302.rs
similarity index 100%
rename from src/test/ui/issues/issue-30302.rs
rename to src/test/ui/lint/issue-30302.rs
diff --git a/src/test/ui/issues/issue-30302.stderr b/src/test/ui/lint/issue-30302.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30302.stderr
rename to src/test/ui/lint/issue-30302.stderr
diff --git a/src/test/ui/issues/issue-34798.rs b/src/test/ui/lint/issue-34798.rs
similarity index 100%
rename from src/test/ui/issues/issue-34798.rs
rename to src/test/ui/lint/issue-34798.rs
diff --git a/src/test/ui/trivial_casts.rs b/src/test/ui/lint/trivial_casts.rs
similarity index 100%
rename from src/test/ui/trivial_casts.rs
rename to src/test/ui/lint/trivial_casts.rs
diff --git a/src/test/ui/trivial_casts.stderr b/src/test/ui/lint/trivial_casts.stderr
similarity index 100%
rename from src/test/ui/trivial_casts.stderr
rename to src/test/ui/lint/trivial_casts.stderr
diff --git a/src/test/ui/inline-asm-bad-constraint.rs b/src/test/ui/llvm-asm/inline-asm-bad-constraint.rs
similarity index 100%
rename from src/test/ui/inline-asm-bad-constraint.rs
rename to src/test/ui/llvm-asm/inline-asm-bad-constraint.rs
diff --git a/src/test/ui/inline-asm-bad-constraint.stderr b/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr
similarity index 100%
rename from src/test/ui/inline-asm-bad-constraint.stderr
rename to src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr
diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/llvm-asm/inline-asm-bad-operand.rs
similarity index 100%
rename from src/test/ui/inline-asm-bad-operand.rs
rename to src/test/ui/llvm-asm/inline-asm-bad-operand.rs
diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/llvm-asm/inline-asm-bad-operand.stderr
similarity index 100%
rename from src/test/ui/inline-asm-bad-operand.stderr
rename to src/test/ui/llvm-asm/inline-asm-bad-operand.stderr
diff --git a/src/test/ui/issues/issue-14936.rs b/src/test/ui/llvm-asm/issue-14936.rs
similarity index 100%
rename from src/test/ui/issues/issue-14936.rs
rename to src/test/ui/llvm-asm/issue-14936.rs
diff --git a/src/test/ui/issues/auxiliary/issue-40469.rs b/src/test/ui/macros/auxiliary/issue-40469.rs
similarity index 100%
rename from src/test/ui/issues/auxiliary/issue-40469.rs
rename to src/test/ui/macros/auxiliary/issue-40469.rs
diff --git a/src/test/ui/issues/issue-26322.rs b/src/test/ui/macros/issue-26322.rs
similarity index 100%
rename from src/test/ui/issues/issue-26322.rs
rename to src/test/ui/macros/issue-26322.rs
diff --git a/src/test/ui/issues/issue-40469.rs b/src/test/ui/macros/issue-40469.rs
similarity index 100%
rename from src/test/ui/issues/issue-40469.rs
rename to src/test/ui/macros/issue-40469.rs
diff --git a/src/test/ui/issues/issue-41803.rs b/src/test/ui/macros/issue-41803.rs
similarity index 100%
rename from src/test/ui/issues/issue-41803.rs
rename to src/test/ui/macros/issue-41803.rs
diff --git a/src/test/ui/issues/issue-5060.rs b/src/test/ui/macros/issue-5060.rs
similarity index 100%
rename from src/test/ui/issues/issue-5060.rs
rename to src/test/ui/macros/issue-5060.rs
diff --git a/src/test/ui/macros/vec-macro-in-pattern.rs b/src/test/ui/macros/vec-macro-in-pattern.rs
new file mode 100644
index 0000000..ce4298b
--- /dev/null
+++ b/src/test/ui/macros/vec-macro-in-pattern.rs
@@ -0,0 +1,10 @@
+// This is a regression test for #61933
+// Verify that the vec![] macro may not be used in patterns
+// and that the resulting diagnostic is actually helpful.
+
+fn main() {
+ match Some(vec![42]) {
+ Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns
+ _ => {}
+ }
+}
diff --git a/src/test/ui/macros/vec-macro-in-pattern.stderr b/src/test/ui/macros/vec-macro-in-pattern.stderr
new file mode 100644
index 0000000..3dabebf
--- /dev/null
+++ b/src/test/ui/macros/vec-macro-in-pattern.stderr
@@ -0,0 +1,10 @@
+error: arbitrary expressions aren't allowed in patterns
+ --> $DIR/vec-macro-in-pattern.rs:7:14
+ |
+LL | Some(vec![43]) => {}
+ | ^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-66851.rs b/src/test/ui/mir/issue-66851.rs
similarity index 100%
rename from src/test/ui/issues/issue-66851.rs
rename to src/test/ui/mir/issue-66851.rs
diff --git a/src/test/ui/mir/ssa-analysis-regression-50041.rs b/src/test/ui/mir/ssa-analysis-regression-50041.rs
new file mode 100644
index 0000000..c818f29
--- /dev/null
+++ b/src/test/ui/mir/ssa-analysis-regression-50041.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags: -Z mir-opt-level=3
+
+#![crate_type="lib"]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "owned_box"]
+pub struct Box<T: ?Sized>(*mut T);
+
+impl<T: ?Sized> Drop for Box<T> {
+ fn drop(&mut self) {
+ }
+}
+
+#[lang = "box_free"]
+#[inline(always)]
+unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+ dealloc(ptr)
+}
+
+#[inline(never)]
+fn dealloc<T: ?Sized>(_: *mut T) {
+}
+
+pub struct Foo<T>(T);
+
+pub fn foo(a: Option<Box<Foo<usize>>>) -> usize {
+ let f = match a {
+ None => Foo(0),
+ Some(vec) => *vec,
+ };
+ f.0
+}
diff --git a/src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/nll/issue-45696-long-live-borrows-in-boxes.rs
similarity index 100%
rename from src/test/ui/issues/issue-45696-long-live-borrows-in-boxes.rs
rename to src/test/ui/nll/issue-45696-long-live-borrows-in-boxes.rs
diff --git a/src/test/ui/issues/issue-51345-2.rs b/src/test/ui/nll/issue-51345-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-51345-2.rs
rename to src/test/ui/nll/issue-51345-2.rs
diff --git a/src/test/ui/issues/issue-51770.rs b/src/test/ui/nll/issue-51770.rs
similarity index 100%
rename from src/test/ui/issues/issue-51770.rs
rename to src/test/ui/nll/issue-51770.rs
diff --git a/src/test/ui/issues/issue-54943-3.rs b/src/test/ui/nll/issue-54943-3.rs
similarity index 100%
rename from src/test/ui/issues/issue-54943-3.rs
rename to src/test/ui/nll/issue-54943-3.rs
diff --git a/src/test/ui/issues/issue-55511.rs b/src/test/ui/nll/issue-55511.rs
similarity index 100%
rename from src/test/ui/issues/issue-55511.rs
rename to src/test/ui/nll/issue-55511.rs
diff --git a/src/test/ui/issues/issue-55511.stderr b/src/test/ui/nll/issue-55511.stderr
similarity index 100%
rename from src/test/ui/issues/issue-55511.stderr
rename to src/test/ui/nll/issue-55511.stderr
diff --git a/src/test/ui/non-built-in-quote.rs b/src/test/ui/non-built-in-quote.rs
deleted file mode 100644
index 92efa99..0000000
--- a/src/test/ui/non-built-in-quote.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-macro_rules! quote_tokens { () => (()) }
-
-pub fn main() {
- quote_tokens!();
-}
diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.noopt.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.opt.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
rename to src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/numbers-arithmetic/issue-8460-const.rs
similarity index 100%
rename from src/test/ui/issues/issue-8460-const.rs
rename to src/test/ui/numbers-arithmetic/issue-8460-const.rs
diff --git a/src/test/ui/issues/issue-8460.rs b/src/test/ui/numbers-arithmetic/issue-8460.rs
similarity index 100%
rename from src/test/ui/issues/issue-8460.rs
rename to src/test/ui/numbers-arithmetic/issue-8460.rs
diff --git a/src/test/ui/issues/auxiliary/issue-21146-inc.rs b/src/test/ui/parser/auxiliary/issue-21146-inc.rs
similarity index 100%
rename from src/test/ui/issues/auxiliary/issue-21146-inc.rs
rename to src/test/ui/parser/auxiliary/issue-21146-inc.rs
diff --git a/src/test/ui/can-begin-expr-check.rs b/src/test/ui/parser/can-begin-expr-check.rs
similarity index 100%
rename from src/test/ui/can-begin-expr-check.rs
rename to src/test/ui/parser/can-begin-expr-check.rs
diff --git a/src/test/ui/can-begin-expr-check.stderr b/src/test/ui/parser/can-begin-expr-check.stderr
similarity index 100%
rename from src/test/ui/can-begin-expr-check.stderr
rename to src/test/ui/parser/can-begin-expr-check.stderr
diff --git a/src/test/ui/issues/issue-20616-1.rs b/src/test/ui/parser/issue-20616-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-20616-1.rs
rename to src/test/ui/parser/issue-20616-1.rs
diff --git a/src/test/ui/issues/issue-20616-1.stderr b/src/test/ui/parser/issue-20616-1.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20616-1.stderr
rename to src/test/ui/parser/issue-20616-1.stderr
diff --git a/src/test/ui/issues/issue-20616-2.rs b/src/test/ui/parser/issue-20616-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-20616-2.rs
rename to src/test/ui/parser/issue-20616-2.rs
diff --git a/src/test/ui/issues/issue-20616-2.stderr b/src/test/ui/parser/issue-20616-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-20616-2.stderr
rename to src/test/ui/parser/issue-20616-2.stderr
diff --git a/src/test/ui/issues/issue-21146.rs b/src/test/ui/parser/issue-21146.rs
similarity index 100%
rename from src/test/ui/issues/issue-21146.rs
rename to src/test/ui/parser/issue-21146.rs
diff --git a/src/test/ui/issues/issue-21146.stderr b/src/test/ui/parser/issue-21146.stderr
similarity index 100%
rename from src/test/ui/issues/issue-21146.stderr
rename to src/test/ui/parser/issue-21146.stderr
diff --git a/src/test/ui/issues/issue-34222-1.rs b/src/test/ui/parser/issue-34222-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-34222-1.rs
rename to src/test/ui/parser/issue-34222-1.rs
diff --git a/src/test/ui/issues/issue-34222-1.stderr b/src/test/ui/parser/issue-34222-1.stderr
similarity index 100%
rename from src/test/ui/issues/issue-34222-1.stderr
rename to src/test/ui/parser/issue-34222-1.stderr
diff --git a/src/test/ui/issues/issue-43196.rs b/src/test/ui/parser/issue-43196.rs
similarity index 100%
rename from src/test/ui/issues/issue-43196.rs
rename to src/test/ui/parser/issue-43196.rs
diff --git a/src/test/ui/issues/issue-43196.stderr b/src/test/ui/parser/issue-43196.stderr
similarity index 100%
rename from src/test/ui/issues/issue-43196.stderr
rename to src/test/ui/parser/issue-43196.stderr
diff --git a/src/test/ui/issues/issue-44021.rs b/src/test/ui/parser/issue-44021.rs
similarity index 100%
rename from src/test/ui/issues/issue-44021.rs
rename to src/test/ui/parser/issue-44021.rs
diff --git a/src/test/ui/issues/issue-44021.stderr b/src/test/ui/parser/issue-44021.stderr
similarity index 100%
rename from src/test/ui/issues/issue-44021.stderr
rename to src/test/ui/parser/issue-44021.stderr
diff --git a/src/test/ui/issues/issue-45296.rs b/src/test/ui/parser/issue-45296.rs
similarity index 100%
rename from src/test/ui/issues/issue-45296.rs
rename to src/test/ui/parser/issue-45296.rs
diff --git a/src/test/ui/issues/issue-45296.stderr b/src/test/ui/parser/issue-45296.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45296.stderr
rename to src/test/ui/parser/issue-45296.stderr
diff --git a/src/test/ui/issues/issue-46186.fixed b/src/test/ui/parser/issue-46186.fixed
similarity index 100%
rename from src/test/ui/issues/issue-46186.fixed
rename to src/test/ui/parser/issue-46186.fixed
diff --git a/src/test/ui/issues/issue-46186.rs b/src/test/ui/parser/issue-46186.rs
similarity index 100%
rename from src/test/ui/issues/issue-46186.rs
rename to src/test/ui/parser/issue-46186.rs
diff --git a/src/test/ui/issues/issue-46186.stderr b/src/test/ui/parser/issue-46186.stderr
similarity index 100%
rename from src/test/ui/issues/issue-46186.stderr
rename to src/test/ui/parser/issue-46186.stderr
diff --git a/src/test/ui/issues/issue-51602.rs b/src/test/ui/parser/issue-51602.rs
similarity index 100%
rename from src/test/ui/issues/issue-51602.rs
rename to src/test/ui/parser/issue-51602.rs
diff --git a/src/test/ui/issues/issue-51602.stderr b/src/test/ui/parser/issue-51602.stderr
similarity index 100%
rename from src/test/ui/issues/issue-51602.stderr
rename to src/test/ui/parser/issue-51602.stderr
diff --git a/src/test/ui/issues/issue-52496.rs b/src/test/ui/parser/issue-52496.rs
similarity index 100%
rename from src/test/ui/issues/issue-52496.rs
rename to src/test/ui/parser/issue-52496.rs
diff --git a/src/test/ui/issues/issue-52496.stderr b/src/test/ui/parser/issue-52496.stderr
similarity index 100%
rename from src/test/ui/issues/issue-52496.stderr
rename to src/test/ui/parser/issue-52496.stderr
diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/parser/issue-58856-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-58856-2.rs
rename to src/test/ui/parser/issue-58856-2.rs
diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/parser/issue-58856-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-58856-2.stderr
rename to src/test/ui/parser/issue-58856-2.stderr
diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/parser/issue-60075.rs
similarity index 100%
rename from src/test/ui/issues/issue-60075.rs
rename to src/test/ui/parser/issue-60075.rs
diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/parser/issue-60075.stderr
similarity index 100%
rename from src/test/ui/issues/issue-60075.stderr
rename to src/test/ui/parser/issue-60075.stderr
diff --git a/src/test/ui/issues/issue-62554.rs b/src/test/ui/parser/issue-62554.rs
similarity index 100%
rename from src/test/ui/issues/issue-62554.rs
rename to src/test/ui/parser/issue-62554.rs
diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/parser/issue-62554.stderr
similarity index 100%
rename from src/test/ui/issues/issue-62554.stderr
rename to src/test/ui/parser/issue-62554.stderr
diff --git a/src/test/ui/issues/issue-66473.rs b/src/test/ui/parser/issue-66473.rs
similarity index 100%
rename from src/test/ui/issues/issue-66473.rs
rename to src/test/ui/parser/issue-66473.rs
Binary files differ
diff --git a/src/test/ui/issues/issue-66473.stderr b/src/test/ui/parser/issue-66473.stderr
similarity index 100%
rename from src/test/ui/issues/issue-66473.stderr
rename to src/test/ui/parser/issue-66473.stderr
Binary files differ
diff --git a/src/test/ui/issues/issue-72253.rs b/src/test/ui/parser/issue-72253.rs
similarity index 100%
rename from src/test/ui/issues/issue-72253.rs
rename to src/test/ui/parser/issue-72253.rs
diff --git a/src/test/ui/issues/issue-72253.stderr b/src/test/ui/parser/issue-72253.stderr
similarity index 100%
rename from src/test/ui/issues/issue-72253.stderr
rename to src/test/ui/parser/issue-72253.stderr
diff --git a/src/test/ui/issues/issue-72373.rs b/src/test/ui/parser/issue-72373.rs
similarity index 100%
rename from src/test/ui/issues/issue-72373.rs
rename to src/test/ui/parser/issue-72373.rs
diff --git a/src/test/ui/issues/issue-72373.stderr b/src/test/ui/parser/issue-72373.stderr
similarity index 100%
rename from src/test/ui/issues/issue-72373.stderr
rename to src/test/ui/parser/issue-72373.stderr
diff --git a/src/test/ui/issues/issue-75599.rs b/src/test/ui/parser/issue-75599.rs
similarity index 100%
rename from src/test/ui/issues/issue-75599.rs
rename to src/test/ui/parser/issue-75599.rs
diff --git a/src/test/ui/issue-76597.fixed b/src/test/ui/parser/issue-76597.fixed
similarity index 100%
rename from src/test/ui/issue-76597.fixed
rename to src/test/ui/parser/issue-76597.fixed
diff --git a/src/test/ui/issue-76597.rs b/src/test/ui/parser/issue-76597.rs
similarity index 100%
rename from src/test/ui/issue-76597.rs
rename to src/test/ui/parser/issue-76597.rs
diff --git a/src/test/ui/issue-76597.stderr b/src/test/ui/parser/issue-76597.stderr
similarity index 100%
rename from src/test/ui/issue-76597.stderr
rename to src/test/ui/parser/issue-76597.stderr
diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/parser/lifetime_starts_expressions.rs
similarity index 100%
rename from src/test/ui/lifetime_starts_expressions.rs
rename to src/test/ui/parser/lifetime_starts_expressions.rs
diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/parser/lifetime_starts_expressions.stderr
similarity index 100%
rename from src/test/ui/lifetime_starts_expressions.stderr
rename to src/test/ui/parser/lifetime_starts_expressions.stderr
diff --git a/src/test/ui/issues/issue-12582.rs b/src/test/ui/pattern/issue-12582.rs
similarity index 100%
rename from src/test/ui/issues/issue-12582.rs
rename to src/test/ui/pattern/issue-12582.rs
diff --git a/src/test/ui/issues/issue-14221.rs b/src/test/ui/pattern/issue-14221.rs
similarity index 100%
rename from src/test/ui/issues/issue-14221.rs
rename to src/test/ui/pattern/issue-14221.rs
diff --git a/src/test/ui/issues/issue-14221.stderr b/src/test/ui/pattern/issue-14221.stderr
similarity index 100%
rename from src/test/ui/issues/issue-14221.stderr
rename to src/test/ui/pattern/issue-14221.stderr
diff --git a/src/test/ui/issues/issue-22546.rs b/src/test/ui/pattern/issue-22546.rs
similarity index 100%
rename from src/test/ui/issues/issue-22546.rs
rename to src/test/ui/pattern/issue-22546.rs
diff --git a/src/test/ui/issues/issue-6449.rs b/src/test/ui/pattern/issue-6449.rs
similarity index 100%
rename from src/test/ui/issues/issue-6449.rs
rename to src/test/ui/pattern/issue-6449.rs
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
similarity index 100%
rename from src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
rename to src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
similarity index 100%
rename from src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
rename to src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
diff --git a/src/test/ui/size-and-align.rs b/src/test/ui/pattern/size-and-align.rs
similarity index 100%
rename from src/test/ui/size-and-align.rs
rename to src/test/ui/pattern/size-and-align.rs
diff --git a/src/test/ui/issues/issue-29161.rs b/src/test/ui/privacy/issue-29161.rs
similarity index 100%
rename from src/test/ui/issues/issue-29161.rs
rename to src/test/ui/privacy/issue-29161.rs
diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/privacy/issue-29161.stderr
similarity index 100%
rename from src/test/ui/issues/issue-29161.stderr
rename to src/test/ui/privacy/issue-29161.stderr
diff --git a/src/test/ui/issues/issue-30079.rs b/src/test/ui/privacy/issue-30079.rs
similarity index 100%
rename from src/test/ui/issues/issue-30079.rs
rename to src/test/ui/privacy/issue-30079.rs
diff --git a/src/test/ui/issues/issue-30079.stderr b/src/test/ui/privacy/issue-30079.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30079.stderr
rename to src/test/ui/privacy/issue-30079.stderr
diff --git a/src/test/ui/priv-in-bad-locations.rs b/src/test/ui/privacy/priv-in-bad-locations.rs
similarity index 100%
rename from src/test/ui/priv-in-bad-locations.rs
rename to src/test/ui/privacy/priv-in-bad-locations.rs
diff --git a/src/test/ui/priv-in-bad-locations.stderr b/src/test/ui/privacy/priv-in-bad-locations.stderr
similarity index 100%
rename from src/test/ui/priv-in-bad-locations.stderr
rename to src/test/ui/privacy/priv-in-bad-locations.stderr
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
index 142efb3..5f45f68 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
@@ -1,5 +1,5 @@
+// edition:2018
// aux-build:builtin-attrs.rs
-
#![feature(decl_macro)] //~ ERROR `feature` is ambiguous
extern crate builtin_attrs;
@@ -31,3 +31,7 @@
Bench;
NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
}
+
+use deny as allow;
+#[allow(unused)] //~ ERROR `allow` is ambiguous (built-in attribute vs any other name)
+fn builtin_renamed() {}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
index 276ee1c..dfd60dc 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
@@ -60,6 +60,20 @@
| ^^^^^^^^^^^^^^^^
= help: use `crate::repr` to refer to this attribute macro unambiguously
+error[E0659]: `allow` is ambiguous (built-in attribute vs any other name)
+ --> $DIR/ambiguous-builtin-attrs.rs:36:3
+ |
+LL | #[allow(unused)]
+ | ^^^^^ ambiguous name
+ |
+ = note: `allow` could refer to a built-in attribute
+note: `allow` could also refer to the built-in attribute imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:35:5
+ |
+LL | use deny as allow;
+ | ^^^^^^^^^^^^^
+ = help: use `crate::allow` to refer to this built-in attribute unambiguously
+
error[E0659]: `feature` is ambiguous (built-in attribute vs any other name)
--> $DIR/ambiguous-builtin-attrs.rs:3:4
|
@@ -80,7 +94,7 @@
LL | fn non_macro_expanded_location<#[repr(C)] T>() {
| ^ - not a struct, enum, or union
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
Some errors have detailed explanations: E0425, E0517, E0659.
For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/unreachable-code-ret.rs b/src/test/ui/reachable/unreachable-code-ret.rs
similarity index 100%
rename from src/test/ui/unreachable-code-ret.rs
rename to src/test/ui/reachable/unreachable-code-ret.rs
diff --git a/src/test/ui/unreachable-code-ret.stderr b/src/test/ui/reachable/unreachable-code-ret.stderr
similarity index 100%
rename from src/test/ui/unreachable-code-ret.stderr
rename to src/test/ui/reachable/unreachable-code-ret.stderr
diff --git a/src/test/ui/issues/issue-12470.rs b/src/test/ui/regions/issue-12470.rs
similarity index 100%
rename from src/test/ui/issues/issue-12470.rs
rename to src/test/ui/regions/issue-12470.rs
diff --git a/src/test/ui/issues/issue-12470.stderr b/src/test/ui/regions/issue-12470.stderr
similarity index 100%
rename from src/test/ui/issues/issue-12470.stderr
rename to src/test/ui/regions/issue-12470.stderr
diff --git a/src/test/ui/issues/issue-24085.rs b/src/test/ui/regions/issue-24085.rs
similarity index 100%
rename from src/test/ui/issues/issue-24085.rs
rename to src/test/ui/regions/issue-24085.rs
diff --git a/src/test/ui/issues/issue-2718.rs b/src/test/ui/regions/issue-2718.rs
similarity index 100%
rename from src/test/ui/issues/issue-2718.rs
rename to src/test/ui/regions/issue-2718.rs
diff --git a/src/test/ui/issues/issue-28848.nll.stderr b/src/test/ui/regions/issue-28848.nll.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28848.nll.stderr
rename to src/test/ui/regions/issue-28848.nll.stderr
diff --git a/src/test/ui/issues/issue-28848.rs b/src/test/ui/regions/issue-28848.rs
similarity index 100%
rename from src/test/ui/issues/issue-28848.rs
rename to src/test/ui/regions/issue-28848.rs
diff --git a/src/test/ui/issues/issue-28848.stderr b/src/test/ui/regions/issue-28848.stderr
similarity index 100%
rename from src/test/ui/issues/issue-28848.stderr
rename to src/test/ui/regions/issue-28848.stderr
diff --git a/src/test/ui/issues/issue-5243.rs b/src/test/ui/regions/issue-5243.rs
similarity index 100%
rename from src/test/ui/issues/issue-5243.rs
rename to src/test/ui/regions/issue-5243.rs
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
index fee8b06..9220823 100644
--- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -1,4 +1,4 @@
-error: cannot specialize on `ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,))`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)))`
--> $DIR/repeated_projection_type.rs:19:1
|
LL | / impl<I, V: Id<This = (I,)>> X for V {
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
index cc57071..656564f 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
@@ -22,7 +22,7 @@
impl UnstableTrait for StableType {}
#[unstable(feature = "x", issue = "none")]
-//~^ ERROR an `#[unstable]` annotation here has no effect [rustc::ineffective_unstable_trait_impl]
+//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
impl StableTrait for StableType {}
fn main() {}
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
index 1915d03..a11479c 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
@@ -4,7 +4,7 @@
LL | #[unstable(feature = "x", issue = "none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(rustc::ineffective_unstable_trait_impl)]` on by default
+ = note: `#[deny(ineffective_unstable_trait_impl)]` on by default
= note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
error: aborting due to previous error
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.fixed b/src/test/ui/suggestions/vec-macro-in-pattern.fixed
deleted file mode 100644
index e1695d6..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.fixed
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-rustfix
-fn main() {
- // everything after `.as_ref` should be suggested
- match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
- Some([_x]) => (), //~ ERROR unexpected `(` after qualified path
- _ => (),
- }
-}
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.rs b/src/test/ui/suggestions/vec-macro-in-pattern.rs
deleted file mode 100644
index 4843629..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-rustfix
-fn main() {
- // everything after `.as_ref` should be suggested
- match Some(vec![3]).as_ref().map(|v| v.as_slice()) {
- Some(vec![_x]) => (), //~ ERROR unexpected `(` after qualified path
- _ => (),
- }
-}
diff --git a/src/test/ui/suggestions/vec-macro-in-pattern.stderr b/src/test/ui/suggestions/vec-macro-in-pattern.stderr
deleted file mode 100644
index f9d0464..0000000
--- a/src/test/ui/suggestions/vec-macro-in-pattern.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: unexpected `(` after qualified path
- --> $DIR/vec-macro-in-pattern.rs:5:14
- |
-LL | Some(vec![_x]) => (),
- | ^^^^^^^^
- | |
- | unexpected `(` after qualified path
- | the qualified path
- | in this macro invocation
- | help: use a slice pattern here instead: `[_x]`
- |
- = help: for more information, see https://doc.rust-lang.org/edition-guide/rust-2018/slice-patterns.html
- = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/eprint-on-tls-drop.rs b/src/test/ui/threads-sendsync/eprint-on-tls-drop.rs
similarity index 100%
rename from src/test/ui/eprint-on-tls-drop.rs
rename to src/test/ui/threads-sendsync/eprint-on-tls-drop.rs
diff --git a/src/test/ui/issues/issue-6334.rs b/src/test/ui/traits/issue-6334.rs
similarity index 100%
rename from src/test/ui/issues/issue-6334.rs
rename to src/test/ui/traits/issue-6334.rs
diff --git a/src/test/ui/issues/issue-65673.rs b/src/test/ui/traits/issue-65673.rs
similarity index 100%
rename from src/test/ui/issues/issue-65673.rs
rename to src/test/ui/traits/issue-65673.rs
diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/traits/issue-65673.stderr
similarity index 100%
rename from src/test/ui/issues/issue-65673.stderr
rename to src/test/ui/traits/issue-65673.stderr
diff --git a/src/test/ui/issues/issue-9394-inherited-trait-calls.rs b/src/test/ui/traits/issue-9394-inherited-trait-calls.rs
similarity index 100%
rename from src/test/ui/issues/issue-9394-inherited-trait-calls.rs
rename to src/test/ui/traits/issue-9394-inherited-trait-calls.rs
diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr
index ba393ff..755eec2 100644
--- a/src/test/ui/type/ascription/issue-47666.stderr
+++ b/src/test/ui/type/ascription/issue-47666.stderr
@@ -1,4 +1,4 @@
-error: expected type, found reserved keyword `box`
+error: expected type, found `<[_]>::into_vec(box [0, 1])`
--> $DIR/issue-47666.rs:3:25
|
LL | let _ = Option:Some(vec![0, 1]);
diff --git a/src/test/ui/typestate-cfg-nesting.rs b/src/test/ui/typestate-cfg-nesting.rs
deleted file mode 100644
index 5718e0e..0000000
--- a/src/test/ui/typestate-cfg-nesting.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_assignments)]
-#![allow(unknown_lints)]
-// pretty-expanded FIXME #23616
-
-#![allow(dead_assignment)]
-#![allow(unused_variables)]
-
-fn f() {
- let x = 10; let mut y = 11;
- if true { match x { _ => { y = x; } } } else { }
-}
-
-pub fn main() {
- let x = 10;
- let mut y = 11;
- if true { while false { y = x; } } else { }
-}
diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs
index a254f6e..c4db652 100644
--- a/src/test/ui/underscore-imports/hygiene.rs
+++ b/src/test/ui/underscore-imports/hygiene.rs
@@ -1,5 +1,6 @@
-// Make sure that underscore imports have the same hygiene considerations as
-// other imports.
+// Make sure that underscore imports have the same hygiene considerations as other imports.
+
+// check-pass
#![feature(decl_macro)]
@@ -7,7 +8,6 @@
pub use std::ops::Deref as _;
}
-
macro glob_import() {
pub use crate::x::*;
}
@@ -35,6 +35,6 @@
use crate::z::*;
glob_import!();
underscore_import!();
- (&()).deref(); //~ ERROR no method named `deref`
- (&mut ()).deref_mut(); //~ ERROR no method named `deref_mut`
+ (&()).deref();
+ (&mut ()).deref_mut();
}
diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr
deleted file mode 100644
index 2983613..0000000
--- a/src/test/ui/underscore-imports/hygiene.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0599]: no method named `deref` found for reference `&()` in the current scope
- --> $DIR/hygiene.rs:38:11
- |
-LL | (&()).deref();
- | ^^^^^ method not found in `&()`
- |
- = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
- |
-LL | use std::ops::Deref;
- |
-
-error[E0599]: no method named `deref_mut` found for mutable reference `&mut ()` in the current scope
- --> $DIR/hygiene.rs:39:15
- |
-LL | (&mut ()).deref_mut();
- | ^^^^^^^^^ method not found in `&mut ()`
- |
- = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
- |
-LL | use std::ops::DerefMut;
- |
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.rs b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
similarity index 100%
rename from src/test/ui/issues/issue-45087-unreachable-unsafe.rs
rename to src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
diff --git a/src/test/ui/issues/issue-45087-unreachable-unsafe.stderr b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.stderr
similarity index 100%
rename from src/test/ui/issues/issue-45087-unreachable-unsafe.stderr
rename to src/test/ui/unsafe/issue-45087-unreachable-unsafe.stderr
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.rs b/src/test/ui/unsafe/unsafe-move-val-init.rs
deleted file mode 100644
index 24249a7..0000000
--- a/src/test/ui/unsafe/unsafe-move-val-init.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(core_intrinsics)]
-
-use std::intrinsics;
-
-// `move_val_init` has an odd desugaring, check that it is still treated
-// as unsafe.
-fn main() {
- intrinsics::move_val_init(1 as *mut u32, 1);
- //~^ ERROR dereference of raw pointer is unsafe
-}
diff --git a/src/test/ui/unsafe/unsafe-move-val-init.stderr b/src/test/ui/unsafe/unsafe-move-val-init.stderr
deleted file mode 100644
index 44c2aae..0000000
--- a/src/test/ui/unsafe/unsafe-move-val-init.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
- --> $DIR/unsafe-move-val-init.rs:8:5
- |
-LL | intrinsics::move_val_init(1 as *mut u32, 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
- |
- = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/wasm/wasm-hang-issue-76281.rs b/src/test/ui/wasm/wasm-hang-issue-76281.rs
new file mode 100644
index 0000000..a4adfa6
--- /dev/null
+++ b/src/test/ui/wasm/wasm-hang-issue-76281.rs
@@ -0,0 +1,12 @@
+// only-wasm32
+// compile-flags: -C opt-level=2
+// build-pass
+
+// Regression test for #76281.
+// This seems like an issue related to LLVM rather than
+// libs-impl so place here.
+
+fn main() {
+ let mut v: Vec<&()> = Vec::new();
+ v.sort_by_key(|&r| r as *const ());
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 3edbe723..7607394 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -10,11 +10,10 @@
use rustc_hir::{
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
};
-use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::Span;
use rustc_span::sym;
use rustc_span::symbol::{Symbol, SymbolStr};
@@ -157,33 +156,6 @@
}
declare_clippy_lint! {
- /// **What it does:** Checks for `allow`/`warn`/`deny`/`forbid` attributes with scoped clippy
- /// lints and if those lints exist in clippy. If there is an uppercase letter in the lint name
- /// (not the tool name) and a lowercase version of this lint exists, it will suggest to lowercase
- /// the lint name.
- ///
- /// **Why is this bad?** A lint attribute with a mistyped lint name won't have an effect.
- ///
- /// **Known problems:** None.
- ///
- /// **Example:**
- /// Bad:
- /// ```rust
- /// #![warn(if_not_els)]
- /// #![deny(clippy::All)]
- /// ```
- ///
- /// Good:
- /// ```rust
- /// #![warn(if_not_else)]
- /// #![deny(clippy::all)]
- /// ```
- pub UNKNOWN_CLIPPY_LINTS,
- style,
- "unknown_lints for scoped Clippy lints"
-}
-
-declare_clippy_lint! {
/// **What it does:** Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
///
/// **Why is this bad?** Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
@@ -272,7 +244,6 @@
INLINE_ALWAYS,
DEPRECATED_SEMVER,
USELESS_ATTRIBUTE,
- UNKNOWN_CLIPPY_LINTS,
BLANKET_CLIPPY_RESTRICTION_LINTS,
]);
@@ -409,48 +380,9 @@
}
fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
- let lint_store = cx.lints();
for lint in items {
if let Some(lint_name) = extract_clippy_lint(lint) {
- if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(&lint_name, Some(sym::clippy))
- {
- span_lint_and_then(
- cx,
- UNKNOWN_CLIPPY_LINTS,
- lint.span(),
- &format!("unknown clippy lint: clippy::{}", lint_name),
- |diag| {
- let name_lower = lint_name.to_lowercase();
- let symbols = lint_store
- .get_lints()
- .iter()
- .map(|l| Symbol::intern(&l.name_lower()))
- .collect::<Vec<_>>();
- let sugg = find_best_match_for_name(
- &symbols,
- Symbol::intern(&format!("clippy::{}", name_lower)),
- None,
- );
- if lint_name.chars().any(char::is_uppercase)
- && lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok()
- {
- diag.span_suggestion(
- lint.span(),
- "lowercase the lint name",
- format!("clippy::{}", name_lower),
- Applicability::MachineApplicable,
- );
- } else if let Some(sugg) = sugg {
- diag.span_suggestion(
- lint.span(),
- "did you mean",
- sugg.to_string(),
- Applicability::MachineApplicable,
- );
- }
- },
- );
- } else if lint_name == "restriction" && ident != "allow" {
+ if lint_name == "restriction" && ident != "allow" {
span_lint_and_help(
cx,
BLANKET_CLIPPY_RESTRICTION_LINTS,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index bec0c9f..47b3cc3 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -163,6 +163,19 @@
}
declare_deprecated_lint! {
+ /// **What it does:** Nothing. This lint has been deprecated.
+ ///
+ /// **Deprecation reason:** This lint has been uplifted to rustc and is now called
+ /// `panic_fmt`.
pub PANIC_PARAMS,
"this lint has been uplifted to rustc and is now called `panic_fmt`"
}
+
+declare_deprecated_lint! {
+ /// **What it does:** Nothing. This lint has been deprecated.
+ ///
+ /// **Deprecation reason:** This lint has been integrated into the `unknown_lints`
+ /// rustc lint.
+ pub UNKNOWN_CLIPPY_LINTS,
+ "this lint has been integrated into the `unknown_lints` rustc lint"
+}
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index f9697af..a3a38fa 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,7 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
+use rustc_middle::ty::{Opaque, PredicateKind::Trait};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
@@ -97,7 +97,7 @@
&obligation,
);
if let Trait(trait_pred, _) =
- obligation.predicate.skip_binders()
+ obligation.predicate.kind().skip_binder()
{
db.note(&format!(
"`{}` doesn't implement `{}`",
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 35b057d..aaa1756 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -500,6 +500,10 @@
"clippy::panic_params",
"this lint has been uplifted to rustc and is now called `panic_fmt`",
);
+ store.register_removed(
+ "clippy::unknown_clippy_lints",
+ "this lint has been integrated into the `unknown_lints` rustc lint",
+ );
// end deprecated lints, do not remove this comment, it’s used in `update_lints`
// begin register lints, do not remove this comment, it’s used in `update_lints`
@@ -541,7 +545,6 @@
&attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
&attrs::INLINE_ALWAYS,
&attrs::MISMATCHED_TARGET_OS,
- &attrs::UNKNOWN_CLIPPY_LINTS,
&attrs::USELESS_ATTRIBUTE,
&await_holding_invalid::AWAIT_HOLDING_LOCK,
&await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
@@ -1375,7 +1378,6 @@
LintId::of(&attrs::DEPRECATED_CFG_ATTR),
LintId::of(&attrs::DEPRECATED_SEMVER),
LintId::of(&attrs::MISMATCHED_TARGET_OS),
- LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
LintId::of(&attrs::USELESS_ATTRIBUTE),
LintId::of(&bit_mask::BAD_BIT_MASK),
LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
@@ -1650,7 +1652,6 @@
LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
- LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
LintId::of(&blacklisted_name::BLACKLISTED_NAME),
LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
LintId::of(&collapsible_if::COLLAPSIBLE_IF),
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 6e81027..f7231bb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -1697,7 +1697,7 @@
if let ty::Opaque(def_id, _) = *ret_ty.kind() {
// one of the associated types must be Self
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
- if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+ if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
// walk the associated type and check for Self
if contains_ty(projection_predicate.ty, self_ty) {
return;
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index a435f86..3b71f1b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -115,13 +115,11 @@
.filter(|p| !p.is_global())
.filter_map(|obligation| {
// Note that we do not want to deal with qualified predicates here.
- if let ty::PredicateKind::Atom(ty::PredicateAtom::Trait(pred, _)) = obligation.predicate.kind() {
- if pred.def_id() == sized_trait {
- return None;
- }
- Some(pred)
- } else {
- None
+ match obligation.predicate.kind().no_bound_vars() {
+ Some(ty::PredicateKind::Trait(pred, _)) if pred.def_id() != sized_trait => {
+ Some(pred)
+ },
+ _ => None,
}
})
.collect::<Vec<_>>();
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 2501635..c6ae8b9 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -4,7 +4,7 @@
use rustc_hir::{Expr, ExprKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
-use rustc_middle::ty::{GenericPredicates, PredicateAtom, ProjectionPredicate, TraitPredicate};
+use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{BytePos, Span};
@@ -42,7 +42,7 @@
let mut preds = Vec::new();
for (pred, _) in generics.predicates {
if_chain! {
- if let PredicateAtom::Trait(poly_trait_pred, _) = pred.skip_binders();
+ if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder();
let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred));
if let Some(trait_def_id) = trait_id;
if trait_def_id == trait_pred.trait_ref.def_id;
@@ -60,7 +60,7 @@
pred: TraitPredicate<'tcx>,
) -> Option<ProjectionPredicate<'tcx>> {
generics.predicates.iter().find_map(|(proj_pred, _)| {
- if let ty::PredicateAtom::Projection(proj_pred) = proj_pred.skip_binders() {
+ if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() {
let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred));
if projection_pred.projection_ty.substs == pred.trait_ref.substs {
return Some(projection_pred);
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 3e39a47..4c707c4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -1470,7 +1470,7 @@
ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
ty::Opaque(ref def_id, _) => {
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
- if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() {
+ if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
index 7cb7d0a..a482017 100644
--- a/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -19,18 +19,18 @@
loop {
let predicates = tcx.predicates_of(current);
for (predicate, _) in predicates.predicates {
- match predicate.skip_binders() {
- ty::PredicateAtom::RegionOutlives(_)
- | ty::PredicateAtom::TypeOutlives(_)
- | ty::PredicateAtom::WellFormed(_)
- | ty::PredicateAtom::Projection(_)
- | ty::PredicateAtom::ConstEvaluatable(..)
- | ty::PredicateAtom::ConstEquate(..)
- | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
- ty::PredicateAtom::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
- ty::PredicateAtom::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
- ty::PredicateAtom::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
- ty::PredicateAtom::Trait(pred, _) => {
+ match predicate.kind().skip_binder() {
+ ty::PredicateKind::RegionOutlives(_)
+ | ty::PredicateKind::TypeOutlives(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Projection(_)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+ ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
+ ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
+ ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
+ ty::PredicateKind::Trait(pred, _) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index e1ee8db..4a53802 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -9,5 +9,6 @@
#[warn(clippy::drop_bounds)]
#[warn(clippy::temporary_cstring_as_ptr)]
#[warn(clippy::panic_params)]
+#[warn(clippy::unknown_clippy_lints)]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index edbb891..3429317 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -66,11 +66,17 @@
LL | #[warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^
+error: lint `clippy::unknown_clippy_lints` has been removed: `this lint has been integrated into the `unknown_lints` rustc lint`
+ --> $DIR/deprecated.rs:12:8
+ |
+LL | #[warn(clippy::unknown_clippy_lints)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
--> $DIR/deprecated.rs:1:8
|
LL | #[warn(clippy::unstable_as_slice)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
index 1b85904..94a667e 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
@@ -1,52 +1,58 @@
-error: unknown clippy lint: clippy::if_not_els
+error: unknown lint: `clippy::All`
+ --> $DIR/unknown_clippy_lints.rs:5:10
+ |
+LL | #![allow(clippy::All)]
+ | ^^^^^^^^^^^ help: did you mean: `clippy::all`
+ |
+ = note: `-D unknown-lints` implied by `-D warnings`
+
+error: unknown lint: `clippy::CMP_NAN`
+ --> $DIR/unknown_clippy_lints.rs:6:9
+ |
+LL | #![warn(clippy::CMP_NAN)]
+ | ^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_nan`
+
+error: unknown lint: `clippy::if_not_els`
--> $DIR/unknown_clippy_lints.rs:9:8
|
LL | #[warn(clippy::if_not_els)]
| ^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::if_not_else`
- |
- = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings`
-error: unknown clippy lint: clippy::UNNecsaRy_cAst
+error: unknown lint: `clippy::UNNecsaRy_cAst`
--> $DIR/unknown_clippy_lints.rs:10:8
|
LL | #[warn(clippy::UNNecsaRy_cAst)]
| ^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unnecessary_cast`
-error: unknown clippy lint: clippy::useles_transute
+error: unknown lint: `clippy::useles_transute`
--> $DIR/unknown_clippy_lints.rs:11:8
|
LL | #[warn(clippy::useles_transute)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::useless_transmute`
-error: unknown clippy lint: clippy::dead_cod
+error: unknown lint: `clippy::dead_cod`
--> $DIR/unknown_clippy_lints.rs:13:8
|
LL | #[warn(clippy::dead_cod)]
| ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::drop_copy`
-error: unknown clippy lint: clippy::unused_colle
+error: unknown lint: `clippy::unused_colle`
--> $DIR/unknown_clippy_lints.rs:15:8
|
LL | #[warn(clippy::unused_colle)]
| ^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::unused_self`
-error: unknown clippy lint: clippy::const_static_lifetim
+error: unknown lint: `clippy::const_static_lifetim`
--> $DIR/unknown_clippy_lints.rs:17:8
|
LL | #[warn(clippy::const_static_lifetim)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes`
-error: unknown clippy lint: clippy::All
+error: unknown lint: `clippy::All`
--> $DIR/unknown_clippy_lints.rs:5:10
|
LL | #![allow(clippy::All)]
- | ^^^^^^^^^^^ help: lowercase the lint name: `clippy::all`
+ | ^^^^^^^^^^^ help: did you mean: `clippy::all`
-error: unknown clippy lint: clippy::CMP_NAN
- --> $DIR/unknown_clippy_lints.rs:6:9
- |
-LL | #![warn(clippy::CMP_NAN)]
- | ^^^^^^^^^^^^^^^ help: lowercase the lint name: `clippy::cmp_nan`
-
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
index 4f9c794..216a643 160000
--- a/src/tools/rustfmt
+++ b/src/tools/rustfmt
@@ -1 +1 @@
-Subproject commit 4f9c794ce1e3c77698f522c3eb1ab935f23df303
+Subproject commit 216a64300563351cad20bb3847110c14561687e0
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index bc5e43d..e687901 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -7,8 +7,8 @@
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1500;
-const ISSUES_ENTRY_LIMIT: usize = 2830;
+const ROOT_ENTRY_LIMIT: usize = 1458;
+const ISSUES_ENTRY_LIMIT: usize = 2669;
fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
@@ -30,7 +30,7 @@
};
let count = std::fs::read_dir(dir_path).unwrap().count();
- if count >= limit {
+ if count > limit {
tidy_error!(
bad,
"following path contains more than {} entries, \