Skip to content

Rollup of 5 pull requests #109552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 24, 2023
Merged
62 changes: 30 additions & 32 deletions compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter()
.filter(|field| {
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();

Expand Down Expand Up @@ -356,7 +356,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.inputs()
.iter()
.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();
// If there's one field that references the given generic, great!
if let [(idx, _)] = args_referencing_param.as_slice()
Expand Down Expand Up @@ -579,8 +579,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Find out which of `in_ty_elements` refer to `param`.
// FIXME: It may be better to take the first if there are multiple,
// 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)| {
Self::find_param_in_ty((*in_ty_elem).into(), param)
let Some((drill_expr, drill_ty)) = is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
find_param_in_ty((*in_ty_elem).into(), param)
})) else {
// The param is not mentioned, or it is mentioned in multiple indexes.
return Err(expr);
Expand Down Expand Up @@ -628,10 +628,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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.
let Some((drill_generic_index, generic_argument_type)) =
Self::is_iterator_singleton(
is_iterator_singleton(
in_ty_adt_generic_args.iter().enumerate().filter(
|(_index, in_ty_generic)| {
Self::find_param_in_ty(*in_ty_generic, param)
find_param_in_ty(*in_ty_generic, param)
},
),
) else {
Expand Down Expand Up @@ -751,10 +751,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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.
let Some((drill_generic_index, generic_argument_type)) =
Self::is_iterator_singleton(
is_iterator_singleton(
in_ty_adt_generic_args.iter().enumerate().filter(
|(_index, in_ty_generic)| {
Self::find_param_in_ty(*in_ty_generic, param)
find_param_in_ty(*in_ty_generic, param)
},
),
) else {
Expand Down Expand Up @@ -793,14 +793,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// outer contextual information.

// (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
.variant_with_id(variant_def_id)
.fields
.iter()
.map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
.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 {
return Err(expr);
};
Expand Down Expand Up @@ -833,20 +833,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

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
/// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
pub fn find_param_in_ty(
ty: ty::GenericArg<'tcx>,
param_to_point_at: ty::GenericArg<'tcx>,
) -> bool {
let mut walk = ty.walk();
while let Some(arg) = walk.next() {
if arg == param_to_point_at {
return true;
}
if let ty::GenericArgKind::Type(ty) = arg.unpack()
/// 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.
fn find_param_in_ty<'tcx>(
ty: ty::GenericArg<'tcx>,
param_to_point_at: ty::GenericArg<'tcx>,
) -> bool {
let mut walk = ty.walk();
while let Some(arg) = walk.next() {
if arg == param_to_point_at {
return true;
}
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Alias(ty::Projection, ..) = ty.kind()
{
// This logic may seem a bit strange, but typically when
Expand All @@ -857,16 +857,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// in some UI tests.
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.
pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
match (iterator.next(), iterator.next()) {
(_, Some(_)) => None,
(first, _) => first,
}
/// 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> {
match (iterator.next(), iterator.next()) {
(_, Some(_)) => None,
(first, _) => first,
}
}
10 changes: 7 additions & 3 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,10 +712,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

unreachable!(
"we captured two identical projections: capture1 = {:?}, capture2 = {:?}",
capture1, capture2
self.tcx.sess.delay_span_bug(
closure_span,
&format!(
"two identical projections: ({:?}, {:?})",
capture1.place.projections, capture2.place.projections
),
);
std::cmp::Ordering::Equal
});
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ fn main() {
} else if target.contains("darwin")
|| target.contains("freebsd")
|| target.contains("windows-gnullvm")
|| target.contains("aix")
{
"c++"
} else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

fn consider_builtin_destruct_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
Expand Down Expand Up @@ -340,6 +345,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_unsize_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
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 {
Err(NoSolution)
};
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
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.
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `DiscriminantKind` is automatically implemented for every type.
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> {
Expand Down
1 change: 0 additions & 1 deletion library/alloc/src/collections/btree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ pub mod set;
mod set_val;
mod split;

#[doc(hidden)]
trait Recover<Q: ?Sized> {
type Key;

Expand Down
5 changes: 0 additions & 5 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
@@ -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 core::borrow::Borrow;
use core::cmp::Ordering::{self, Equal, Greater, Less};
Expand All @@ -18,8 +15,6 @@ use super::Recover;

use crate::alloc::{Allocator, Global};

// FIXME(conventions): implement bounded iterators

/// An ordered set based on a B-Tree.
///
/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance
Expand Down
7 changes: 0 additions & 7 deletions library/std/src/collections/hash/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub};

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 `()`.
///
/// As with the [`HashMap`] type, a `HashSet` requires that the elements
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/closures/issue-109188.rs
Original file line number Diff line number Diff line change
@@ -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() { }
19 changes: 19 additions & 0 deletions tests/ui/closures/issue-109188.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-flags: -Ztrait-solver=next
// check-pass

trait Mirror {
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/traits/new-solver/destruct.rs
Original file line number Diff line number Diff line change
@@ -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);
}