Auto merge of #109552 - matthiaskrgr:rollup-03xwois, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #109406 (Remove outdated comments)
 - #109433 (Return equal for two identical projections)
 - #109495 (Implement non-const `Destruct` trait in new solver)
 - #109519 (Link against libc++ on AIX)
 - #109550 (Make helper functions private in fn_ctxt/adjust_fulfillment_errors)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-24 06:16:24 +00:00
commit c763eceae3
13 changed files with 121 additions and 48 deletions

View File

@ -310,7 +310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter() .iter()
.filter(|field| { .filter(|field| {
let field_ty = field.ty(self.tcx, identity_substs); let field_ty = field.ty(self.tcx, identity_substs);
Self::find_param_in_ty(field_ty.into(), param_to_point_at) find_param_in_ty(field_ty.into(), param_to_point_at)
}) })
.collect(); .collect();
@ -356,7 +356,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.inputs() .inputs()
.iter() .iter()
.enumerate() .enumerate()
.filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at)) .filter(|(_, ty)| find_param_in_ty((**ty).into(), param_to_point_at))
.collect(); .collect();
// If there's one field that references the given generic, great! // If there's one field that references the given generic, great!
if let [(idx, _)] = args_referencing_param.as_slice() if let [(idx, _)] = args_referencing_param.as_slice()
@ -579,8 +579,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Find out which of `in_ty_elements` refer to `param`. // Find out which of `in_ty_elements` refer to `param`.
// FIXME: It may be better to take the first if there are multiple, // FIXME: It may be better to take the first if there are multiple,
// just so that the error points to a smaller expression. // just so that the error points to a smaller expression.
let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| { let Some((drill_expr, drill_ty)) = is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
Self::find_param_in_ty((*in_ty_elem).into(), param) find_param_in_ty((*in_ty_elem).into(), param)
})) else { })) else {
// The param is not mentioned, or it is mentioned in multiple indexes. // The param is not mentioned, or it is mentioned in multiple indexes.
return Err(expr); return Err(expr);
@ -628,10 +628,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We need to know which of the generic parameters mentions our target param. // We need to know which of the generic parameters mentions our target param.
// We expect that at least one of them does, since it is expected to be mentioned. // We expect that at least one of them does, since it is expected to be mentioned.
let Some((drill_generic_index, generic_argument_type)) = let Some((drill_generic_index, generic_argument_type)) =
Self::is_iterator_singleton( is_iterator_singleton(
in_ty_adt_generic_args.iter().enumerate().filter( in_ty_adt_generic_args.iter().enumerate().filter(
|(_index, in_ty_generic)| { |(_index, in_ty_generic)| {
Self::find_param_in_ty(*in_ty_generic, param) find_param_in_ty(*in_ty_generic, param)
}, },
), ),
) else { ) else {
@ -751,10 +751,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We need to know which of the generic parameters mentions our target param. // We need to know which of the generic parameters mentions our target param.
// We expect that at least one of them does, since it is expected to be mentioned. // We expect that at least one of them does, since it is expected to be mentioned.
let Some((drill_generic_index, generic_argument_type)) = let Some((drill_generic_index, generic_argument_type)) =
Self::is_iterator_singleton( is_iterator_singleton(
in_ty_adt_generic_args.iter().enumerate().filter( in_ty_adt_generic_args.iter().enumerate().filter(
|(_index, in_ty_generic)| { |(_index, in_ty_generic)| {
Self::find_param_in_ty(*in_ty_generic, param) find_param_in_ty(*in_ty_generic, param)
}, },
), ),
) else { ) else {
@ -793,14 +793,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// outer contextual information. // outer contextual information.
// (1) Find the (unique) field index which mentions the type in our constraint: // (1) Find the (unique) field index which mentions the type in our constraint:
let Some((field_index, field_type)) = Self::is_iterator_singleton( let Some((field_index, field_type)) = is_iterator_singleton(
in_ty_adt in_ty_adt
.variant_with_id(variant_def_id) .variant_with_id(variant_def_id)
.fields .fields
.iter() .iter()
.map(|field| field.ty(self.tcx, *in_ty_adt_generic_args)) .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
.enumerate() .enumerate()
.filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param)) .filter(|(_index, field_type)| find_param_in_ty((*field_type).into(), param))
) else { ) else {
return Err(expr); return Err(expr);
}; };
@ -833,20 +833,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Err(expr) Err(expr)
} }
}
// FIXME: This can be made into a private, non-impl function later. /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
/// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
/// to the given `param_to_point_at`. Returns `true` if it finds any use of the param. fn find_param_in_ty<'tcx>(
pub fn find_param_in_ty( ty: ty::GenericArg<'tcx>,
ty: ty::GenericArg<'tcx>, param_to_point_at: ty::GenericArg<'tcx>,
param_to_point_at: ty::GenericArg<'tcx>, ) -> bool {
) -> bool { let mut walk = ty.walk();
let mut walk = ty.walk(); while let Some(arg) = walk.next() {
while let Some(arg) = walk.next() { if arg == param_to_point_at {
if arg == param_to_point_at { return true;
return true; }
} if let ty::GenericArgKind::Type(ty) = arg.unpack()
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Alias(ty::Projection, ..) = ty.kind() && let ty::Alias(ty::Projection, ..) = ty.kind()
{ {
// This logic may seem a bit strange, but typically when // This logic may seem a bit strange, but typically when
@ -857,16 +857,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// in some UI tests. // in some UI tests.
walk.skip_current_subtree(); walk.skip_current_subtree();
} }
}
false
} }
false
}
// FIXME: This can be made into a private, non-impl function later. /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
/// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise. fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> { match (iterator.next(), iterator.next()) {
match (iterator.next(), iterator.next()) { (_, Some(_)) => None,
(_, Some(_)) => None, (first, _) => first,
(first, _) => first,
}
} }
} }

