Auto merge of #110978 - Dylan-DPC:rollup-xclzwax, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #110614 (Clear response values for overflow in new solver) - #110894 (Bump libffi-sys to 2.3.0) - #110932 (include source error for LoadLibraryExW) - #110958 (Make sure that some stdlib method signatures aren't accidental refinements) - #110962 (Make drop_flags an IndexVec.) - #110965 (Don't duplicate anonymous lifetimes for async fn in traits) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
af2c7e0f9b
@ -1956,9 +1956,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libffi-sys"
|
||||
version = "2.2.1"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc65067b78c0fc069771e8b9a9e02df71e08858bec92c1f101377c67b9dca7c7"
|
||||
checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
@ -27,6 +27,7 @@ use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
|
||||
use proc_macro::bridge::client::ProcMacro;
|
||||
use std::error::Error;
|
||||
use std::ops::Fn;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
@ -1094,5 +1095,12 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
|
||||
}
|
||||
|
||||
debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
|
||||
Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts))
|
||||
|
||||
let last_error = last_error.unwrap();
|
||||
let message = if let Some(src) = last_error.source() {
|
||||
format!("{last_error} ({src}) (retried {max_attempts} times)")
|
||||
} else {
|
||||
format!("{last_error} (retried {max_attempts} times)")
|
||||
};
|
||||
Err(message)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::deref_separator::deref_finder;
|
||||
use crate::MirPass;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::patch::MirPatch;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
@ -84,12 +84,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||
|
||||
let reachable = traversal::reachable_as_bitset(body);
|
||||
|
||||
let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
|
||||
ElaborateDropsCtxt {
|
||||
tcx,
|
||||
body,
|
||||
env: &env,
|
||||
init_data: InitializationData { inits, uninits },
|
||||
drop_flags: Default::default(),
|
||||
drop_flags,
|
||||
patch: MirPatch::new(body),
|
||||
un_derefer: un_derefer,
|
||||
reachable,
|
||||
@ -293,7 +294,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
|
||||
body: &'a Body<'tcx>,
|
||||
env: &'a MoveDataParamEnv<'tcx>,
|
||||
init_data: InitializationData<'a, 'tcx>,
|
||||
drop_flags: FxHashMap<MovePathIndex, Local>,
|
||||
drop_flags: IndexVec<MovePathIndex, Option<Local>>,
|
||||
patch: MirPatch<'tcx>,
|
||||
un_derefer: UnDerefer<'tcx>,
|
||||
reachable: BitSet<BasicBlock>,
|
||||
@ -312,11 +313,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let patch = &mut self.patch;
|
||||
debug!("create_drop_flag({:?})", self.body.span);
|
||||
self.drop_flags.entry(index).or_insert_with(|| patch.new_internal(tcx.types.bool, span));
|
||||
self.drop_flags[index].get_or_insert_with(|| patch.new_internal(tcx.types.bool, span));
|
||||
}
|
||||
|
||||
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
|
||||
self.drop_flags.get(&index).map(|t| Place::from(*t))
|
||||
self.drop_flags[index].map(Place::from)
|
||||
}
|
||||
|
||||
/// create a patch that elaborates all drops in the input
|
||||
@ -463,7 +464,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
|
||||
if let Some(&flag) = self.drop_flags.get(&path) {
|
||||
if let Some(flag) = self.drop_flags[path] {
|
||||
let span = self.patch.source_info_for_location(self.body, loc).span;
|
||||
let val = self.constant_bool(span, val.value());
|
||||
self.patch.add_assign(loc, Place::from(flag), val);
|
||||
@ -474,7 +475,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
let loc = Location::START;
|
||||
let span = self.patch.source_info_for_location(self.body, loc).span;
|
||||
let false_ = self.constant_bool(span, false);
|
||||
for flag in self.drop_flags.values() {
|
||||
for flag in self.drop_flags.iter().flatten() {
|
||||
self.patch.add_assign(loc, Place::from(*flag), false_.clone());
|
||||
}
|
||||
}
|
||||
|
@ -859,13 +859,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
|
||||
&sig.decl.output,
|
||||
);
|
||||
|
||||
this.record_lifetime_params_for_async(
|
||||
fn_id,
|
||||
sig.header.asyncness.opt_return_id(),
|
||||
);
|
||||
},
|
||||
);
|
||||
self.record_lifetime_params_for_async(fn_id, sig.header.asyncness.opt_return_id());
|
||||
return;
|
||||
}
|
||||
FnKind::Fn(..) => {
|
||||
|
@ -3,7 +3,8 @@ use rustc_infer::infer::at::ToTrace;
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{
|
||||
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
|
||||
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, RegionVariableOrigin,
|
||||
TyCtxtInferExt,
|
||||
};
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
@ -223,18 +224,20 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||
{
|
||||
debug!("rerunning goal to check result is stable");
|
||||
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
||||
let canonical_response =
|
||||
let new_canonical_response =
|
||||
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
|
||||
if !canonical_response.value.var_values.is_identity() {
|
||||
if !new_canonical_response.value.var_values.is_identity() {
|
||||
bug!(
|
||||
"unstable result: re-canonicalized goal={canonical_goal:#?} \
|
||||
response={canonical_response:#?}"
|
||||
first_response={canonical_response:#?} \
|
||||
second_response={new_canonical_response:#?}"
|
||||
);
|
||||
}
|
||||
if certainty != canonical_response.value.certainty {
|
||||
if certainty != new_canonical_response.value.certainty {
|
||||
bug!(
|
||||
"unstable certainty: {certainty:#?} re-canonicalized goal={canonical_goal:#?} \
|
||||
response={canonical_response:#?}"
|
||||
first_response={canonical_response:#?} \
|
||||
second_response={new_canonical_response:#?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -434,6 +437,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn next_region_infer(&self) -> ty::Region<'tcx> {
|
||||
self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
|
||||
}
|
||||
|
||||
pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
|
||||
self.infcx.next_const_var(
|
||||
ty,
|
||||
|
@ -16,7 +16,7 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData, MaybeCause};
|
||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::iter;
|
||||
@ -60,9 +60,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
||||
let certainty = certainty.unify_with(goals_certainty);
|
||||
|
||||
let external_constraints = self.compute_external_query_constraints()?;
|
||||
let response = match certainty {
|
||||
Certainty::Yes | Certainty::Maybe(MaybeCause::Ambiguity) => {
|
||||
let external_constraints = self.compute_external_query_constraints()?;
|
||||
Response { var_values: self.var_values, external_constraints, certainty }
|
||||
}
|
||||
Certainty::Maybe(MaybeCause::Overflow) => {
|
||||
// If we have overflow, it's probable that we're substituting a type
|
||||
// into itself infinitely and any partial substitutions in the query
|
||||
// response are probably not useful anyways, so just return an empty
|
||||
// query response.
|
||||
//
|
||||
// This may prevent us from potentially useful inference, e.g.
|
||||
// 2 candidates, one ambiguous and one overflow, which both
|
||||
// have the same inference constraints.
|
||||
//
|
||||
// Changing this to retain some constraints in the future
|
||||
// won't be a breaking change, so this is good enough for now.
|
||||
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
|
||||
}
|
||||
};
|
||||
|
||||
let response = Response { var_values: self.var_values, external_constraints, certainty };
|
||||
let canonical = Canonicalizer::canonicalize(
|
||||
self.infcx,
|
||||
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
|
||||
@ -72,6 +90,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
Ok(canonical)
|
||||
}
|
||||
|
||||
/// Constructs a totally unconstrained, ambiguous response to a goal.
|
||||
///
|
||||
/// Take care when using this, since often it's useful to respond with
|
||||
/// ambiguity but return constrained variables to guide inference.
|
||||
pub(in crate::solve) fn make_ambiguous_response_no_constraints(
|
||||
&self,
|
||||
maybe_cause: MaybeCause,
|
||||
) -> CanonicalResponse<'tcx> {
|
||||
let unconstrained_response = Response {
|
||||
var_values: CanonicalVarValues {
|
||||
var_values: self.tcx().mk_substs_from_iter(self.var_values.var_values.iter().map(
|
||||
|arg| -> ty::GenericArg<'tcx> {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Lifetime(_) => self.next_region_infer().into(),
|
||||
GenericArgKind::Type(_) => self.next_ty_infer().into(),
|
||||
GenericArgKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
|
||||
}
|
||||
},
|
||||
)),
|
||||
},
|
||||
external_constraints: self
|
||||
.tcx()
|
||||
.mk_external_constraints(ExternalConstraintsData::default()),
|
||||
certainty: Certainty::Maybe(maybe_cause),
|
||||
};
|
||||
|
||||
Canonicalizer::canonicalize(
|
||||
self.infcx,
|
||||
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
|
||||
&mut Default::default(),
|
||||
unconstrained_response,
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
|
||||
// Cannot use `take_registered_region_obligations` as we may compute the response
|
||||
|
@ -340,17 +340,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
if responses.is_empty() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
|
||||
certainty.unify_with(response.value.certainty)
|
||||
});
|
||||
|
||||
let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
|
||||
if let Ok(response) = response {
|
||||
assert!(response.has_no_inference_or_external_constraints());
|
||||
Ok(response)
|
||||
} else {
|
||||
bug!("failed to make floundered response: {responses:?}");
|
||||
}
|
||||
let Certainty::Maybe(maybe_cause) = responses.iter().fold(
|
||||
Certainty::AMBIGUOUS,
|
||||
|certainty, response| {
|
||||
certainty.unify_with(response.value.certainty)
|
||||
},
|
||||
) else {
|
||||
bug!("expected flounder response to be ambiguous")
|
||||
};
|
||||
|
||||
Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1543,11 +1543,17 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<(&'a K, &'a V)> {
|
||||
fn min(mut self) -> Option<(&'a K, &'a V)>
|
||||
where
|
||||
(&'a K, &'a V): Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<(&'a K, &'a V)> {
|
||||
fn max(mut self) -> Option<(&'a K, &'a V)>
|
||||
where
|
||||
(&'a K, &'a V): Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -1612,11 +1618,17 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
fn min(mut self) -> Option<(&'a K, &'a mut V)>
|
||||
where
|
||||
(&'a K, &'a mut V): Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
fn max(mut self) -> Option<(&'a K, &'a mut V)>
|
||||
where
|
||||
(&'a K, &'a mut V): Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -1779,11 +1791,17 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<&'a K> {
|
||||
fn min(mut self) -> Option<&'a K>
|
||||
where
|
||||
&'a K: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<&'a K> {
|
||||
fn max(mut self) -> Option<&'a K>
|
||||
where
|
||||
&'a K: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -2008,11 +2026,17 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<(&'a K, &'a V)> {
|
||||
fn min(mut self) -> Option<(&'a K, &'a V)>
|
||||
where
|
||||
(&'a K, &'a V): Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<(&'a K, &'a V)> {
|
||||
fn max(mut self) -> Option<(&'a K, &'a V)>
|
||||
where
|
||||
(&'a K, &'a V): Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -2081,11 +2105,17 @@ impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<K> {
|
||||
fn min(mut self) -> Option<K>
|
||||
where
|
||||
K: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<K> {
|
||||
fn max(mut self) -> Option<K>
|
||||
where
|
||||
K: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -2204,11 +2234,17 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
fn min(mut self) -> Option<(&'a K, &'a mut V)>
|
||||
where
|
||||
(&'a K, &'a mut V): Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
fn max(mut self) -> Option<(&'a K, &'a mut V)>
|
||||
where
|
||||
(&'a K, &'a mut V): Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
@ -1501,11 +1501,17 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<&'a T> {
|
||||
fn min(mut self) -> Option<&'a T>
|
||||
where
|
||||
&'a T: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<&'a T> {
|
||||
fn max(mut self) -> Option<&'a T>
|
||||
where
|
||||
&'a T: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
@ -1604,11 +1610,17 @@ impl<'a, T> Iterator for Range<'a, T> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
fn min(mut self) -> Option<&'a T> {
|
||||
fn min(mut self) -> Option<&'a T>
|
||||
where
|
||||
&'a T: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
fn max(mut self) -> Option<&'a T> {
|
||||
fn max(mut self) -> Option<&'a T>
|
||||
where
|
||||
&'a T: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
@ -2815,7 +2815,7 @@ impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extend_one(&mut self, &elem: &T) {
|
||||
fn extend_one(&mut self, &elem: &'a T) {
|
||||
self.push_back(elem);
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ where
|
||||
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
|
||||
fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> {
|
||||
if slice.len() == N {
|
||||
let ptr = slice.as_ptr() as *const [T; N];
|
||||
// SAFETY: ok because we just checked that the length fits
|
||||
@ -275,7 +275,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
|
||||
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
|
||||
fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> {
|
||||
if slice.len() == N {
|
||||
let ptr = slice.as_mut_ptr() as *mut [T; N];
|
||||
// SAFETY: ok because we just checked that the length fits
|
||||
|
@ -732,12 +732,18 @@ impl<A: Step> Iterator for ops::Range<A> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(mut self) -> Option<A> {
|
||||
fn min(mut self) -> Option<A>
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(mut self) -> Option<A> {
|
||||
fn max(mut self) -> Option<A>
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
@ -1158,12 +1164,18 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(mut self) -> Option<A> {
|
||||
fn min(mut self) -> Option<A>
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
self.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(mut self) -> Option<A> {
|
||||
fn max(mut self) -> Option<A>
|
||||
where
|
||||
A: Ord,
|
||||
{
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ macro_rules! deref_ops {
|
||||
|
||||
#[inline]
|
||||
#[must_use = "operator returns a new vector without mutating the inputs"]
|
||||
fn $call(self, rhs: &$simd) -> Self::Output {
|
||||
fn $call(self, rhs: &'rhs $simd) -> Self::Output {
|
||||
(*self).$call(*rhs)
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@
|
||||
}
|
||||
|
||||
bb0: {
|
||||
+ _9 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
|
||||
+ _7 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
|
||||
+ _8 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
|
||||
+ _9 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
|
||||
StorageLive(_1); // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
|
||||
StorageLive(_2); // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
|
||||
_2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
|
||||
|
@ -1,7 +1,5 @@
|
||||
// edition: 2021
|
||||
// known-bug: #105197
|
||||
// failure-status:101
|
||||
// dont-check-compiler-stderr
|
||||
// check-pass
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![feature(return_position_impl_trait_in_trait)]
|
||||
|
@ -0,0 +1,48 @@
|
||||
// edition: 2021
|
||||
// known-bug: #110963
|
||||
|
||||
#![feature(return_type_notation)]
|
||||
#![feature(async_fn_in_trait)]
|
||||
|
||||
trait HealthCheck {
|
||||
async fn check<'a: 'a>(&'a mut self) -> bool;
|
||||
}
|
||||
|
||||
async fn do_health_check_par<HC>(hc: HC)
|
||||
where
|
||||
HC: HealthCheck<check(): Send> + Send + 'static,
|
||||
{
|
||||
spawn(async move {
|
||||
let mut hc = hc;
|
||||
if !hc.check().await {
|
||||
log_health_check_failure().await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn log_health_check_failure() {}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// Fake tokio spawn
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
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 {}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-early.rs:4:12
|
||||
|
|
||||
LL | #![feature(return_type_notation)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-early.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-110963-early.rs:15:5
|
||||
|
|
||||
LL | / spawn(async move {
|
||||
LL | | let mut hc = hc;
|
||||
LL | | if !hc.check().await {
|
||||
LL | | log_health_check_failure().await;
|
||||
LL | | }
|
||||
LL | | });
|
||||
| |______^
|
||||
|
|
||||
= note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
|
||||
|
||||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-110963-early.rs:15:5
|
||||
|
|
||||
LL | / spawn(async move {
|
||||
LL | | let mut hc = hc;
|
||||
LL | | if !hc.check().await {
|
||||
LL | | log_health_check_failure().await;
|
||||
LL | | }
|
||||
LL | | });
|
||||
| |______^
|
||||
|
|
||||
= note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
|
@ -0,0 +1,50 @@
|
||||
// edition: 2021
|
||||
// check-pass
|
||||
|
||||
#![feature(return_type_notation)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait HealthCheck {
|
||||
async fn check(&mut self) -> bool;
|
||||
}
|
||||
|
||||
async fn do_health_check_par<HC>(hc: HC)
|
||||
where
|
||||
HC: HealthCheck<check(): Send> + Send + 'static,
|
||||
{
|
||||
spawn(async move {
|
||||
let mut hc = hc;
|
||||
if !hc.check().await {
|
||||
log_health_check_failure().await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn log_health_check_failure() {}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// Fake tokio spawn
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
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 {}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-late.rs:4:12
|
||||
|
|
||||
LL | #![feature(return_type_notation)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-late.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
20
tests/ui/traits/new-solver/exponential-trait-goals.rs
Normal file
20
tests/ui/traits/new-solver/exponential-trait-goals.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Trait {}
|
||||
|
||||
struct W<T>(T);
|
||||
|
||||
impl<T, U> Trait for W<(W<T>, W<U>)>
|
||||
where
|
||||
W<T>: Trait,
|
||||
W<U>: Trait,
|
||||
{
|
||||
}
|
||||
|
||||
fn impls<T: Trait>() {}
|
||||
|
||||
fn main() {
|
||||
impls::<W<_>>();
|
||||
//~^ ERROR type annotations needed
|
||||
//~| ERROR overflow evaluating the requirement `W<_>: Trait`
|
||||
}
|
23
tests/ui/traits/new-solver/exponential-trait-goals.stderr
Normal file
23
tests/ui/traits/new-solver/exponential-trait-goals.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/exponential-trait-goals.rs:17:5
|
||||
|
|
||||
LL | impls::<W<_>>();
|
||||
| ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `W<_>: Trait`
|
||||
--> $DIR/exponential-trait-goals.rs:17:5
|
||||
|
|
||||
LL | impls::<W<_>>();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`exponential_trait_goals`)
|
||||
note: required by a bound in `impls`
|
||||
--> $DIR/exponential-trait-goals.rs:14:13
|
||||
|
|
||||
LL | fn impls<T: Trait>() {}
|
||||
| ^^^^^ required by this bound in `impls`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0275, E0282.
|
||||
For more information about an error, try `rustc --explain E0275`.
|
Loading…
x
Reference in New Issue
Block a user