Auto merge of #71539 - Dylan-DPC:rollup-a2vbfh9, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #69456 (fix misleading type annotation diagonstics) - #71330 (Only run dataflow for const qualification if type-based check would fail) - #71480 (Improve PanicInfo examples readability) - #71485 (Add BinaryHeap::retain as suggested in #42849) - #71512 (Remove useless "" args) - #71527 (Miscellaneous cleanup in `check_consts`) - #71534 (Avoid unused Option::map results) - #71535 (Fix typos in docs for keyword "in") Failed merges: r? @ghost
This commit is contained in:
commit
40008dcb49
@ -93,12 +93,12 @@ static NIGHTLY_TOOLS: &[(&str, &str)] = &[
|
||||
];
|
||||
|
||||
fn print_error(tool: &str, submodule: &str) {
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
eprintln!("We detected that this PR updated '{}', but its tests failed.", tool);
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
eprintln!("If you do intend to update '{}', please check the error messages above and", tool);
|
||||
eprintln!("commit another update.");
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool);
|
||||
eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule);
|
||||
eprintln!("proper steps.");
|
||||
|
@ -665,6 +665,34 @@ impl<T: Ord> BinaryHeap<T> {
|
||||
pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
|
||||
DrainSorted { inner: self }
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
///
|
||||
/// In other words, remove all elements `e` such that `f(&e)` returns
|
||||
/// `false`. The elements are visited in unsorted (and unspecified) order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(binary_heap_retain)]
|
||||
/// use std::collections::BinaryHeap;
|
||||
///
|
||||
/// let mut heap = BinaryHeap::from(vec![-10, -5, 1, 2, 4, 13]);
|
||||
///
|
||||
/// heap.retain(|x| x % 2 == 0); // only keep even numbers
|
||||
///
|
||||
/// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4])
|
||||
/// ```
|
||||
#[unstable(feature = "binary_heap_retain", issue = "71503")]
|
||||
pub fn retain<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
self.data.retain(f);
|
||||
self.rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BinaryHeap<T> {
|
||||
|
@ -372,6 +372,14 @@ fn assert_covariance() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain() {
|
||||
let mut a = BinaryHeap::from(vec![-10, -5, 1, 2, 4, 13]);
|
||||
a.retain(|x| x % 2 == 0);
|
||||
|
||||
assert_eq!(a.into_sorted_vec(), [-10, 2, 4])
|
||||
}
|
||||
|
||||
// old binaryheap failed this test
|
||||
//
|
||||
// Integrity means that all elements are present after a comparison panics,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#![feature(binary_heap_drain_sorted)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(split_inclusive)]
|
||||
#![feature(binary_heap_retain)]
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -77,7 +77,11 @@ impl<'a> PanicInfo<'a> {
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|panic_info| {
|
||||
/// println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
|
||||
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||
/// println!("panic occurred: {:?}", s);
|
||||
/// } else {
|
||||
/// println!("panic occurred");
|
||||
/// }
|
||||
/// }));
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
@ -112,8 +116,10 @@ impl<'a> PanicInfo<'a> {
|
||||
///
|
||||
/// panic::set_hook(Box::new(|panic_info| {
|
||||
/// if let Some(location) = panic_info.location() {
|
||||
/// println!("panic occurred in file '{}' at line {}", location.file(),
|
||||
/// location.line());
|
||||
/// println!("panic occurred in file '{}' at line {}",
|
||||
/// location.file(),
|
||||
/// location.line(),
|
||||
/// );
|
||||
/// } else {
|
||||
/// println!("panic occurred but can't get location information...");
|
||||
/// }
|
||||
|
@ -98,7 +98,7 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
|
||||
}
|
||||
}
|
||||
|
||||
diagnostic.map(|d| {
|
||||
if let Some(d) = diagnostic {
|
||||
struct_span_err!(d, attr.span, E0633, "malformed `unwind` attribute input")
|
||||
.span_label(attr.span, "invalid argument")
|
||||
.span_suggestions(
|
||||
@ -110,7 +110,7 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1172,10 +1172,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
// ignore derives so they remain unused
|
||||
let (attr, after_derive) = self.classify_nonitem(&mut expr);
|
||||
|
||||
if attr.is_some() {
|
||||
if let Some(ref attr_value) = attr {
|
||||
// Collect the invoc regardless of whether or not attributes are permitted here
|
||||
// expansion will eat the attribute so it won't error later.
|
||||
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
|
||||
self.cfg.maybe_emit_expr_attr_err(attr_value);
|
||||
|
||||
// AstFragmentKind::Expr requires the macro to emit an expression.
|
||||
return self
|
||||
@ -1322,8 +1322,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
// Ignore derives so they remain unused.
|
||||
let (attr, after_derive) = self.classify_nonitem(&mut expr);
|
||||
|
||||
if attr.is_some() {
|
||||
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
|
||||
if let Some(ref attr_value) = attr {
|
||||
self.cfg.maybe_emit_expr_attr_err(attr_value);
|
||||
|
||||
return self
|
||||
.collect_attr(
|
||||
|
@ -246,7 +246,7 @@ impl DefPath {
|
||||
|
||||
let mut opt_delimiter = None;
|
||||
for component in &self.data {
|
||||
opt_delimiter.map(|d| s.push(d));
|
||||
s.extend(opt_delimiter);
|
||||
opt_delimiter = Some('-');
|
||||
if component.disambiguator == 0 {
|
||||
write!(s, "{}", component.data.as_symbol()).unwrap();
|
||||
|
@ -755,7 +755,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
},
|
||||
ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => {
|
||||
err.span_label(then, "expected because of this");
|
||||
outer.map(|sp| err.span_label(sp, "`if` and `else` have incompatible types"));
|
||||
if let Some(sp) = outer {
|
||||
err.span_label(sp, "`if` and `else` have incompatible types");
|
||||
}
|
||||
if let Some(sp) = semicolon {
|
||||
err.span_suggestion_short(
|
||||
sp,
|
||||
|
@ -17,23 +17,27 @@ use std::borrow::Cow;
|
||||
struct FindHirNodeVisitor<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
target: GenericArg<'tcx>,
|
||||
target_span: Span,
|
||||
found_node_ty: Option<Ty<'tcx>>,
|
||||
found_local_pattern: Option<&'tcx Pat<'tcx>>,
|
||||
found_arg_pattern: Option<&'tcx Pat<'tcx>>,
|
||||
found_closure: Option<&'tcx Expr<'tcx>>,
|
||||
found_method_call: Option<&'tcx Expr<'tcx>>,
|
||||
found_exact_method_call: Option<&'tcx Expr<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
|
||||
fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>) -> Self {
|
||||
fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>, target_span: Span) -> Self {
|
||||
Self {
|
||||
infcx,
|
||||
target,
|
||||
target_span,
|
||||
found_node_ty: None,
|
||||
found_local_pattern: None,
|
||||
found_arg_pattern: None,
|
||||
found_closure: None,
|
||||
found_method_call: None,
|
||||
found_exact_method_call: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +107,17 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::MethodCall(_, call_span, exprs) = expr.kind {
|
||||
if call_span == self.target_span
|
||||
&& Some(self.target)
|
||||
== self.infcx.in_progress_tables.and_then(|tables| {
|
||||
tables.borrow().node_type_opt(exprs.first().unwrap().hir_id).map(Into::into)
|
||||
})
|
||||
{
|
||||
self.found_exact_method_call = Some(&expr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if self.node_ty_contains_target(expr.hir_id).is_some() {
|
||||
match expr.kind {
|
||||
ExprKind::Closure(..) => self.found_closure = Some(&expr),
|
||||
@ -234,7 +249,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
|
||||
|
||||
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into());
|
||||
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into(), span);
|
||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||
let mut s = String::new();
|
||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
|
||||
@ -287,14 +302,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
(!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
|
||||
};
|
||||
|
||||
let ty_msg = match local_visitor.found_node_ty {
|
||||
Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => {
|
||||
let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) {
|
||||
(_, Some(_)) => String::new(),
|
||||
(Some(ty::TyS { kind: ty::Closure(_, substs), .. }), _) => {
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
let args = closure_args(&fn_sig);
|
||||
let ret = fn_sig.output().skip_binder().to_string();
|
||||
format!(" for the closure `fn({}) -> {}`", args, ret)
|
||||
}
|
||||
Some(ty) if is_named_and_not_impl_trait(ty) => {
|
||||
(Some(ty), _) if is_named_and_not_impl_trait(ty) => {
|
||||
let ty = ty_to_string(ty);
|
||||
format!(" for `{}`", ty)
|
||||
}
|
||||
@ -370,7 +386,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
_ => "a type".to_string(),
|
||||
};
|
||||
|
||||
if let Some(pattern) = local_visitor.found_arg_pattern {
|
||||
if let Some(e) = local_visitor.found_exact_method_call {
|
||||
if let ExprKind::MethodCall(segment, ..) = &e.kind {
|
||||
// Suggest specifying type params or point out the return type of the call:
|
||||
//
|
||||
// error[E0282]: type annotations needed
|
||||
// --> $DIR/type-annotations-needed-expr.rs:2:39
|
||||
// |
|
||||
// LL | let _ = x.into_iter().sum() as f64;
|
||||
// | ^^^
|
||||
// | |
|
||||
// | cannot infer type for `S`
|
||||
// | help: consider specifying the type argument in
|
||||
// | the method call: `sum::<S>`
|
||||
// |
|
||||
// = note: type must be known at this point
|
||||
//
|
||||
// or
|
||||
//
|
||||
// error[E0282]: type annotations needed
|
||||
// --> $DIR/issue-65611.rs:59:20
|
||||
// |
|
||||
// LL | let x = buffer.last().unwrap().0.clone();
|
||||
// | -------^^^^--
|
||||
// | | |
|
||||
// | | cannot infer type for `T`
|
||||
// | this method call resolves to `std::option::Option<&T>`
|
||||
// |
|
||||
// = note: type must be known at this point
|
||||
self.annotate_method_call(segment, e, &mut err);
|
||||
}
|
||||
} else if let Some(pattern) = local_visitor.found_arg_pattern {
|
||||
// We don't want to show the default label for closures.
|
||||
//
|
||||
// So, before clearing, the output would look something like this:
|
||||
|
@ -101,9 +101,15 @@ fn dump_crates(cstore: &CStore) {
|
||||
info!(" hash: {}", data.hash());
|
||||
info!(" reqd: {:?}", data.dep_kind());
|
||||
let CrateSource { dylib, rlib, rmeta } = data.source();
|
||||
dylib.as_ref().map(|dl| info!(" dylib: {}", dl.0.display()));
|
||||
rlib.as_ref().map(|rl| info!(" rlib: {}", rl.0.display()));
|
||||
rmeta.as_ref().map(|rl| info!(" rmeta: {}", rl.0.display()));
|
||||
if let Some(dylib) = dylib {
|
||||
info!(" dylib: {}", dylib.0.display());
|
||||
}
|
||||
if let Some(rlib) = rlib {
|
||||
info!(" rlib: {}", rlib.0.display());
|
||||
}
|
||||
if let Some(rmeta) = rmeta {
|
||||
info!(" rmeta: {}", rmeta.0.display());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::{def_id::DefId, HirId};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
@ -28,70 +27,100 @@ use crate::dataflow::{self, Analysis};
|
||||
// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
|
||||
// through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals`
|
||||
// kills locals upon `StorageDead` because a local will never be used after a `StorageDead`.
|
||||
pub type IndirectlyMutableResults<'mir, 'tcx> =
|
||||
type IndirectlyMutableResults<'mir, 'tcx> =
|
||||
dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
|
||||
|
||||
struct QualifCursor<'a, 'mir, 'tcx, Q: Qualif> {
|
||||
cursor: dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>>,
|
||||
in_any_value_of_ty: BitSet<Local>,
|
||||
type QualifResults<'mir, 'tcx, Q> =
|
||||
dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Qualifs<'mir, 'tcx> {
|
||||
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
||||
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
|
||||
indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
|
||||
}
|
||||
|
||||
impl<Q: Qualif> QualifCursor<'a, 'mir, 'tcx, Q> {
|
||||
pub fn new(q: Q, ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
|
||||
let cursor = FlowSensitiveAnalysis::new(q, ccx)
|
||||
.into_engine(ccx.tcx, ccx.body, ccx.def_id)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(ccx.body);
|
||||
impl Qualifs<'mir, 'tcx> {
|
||||
fn indirectly_mutable(
|
||||
&mut self,
|
||||
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||
local: Local,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
let indirectly_mutable = self.indirectly_mutable.get_or_insert_with(|| {
|
||||
let ConstCx { tcx, body, def_id, param_env, .. } = *ccx;
|
||||
|
||||
let mut in_any_value_of_ty = BitSet::new_empty(ccx.body.local_decls.len());
|
||||
for (local, decl) in ccx.body.local_decls.iter_enumerated() {
|
||||
if Q::in_any_value_of_ty(ccx, decl.ty) {
|
||||
in_any_value_of_ty.insert(local);
|
||||
}
|
||||
}
|
||||
// We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
|
||||
// allowed in a const.
|
||||
//
|
||||
// FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
|
||||
// without breaking stable code?
|
||||
MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
|
||||
.unsound_ignore_borrow_on_drop()
|
||||
.into_engine(tcx, &body, def_id)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(&body)
|
||||
});
|
||||
|
||||
QualifCursor { cursor, in_any_value_of_ty }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Qualifs<'a, 'mir, 'tcx> {
|
||||
has_mut_interior: QualifCursor<'a, 'mir, 'tcx, HasMutInterior>,
|
||||
needs_drop: QualifCursor<'a, 'mir, 'tcx, NeedsDrop>,
|
||||
indirectly_mutable: IndirectlyMutableResults<'mir, 'tcx>,
|
||||
}
|
||||
|
||||
impl Qualifs<'a, 'mir, 'tcx> {
|
||||
fn indirectly_mutable(&mut self, local: Local, location: Location) -> bool {
|
||||
self.indirectly_mutable.seek_before(location);
|
||||
self.indirectly_mutable.get().contains(local)
|
||||
indirectly_mutable.seek_before(location);
|
||||
indirectly_mutable.get().contains(local)
|
||||
}
|
||||
|
||||
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
|
||||
///
|
||||
/// Only updates the cursor if absolutely necessary
|
||||
fn needs_drop(&mut self, local: Local, location: Location) -> bool {
|
||||
if !self.needs_drop.in_any_value_of_ty.contains(local) {
|
||||
fn needs_drop(
|
||||
&mut self,
|
||||
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||
local: Local,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
let ty = ccx.body.local_decls[local].ty;
|
||||
if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.needs_drop.cursor.seek_before(location);
|
||||
self.needs_drop.cursor.get().contains(local) || self.indirectly_mutable(local, location)
|
||||
let needs_drop = self.needs_drop.get_or_insert_with(|| {
|
||||
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||
|
||||
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
|
||||
.into_engine(tcx, &body, def_id)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(&body)
|
||||
});
|
||||
|
||||
needs_drop.seek_before(location);
|
||||
needs_drop.get().contains(local) || self.indirectly_mutable(ccx, local, location)
|
||||
}
|
||||
|
||||
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
|
||||
///
|
||||
/// Only updates the cursor if absolutely necessary.
|
||||
fn has_mut_interior(&mut self, local: Local, location: Location) -> bool {
|
||||
if !self.has_mut_interior.in_any_value_of_ty.contains(local) {
|
||||
fn has_mut_interior(
|
||||
&mut self,
|
||||
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||
local: Local,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
let ty = ccx.body.local_decls[local].ty;
|
||||
if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.has_mut_interior.cursor.seek_before(location);
|
||||
self.has_mut_interior.cursor.get().contains(local)
|
||||
|| self.indirectly_mutable(local, location)
|
||||
let has_mut_interior = self.has_mut_interior.get_or_insert_with(|| {
|
||||
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||
|
||||
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
|
||||
.into_engine(tcx, &body, def_id)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(&body)
|
||||
});
|
||||
|
||||
has_mut_interior.seek_before(location);
|
||||
has_mut_interior.get().contains(local) || self.indirectly_mutable(ccx, local, location)
|
||||
}
|
||||
|
||||
fn in_return_place(&mut self, ccx: &ConstCx<'_, 'tcx>) -> ConstQualifs {
|
||||
fn in_return_place(&mut self, ccx: &'mir ConstCx<'mir, 'tcx>) -> ConstQualifs {
|
||||
// Find the `Return` terminator if one exists.
|
||||
//
|
||||
// If no `Return` terminator exists, this MIR is divergent. Just return the conservative
|
||||
@ -114,21 +143,21 @@ impl Qualifs<'a, 'mir, 'tcx> {
|
||||
let return_loc = ccx.body.terminator_loc(return_block);
|
||||
|
||||
ConstQualifs {
|
||||
needs_drop: self.needs_drop(RETURN_PLACE, return_loc),
|
||||
has_mut_interior: self.has_mut_interior(RETURN_PLACE, return_loc),
|
||||
needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
|
||||
has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Validator<'a, 'mir, 'tcx> {
|
||||
ccx: &'a ConstCx<'mir, 'tcx>,
|
||||
qualifs: Qualifs<'a, 'mir, 'tcx>,
|
||||
pub struct Validator<'mir, 'tcx> {
|
||||
ccx: &'mir ConstCx<'mir, 'tcx>,
|
||||
qualifs: Qualifs<'mir, 'tcx>,
|
||||
|
||||
/// The span of the current statement.
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl Deref for Validator<'_, 'mir, 'tcx> {
|
||||
impl Deref for Validator<'mir, 'tcx> {
|
||||
type Target = ConstCx<'mir, 'tcx>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -136,27 +165,9 @@ impl Deref for Validator<'_, 'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Validator<'a, 'mir, 'tcx> {
|
||||
pub fn new(ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
|
||||
let ConstCx { tcx, body, def_id, param_env, .. } = *ccx;
|
||||
|
||||
let needs_drop = QualifCursor::new(NeedsDrop, ccx);
|
||||
let has_mut_interior = QualifCursor::new(HasMutInterior, ccx);
|
||||
|
||||
// We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
|
||||
// allowed in a const.
|
||||
//
|
||||
// FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
|
||||
// without breaking stable code?
|
||||
let indirectly_mutable = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env)
|
||||
.unsound_ignore_borrow_on_drop()
|
||||
.into_engine(tcx, body, def_id)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body);
|
||||
|
||||
let qualifs = Qualifs { needs_drop, has_mut_interior, indirectly_mutable };
|
||||
|
||||
Validator { span: ccx.body.span, ccx, qualifs }
|
||||
impl Validator<'mir, 'tcx> {
|
||||
pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
|
||||
Validator { span: ccx.body.span, ccx, qualifs: Default::default() }
|
||||
}
|
||||
|
||||
pub fn check_body(&mut self) {
|
||||
@ -205,7 +216,7 @@ impl Validator<'a, 'mir, 'tcx> {
|
||||
where
|
||||
O: NonConstOp,
|
||||
{
|
||||
trace!("check_op: op={:?}", op);
|
||||
debug!("check_op: op={:?}", op);
|
||||
|
||||
if op.is_allowed_in_item(self) {
|
||||
return;
|
||||
@ -239,7 +250,7 @@ impl Validator<'a, 'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||
fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
|
||||
trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
|
||||
|
||||
@ -345,7 +356,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
| Rvalue::AddressOf(Mutability::Not, ref place) => {
|
||||
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
|
||||
&self.ccx,
|
||||
&mut |local| self.qualifs.has_mut_interior(local, location),
|
||||
&mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
|
||||
place.as_ref(),
|
||||
);
|
||||
|
||||
@ -386,15 +397,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, place_local: &Local, context: PlaceContext, location: Location) {
|
||||
trace!(
|
||||
"visit_local: place_local={:?} context={:?} location={:?}",
|
||||
place_local,
|
||||
context,
|
||||
location,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
|
||||
self.super_operand(op, location);
|
||||
if let Operand::Constant(c) = op {
|
||||
@ -571,7 +573,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
|
||||
let needs_drop = if let Some(local) = dropped_place.as_local() {
|
||||
// Use the span where the local was declared as the span of the drop error.
|
||||
err_span = self.body.local_decls[local].source_info.span;
|
||||
self.qualifs.needs_drop(local, location)
|
||||
self.qualifs.needs_drop(self.ccx, local, location)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
@ -1388,7 +1388,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// Insert a Shallow borrow of any places that is switched on.
|
||||
fake_borrows.as_mut().map(|fb| fb.insert(match_place));
|
||||
if let Some(fb) = fake_borrows {
|
||||
fb.insert(match_place);
|
||||
}
|
||||
|
||||
// perform the test, branching to one of N blocks. For each of
|
||||
// those N possible outcomes, create a (initially empty)
|
||||
|
@ -1206,8 +1206,8 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &Pa
|
||||
*sess.reached_eof.borrow_mut() |=
|
||||
unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none());
|
||||
for unmatched in unclosed_delims.drain(..) {
|
||||
make_unclosed_delims_error(unmatched, sess).map(|mut e| {
|
||||
if let Some(mut e) = make_unclosed_delims_error(unmatched, sess) {
|
||||
e.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,9 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
||||
self.with_context(LabeledBlock, |v| v.visit_block(&b));
|
||||
}
|
||||
hir::ExprKind::Break(label, ref opt_expr) => {
|
||||
opt_expr.as_ref().map(|e| self.visit_expr(e));
|
||||
if let Some(e) = opt_expr {
|
||||
self.visit_expr(e);
|
||||
}
|
||||
|
||||
if self.require_label_in_labeled_block(e.span, &label, "break") {
|
||||
// If we emitted an error about an unlabeled break in a labeled
|
||||
|
@ -133,7 +133,11 @@ impl<CTX: QueryContext> QueryJob<CTX> {
|
||||
/// as there are no concurrent jobs which could be waiting on us
|
||||
pub fn signal_complete(self) {
|
||||
#[cfg(parallel_compiler)]
|
||||
self.latch.map(|latch| latch.set());
|
||||
{
|
||||
if let Some(latch) = self.latch {
|
||||
latch.set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1996,7 +1996,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
this.visit_expr(cond);
|
||||
this.visit_block(then);
|
||||
});
|
||||
opt_else.as_ref().map(|expr| self.visit_expr(expr));
|
||||
if let Some(expr) = opt_else {
|
||||
self.visit_expr(expr);
|
||||
}
|
||||
}
|
||||
|
||||
ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
|
||||
|
@ -499,7 +499,9 @@ impl<'a> ModuleData<'a> {
|
||||
F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>),
|
||||
{
|
||||
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
|
||||
name_resolution.borrow().binding.map(|binding| f(resolver, key.ident, key.ns, binding));
|
||||
if let Some(binding) = name_resolution.borrow().binding {
|
||||
f(resolver, key.ident, key.ns, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,20 +979,21 @@ impl Target {
|
||||
macro_rules! key {
|
||||
($key_name:ident) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..]).map(|o| o.as_string()
|
||||
.map(|s| base.options.$key_name = s.to_string()));
|
||||
if let Some(s) = obj.find(&name).and_then(Json::as_string) {
|
||||
base.options.$key_name = s.to_string();
|
||||
}
|
||||
} );
|
||||
($key_name:ident, bool) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..])
|
||||
.map(|o| o.as_boolean()
|
||||
.map(|s| base.options.$key_name = s));
|
||||
if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
|
||||
base.options.$key_name = s;
|
||||
}
|
||||
} );
|
||||
($key_name:ident, Option<u64>) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..])
|
||||
.map(|o| o.as_u64()
|
||||
.map(|s| base.options.$key_name = Some(s)));
|
||||
if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
|
||||
base.options.$key_name = Some(s);
|
||||
}
|
||||
} );
|
||||
($key_name:ident, MergeFunctions) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
@ -1034,19 +1035,19 @@ impl Target {
|
||||
} );
|
||||
($key_name:ident, list) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..]).map(|o| o.as_array()
|
||||
.map(|v| base.options.$key_name = v.iter()
|
||||
.map(|a| a.as_string().unwrap().to_string()).collect()
|
||||
)
|
||||
);
|
||||
if let Some(v) = obj.find(&name).and_then(Json::as_array) {
|
||||
base.options.$key_name = v.iter()
|
||||
.map(|a| a.as_string().unwrap().to_string())
|
||||
.collect();
|
||||
}
|
||||
} );
|
||||
($key_name:ident, opt_list) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.find(&name[..]).map(|o| o.as_array()
|
||||
.map(|v| base.options.$key_name = Some(v.iter()
|
||||
.map(|a| a.as_string().unwrap().to_string()).collect())
|
||||
)
|
||||
);
|
||||
if let Some(v) = obj.find(&name).and_then(Json::as_array) {
|
||||
base.options.$key_name = Some(v.iter()
|
||||
.map(|a| a.as_string().unwrap().to_string())
|
||||
.collect());
|
||||
}
|
||||
} );
|
||||
($key_name:ident, optional) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
|
@ -213,7 +213,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
None,
|
||||
);
|
||||
|
||||
assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span));
|
||||
if let Some(b) = assoc_bindings.first() {
|
||||
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
}
|
||||
|
||||
substs
|
||||
}
|
||||
@ -1095,7 +1097,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
let (substs, assoc_bindings, _) =
|
||||
self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment);
|
||||
assoc_bindings.first().map(|b| AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span));
|
||||
if let Some(b) = assoc_bindings.first() {
|
||||
AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
}
|
||||
ty::TraitRef::new(trait_def_id, substs)
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Requires that the two types unify, and prints an error message if
|
||||
// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
self.demand_suptype_diag(sp, expected, actual).map(|mut e| e.emit());
|
||||
if let Some(mut e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demand_suptype_diag(
|
||||
|
@ -4492,15 +4492,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
_ => Err(ErrorReported),
|
||||
};
|
||||
if item_name.name != kw::Invalid {
|
||||
self.report_method_error(
|
||||
if let Some(mut e) = self.report_method_error(
|
||||
span,
|
||||
ty,
|
||||
item_name,
|
||||
SelfSource::QPath(qself),
|
||||
error,
|
||||
None,
|
||||
)
|
||||
.map(|mut e| e.emit());
|
||||
) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
result
|
||||
});
|
||||
|
@ -104,7 +104,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
actual: Ty<'tcx>,
|
||||
ti: TopInfo<'tcx>,
|
||||
) {
|
||||
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map(|mut err| err.emit());
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,12 +451,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Subtyping doesn't matter here, as the value is some kind of scalar.
|
||||
let demand_eqtype = |x, y| {
|
||||
if let Some((_, x_ty, x_span)) = x {
|
||||
self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti).map(|mut err| {
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) {
|
||||
if let Some((_, y_ty, y_span)) = y {
|
||||
self.endpoint_has_type(&mut err, y_span, y_ty);
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
demand_eqtype(lhs, rhs);
|
||||
@ -852,8 +854,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
|
||||
let had_err = diag.is_some();
|
||||
diag.map(|mut err| err.emit());
|
||||
let had_err = if let Some(mut err) = diag {
|
||||
err.emit();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Type-check subpatterns.
|
||||
if subpats.len() == variant.fields.len()
|
||||
|
@ -165,12 +165,18 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
hir::ExprKind::Binary(..) => {
|
||||
if !op.node.is_by_value() {
|
||||
let mut adjustments = tables.adjustments_mut();
|
||||
adjustments.get_mut(lhs.hir_id).map(|a| a.pop());
|
||||
adjustments.get_mut(rhs.hir_id).map(|a| a.pop());
|
||||
if let Some(a) = adjustments.get_mut(lhs.hir_id) {
|
||||
a.pop();
|
||||
}
|
||||
if let Some(a) = adjustments.get_mut(rhs.hir_id) {
|
||||
a.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ExprKind::AssignOp(..) => {
|
||||
tables.adjustments_mut().get_mut(lhs.hir_id).map(|a| a.pop());
|
||||
if let Some(a) = tables.adjustments_mut().get_mut(lhs.hir_id) {
|
||||
a.pop();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -215,7 +221,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
tables.type_dependent_defs_mut().remove(e.hir_id);
|
||||
tables.node_substs_mut().remove(e.hir_id);
|
||||
|
||||
tables.adjustments_mut().get_mut(base.hir_id).map(|a| {
|
||||
if let Some(a) = tables.adjustments_mut().get_mut(base.hir_id) {
|
||||
// Discard the need for a mutable borrow
|
||||
|
||||
// Extra adjustment made when indexing causes a drop
|
||||
@ -229,7 +235,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
// So the borrow discard actually happens here
|
||||
a.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1599,7 +1599,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
inline::record_extern_fqn(cx, did, TypeKind::Trait);
|
||||
|
||||
let mut param_names = vec![];
|
||||
reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
|
||||
if let Some(b) = reg.clean(cx) {
|
||||
param_names.push(GenericBound::Outlives(b));
|
||||
}
|
||||
for did in dids {
|
||||
let empty = cx.tcx.intern_substs(&[]);
|
||||
let path =
|
||||
@ -1662,10 +1664,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
tr
|
||||
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
|
||||
// these should turn up at the end
|
||||
pred.skip_binder()
|
||||
.1
|
||||
.clean(cx)
|
||||
.map(|r| regions.push(GenericBound::Outlives(r)));
|
||||
if let Some(r) = pred.skip_binder().1.clean(cx) {
|
||||
regions.push(GenericBound::Outlives(r));
|
||||
}
|
||||
return None;
|
||||
} else {
|
||||
return None;
|
||||
|
@ -94,7 +94,7 @@ impl TocBuilder {
|
||||
loop {
|
||||
match self.chain.pop() {
|
||||
Some(mut next) => {
|
||||
this.map(|e| next.children.entries.push(e));
|
||||
next.children.entries.extend(this);
|
||||
if next.level < level {
|
||||
// this is the parent we want, so return it to
|
||||
// its rightful place.
|
||||
@ -105,7 +105,7 @@ impl TocBuilder {
|
||||
}
|
||||
}
|
||||
None => {
|
||||
this.map(|e| self.top_level.entries.push(e));
|
||||
self.top_level.entries.extend(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -685,12 +685,12 @@ mod impl_keyword {}
|
||||
/// ## Literal Examples:
|
||||
///
|
||||
/// * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3.
|
||||
/// * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3.
|
||||
/// * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and including 3.
|
||||
///
|
||||
/// (Read more about [range patterns])
|
||||
///
|
||||
/// [`Iterator`]: ../book/ch13-04-performance.html
|
||||
/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns
|
||||
/// [range patterns]: ../reference/patterns.html?highlight=range#range-patterns
|
||||
/// [`for`]: keyword.for.html
|
||||
mod in_keyword {}
|
||||
|
||||
|
@ -91,7 +91,7 @@ impl<T> Packet<T> {
|
||||
//
|
||||
// This can only be called at channel-creation time
|
||||
pub fn inherit_blocker(&self, token: Option<SignalToken>, guard: MutexGuard<'_, ()>) {
|
||||
token.map(|token| {
|
||||
if let Some(token) = token {
|
||||
assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
|
||||
assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
|
||||
self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst);
|
||||
@ -118,7 +118,7 @@ impl<T> Packet<T> {
|
||||
unsafe {
|
||||
*self.steals.get() = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// When the shared packet is constructed, we grabbed this lock. The
|
||||
// purpose of this lock is to ensure that abort_selection() doesn't
|
||||
|
@ -343,8 +343,12 @@ impl<T> Packet<T> {
|
||||
mem::drop(guard);
|
||||
|
||||
// only outside of the lock do we wake up the pending threads
|
||||
pending_sender1.map(|t| t.signal());
|
||||
pending_sender2.map(|t| t.signal());
|
||||
if let Some(token) = pending_sender1 {
|
||||
token.signal();
|
||||
}
|
||||
if let Some(token) = pending_sender2 {
|
||||
token.signal();
|
||||
}
|
||||
}
|
||||
|
||||
// Prepares this shared packet for a channel clone, essentially just bumping
|
||||
@ -410,7 +414,9 @@ impl<T> Packet<T> {
|
||||
while let Some(token) = queue.dequeue() {
|
||||
token.signal();
|
||||
}
|
||||
waiter.map(|t| t.signal());
|
||||
if let Some(token) = waiter {
|
||||
token.signal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,22 @@
|
||||
error[E0391]: cycle detected when const checking `FOO`
|
||||
--> $DIR/issue-17252.rs:1:20
|
||||
error[E0391]: cycle detected when normalizing `FOO`
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `FOO`...
|
||||
--> $DIR/issue-17252.rs:1:1
|
||||
|
|
||||
LL | const FOO: usize = FOO;
|
||||
| ^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `FOO`...
|
||||
--> $DIR/issue-17252.rs:1:1
|
||||
|
|
||||
= note: ...which again requires const checking `FOO`, completing the cycle
|
||||
note: cycle used when const checking `main::{{constant}}#0`
|
||||
LL | const FOO: usize = FOO;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `FOO`...
|
||||
--> $DIR/issue-17252.rs:1:1
|
||||
|
|
||||
LL | const FOO: usize = FOO;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires normalizing `FOO`, completing the cycle
|
||||
note: cycle used when const-evaluating `main::{{constant}}#0`
|
||||
--> $DIR/issue-17252.rs:4:18
|
||||
|
|
||||
LL | let _x: [u8; FOO]; // caused stack overflow prior to fix
|
||||
|
@ -1,15 +1,26 @@
|
||||
error[E0391]: cycle detected when const checking `X::A::{{constant}}#0`
|
||||
error[E0391]: cycle detected when const-evaluating + checking `X::A::{{constant}}#0`
|
||||
--> $DIR/issue-23302-1.rs:4:9
|
||||
|
|
||||
LL | A = X::A as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires const checking `X::A::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when processing `X::A::{{constant}}#0`
|
||||
note: ...which requires const-evaluating + checking `X::A::{{constant}}#0`...
|
||||
--> $DIR/issue-23302-1.rs:4:9
|
||||
|
|
||||
LL | A = X::A as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `X::A::{{constant}}#0`...
|
||||
--> $DIR/issue-23302-1.rs:4:9
|
||||
|
|
||||
LL | A = X::A as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which requires normalizing `X::A as isize`...
|
||||
= note: ...which again requires const-evaluating + checking `X::A::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-23302-1.rs:3:1
|
||||
|
|
||||
LL | enum X {
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,15 +1,26 @@
|
||||
error[E0391]: cycle detected when const checking `Y::A::{{constant}}#0`
|
||||
error[E0391]: cycle detected when const-evaluating + checking `Y::A::{{constant}}#0`
|
||||
--> $DIR/issue-23302-2.rs:4:9
|
||||
|
|
||||
LL | A = Y::B as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which again requires const checking `Y::A::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when processing `Y::A::{{constant}}#0`
|
||||
note: ...which requires const-evaluating + checking `Y::A::{{constant}}#0`...
|
||||
--> $DIR/issue-23302-2.rs:4:9
|
||||
|
|
||||
LL | A = Y::B as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `Y::A::{{constant}}#0`...
|
||||
--> $DIR/issue-23302-2.rs:4:9
|
||||
|
|
||||
LL | A = Y::B as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which requires normalizing `Y::B as isize`...
|
||||
= note: ...which again requires const-evaluating + checking `Y::A::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-23302-2.rs:3:1
|
||||
|
|
||||
LL | enum Y {
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,20 +1,38 @@
|
||||
error[E0391]: cycle detected when const checking `A`
|
||||
--> $DIR/issue-23302-3.rs:1:16
|
||||
|
|
||||
LL | const A: i32 = B;
|
||||
| ^
|
||||
|
|
||||
note: ...which requires const checking `B`...
|
||||
--> $DIR/issue-23302-3.rs:3:16
|
||||
|
|
||||
LL | const B: i32 = A;
|
||||
| ^
|
||||
= note: ...which again requires const checking `A`, completing the cycle
|
||||
note: cycle used when processing `A`
|
||||
error[E0391]: cycle detected when const-evaluating + checking `A`
|
||||
--> $DIR/issue-23302-3.rs:1:1
|
||||
|
|
||||
LL | const A: i32 = B;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `A`...
|
||||
--> $DIR/issue-23302-3.rs:1:1
|
||||
|
|
||||
LL | const A: i32 = B;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `A`...
|
||||
--> $DIR/issue-23302-3.rs:1:1
|
||||
|
|
||||
LL | const A: i32 = B;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires normalizing `B`...
|
||||
note: ...which requires const-evaluating + checking `B`...
|
||||
--> $DIR/issue-23302-3.rs:3:1
|
||||
|
|
||||
LL | const B: i32 = A;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `B`...
|
||||
--> $DIR/issue-23302-3.rs:3:1
|
||||
|
|
||||
LL | const B: i32 = A;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `B`...
|
||||
--> $DIR/issue-23302-3.rs:3:1
|
||||
|
|
||||
LL | const B: i32 = A;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires normalizing `A`...
|
||||
= note: ...which again requires const-evaluating + checking `A`, completing the cycle
|
||||
= note: cycle used when running analysis passes on this crate
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,20 +1,48 @@
|
||||
error[E0391]: cycle detected when const checking `Foo::B::{{constant}}#0`
|
||||
error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{{constant}}#0`
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
|
|
||||
note: ...which requires const checking `A`...
|
||||
--> $DIR/issue-36163.rs:1:18
|
||||
note: ...which requires const-evaluating + checking `Foo::B::{{constant}}#0`...
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
note: ...which requires const-evaluating `Foo::B::{{constant}}#0`...
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
= note: ...which requires normalizing `A`...
|
||||
note: ...which requires const-evaluating + checking `A`...
|
||||
--> $DIR/issue-36163.rs:1:1
|
||||
|
|
||||
LL | const A: isize = Foo::B as isize;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires const checking `Foo::B::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when processing `Foo::B::{{constant}}#0`
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `A`...
|
||||
--> $DIR/issue-36163.rs:1:1
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
LL | const A: isize = Foo::B as isize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating `A`...
|
||||
--> $DIR/issue-36163.rs:1:1
|
||||
|
|
||||
LL | const A: isize = Foo::B as isize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires normalizing `A`...
|
||||
= note: ...which again requires const-evaluating + checking `Foo::B::{{constant}}#0`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-36163.rs:1:1
|
||||
|
|
||||
LL | / const A: isize = Foo::B as isize;
|
||||
LL | |
|
||||
LL | | enum Foo {
|
||||
LL | | B = A,
|
||||
LL | | }
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
30
src/test/ui/issues/issue-69455.rs
Normal file
30
src/test/ui/issues/issue-69455.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Regression test for #69455: projection predicate was not satisfied.
|
||||
// Compiler should indicate the correct location of the
|
||||
// unsatisfied projection predicate
|
||||
|
||||
pub trait Test<Rhs = Self> {
|
||||
type Output;
|
||||
|
||||
fn test(self, rhs: Rhs) -> Self::Output;
|
||||
}
|
||||
|
||||
impl Test<u32> for u64 {
|
||||
type Output = u64;
|
||||
|
||||
fn test(self, other: u32) -> u64 {
|
||||
self + (other as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Test<u64> for u64 {
|
||||
type Output = u64;
|
||||
|
||||
fn test(self, other: u64) -> u64 {
|
||||
(self + other) as u64
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let xs: Vec<u64> = vec![1, 2, 3];
|
||||
println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed [E0284]
|
||||
}
|
17
src/test/ui/issues/issue-69455.stderr
Normal file
17
src/test/ui/issues/issue-69455.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0284]: type annotations needed
|
||||
--> $DIR/issue-69455.rs:29:26
|
||||
|
|
||||
LL | type Output;
|
||||
| ------------ `<Self as Test<Rhs>>::Output` defined here
|
||||
...
|
||||
LL | println!("{}", 23u64.test(xs.iter().sum()));
|
||||
| ------^^^^-----------------
|
||||
| | |
|
||||
| | cannot infer type for type `u64`
|
||||
| this method call resolves to `<Self as Test<Rhs>>::Output`
|
||||
|
|
||||
= note: cannot satisfy `<u64 as Test<_>>::Output == _`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
Loading…
Reference in New Issue
Block a user