View File

@ -712,10 +712,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
unreachable!( self.tcx.sess.delay_span_bug(
"we captured two identical projections: capture1 = {:?}, capture2 = {:?}", closure_span,
capture1, capture2 &format!(
"two identical projections: ({:?}, {:?})",
capture1.place.projections, capture2.place.projections
),
); );
std::cmp::Ordering::Equal
}); });
} }

View File

@ -333,6 +333,7 @@ fn main() {
} else if target.contains("darwin") } else if target.contains("darwin")
|| target.contains("freebsd") || target.contains("freebsd")
|| target.contains("windows-gnullvm") || target.contains("windows-gnullvm")
|| target.contains("aix")
{ {
"c++" "c++"
} else if target.contains("netbsd") && llvm_static_stdcpp.is_some() { } else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {

View File

@ -212,6 +212,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>; ) -> QueryResult<'tcx>;
fn consider_builtin_destruct_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
} }
impl<'tcx> EvalCtxt<'_, 'tcx> { impl<'tcx> EvalCtxt<'_, 'tcx> {
@ -340,6 +345,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_unsize_candidate(self, goal) G::consider_builtin_unsize_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) { } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
G::consider_builtin_discriminant_kind_candidate(self, goal) G::consider_builtin_discriminant_kind_candidate(self, goal)
} else if lang_items.destruct_trait() == Some(trait_def_id) {
G::consider_builtin_destruct_candidate(self, goal)
} else { } else {
Err(NoSolution) Err(NoSolution)
}; };

View File

@ -487,6 +487,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}) })
} }
fn consider_builtin_destruct_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
bug!("`Destruct` does not have an associated type: {:?}", goal);
}
} }
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.

View File

@ -534,6 +534,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `DiscriminantKind` is automatically implemented for every type. // `DiscriminantKind` is automatically implemented for every type.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} }
fn consider_builtin_destruct_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
if !goal.param_env.is_const() {
// `Destruct` is automatically implemented for every type in
// non-const environments.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
// FIXME(-Ztrait-solver=next): Implement this when we get const working in the new solver
Err(NoSolution)
}
}
} }
impl<'tcx> EvalCtxt<'_, 'tcx> { impl<'tcx> EvalCtxt<'_, 'tcx> {

View File

@ -13,7 +13,6 @@ pub mod set;
mod set_val; mod set_val;
mod split; mod split;
#[doc(hidden)]
trait Recover<Q: ?Sized> { trait Recover<Q: ?Sized> {
type Key; type Key;

View File

@ -1,6 +1,3 @@
// This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface
// to TreeMap
use crate::vec::Vec; use crate::vec::Vec;
use core::borrow::Borrow; use core::borrow::Borrow;
use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::Ordering::{self, Equal, Greater, Less};
@ -18,8 +15,6 @@ use super::Recover;
use crate::alloc::{Allocator, Global}; use crate::alloc::{Allocator, Global};
// FIXME(conventions): implement bounded iterators
/// An ordered set based on a B-Tree. /// An ordered set based on a B-Tree.
/// ///
/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance

View File

@ -12,13 +12,6 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub};
use super::map::{map_try_reserve_error, RandomState}; use super::map::{map_try_reserve_error, RandomState};
// Future Optimization (FIXME!)
// ============================
//
// Iteration over zero sized values is a noop. There is no need
// for `bucket.val` in the case of HashSet. I suppose we would need HKT
// to get rid of it properly.
/// A [hash set] implemented as a `HashMap` where the value is `()`. /// A [hash set] implemented as a `HashMap` where the value is `()`.
/// ///
/// As with the [`HashMap`] type, a `HashSet` requires that the elements /// As with the [`HashMap`] type, a `HashSet` requires that the elements

View File

@ -0,0 +1,22 @@
enum Either {
One(X),
Two(X),
}
struct X(Y);
struct Y;
fn consume_fnmut(f: &dyn FnMut()) {
f();
}
fn move_into_fnmut() {
let x = move_into_fnmut();
consume_fnmut(&|| {
let Either::One(_t) = x; //~ ERROR mismatched types
let Either::Two(_t) = x; //~ ERROR mismatched types
});
}
fn main() { }

View File

@ -0,0 +1,19 @@
error[E0308]: mismatched types
--> $DIR/issue-109188.rs:17:13
|
LL | let Either::One(_t) = x;
| ^^^^^^^^^^^^^^^ - this expression has type `()`
| |
| expected `()`, found `Either`
error[E0308]: mismatched types
--> $DIR/issue-109188.rs:18:13
|
LL | let Either::Two(_t) = x;
| ^^^^^^^^^^^^^^^ - this expression has type `()`
| |
| expected `()`, found `Either`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,3 +1,4 @@
// compile-flags: -Ztrait-solver=next
// check-pass // check-pass
trait Mirror { trait Mirror {

View File

@ -0,0 +1,13 @@
// compile-flags: -Ztrait-solver=next
// check-pass
#![feature(const_trait_impl)]
fn foo(_: impl std::marker::Destruct) {}
struct MyAdt;
fn main() {
foo(1);
foo(MyAdt);
}