about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs62
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs10
-rw-r--r--compiler/rustc_llvm/build.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs14
-rw-r--r--library/alloc/src/collections/btree/mod.rs1
-rw-r--r--library/alloc/src/collections/btree/set.rs5
-rw-r--r--library/std/src/collections/hash/set.rs7
-rw-r--r--tests/ui/closures/issue-109188.rs22
-rw-r--r--tests/ui/closures/issue-109188.stderr19
-rw-r--r--tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs1
-rw-r--r--tests/ui/traits/new-solver/destruct.rs13
13 files changed, 121 insertions, 48 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index e0ddb90c33b..7534e432f11 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -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();
 
@@ -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()
@@ -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);
@@ -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 {
@@ -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 {
@@ -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);
             };
@@ -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
@@ -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,
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index d5d260d7138..eadc30a799b 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -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
             });
         }
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 9fe59a1d826..f8e9ec535e4 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -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() {
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index 8cb09108e83..995fec78c40 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -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> {
@@ -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)
         };
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 99885996652..525b3105538 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -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.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 2ebdfc8fe72..ade45d199f0 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -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> {
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index 7552f2fc04c..c7d0144de30 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -13,7 +13,6 @@ pub mod set;
 mod set_val;
 mod split;
 
-#[doc(hidden)]
 trait Recover<Q: ?Sized> {
     type Key;
 
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 4ddb2119252..4de30d40825 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -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};
@@ -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
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index b59f89d321c..837a18bff60 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -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
diff --git a/tests/ui/closures/issue-109188.rs b/tests/ui/closures/issue-109188.rs
new file mode 100644
index 00000000000..cae1ced9958
--- /dev/null
+++ b/tests/ui/closures/issue-109188.rs
@@ -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() { }
diff --git a/tests/ui/closures/issue-109188.stderr b/tests/ui/closures/issue-109188.stderr
new file mode 100644
index 00000000000..d52b516294f
--- /dev/null
+++ b/tests/ui/closures/issue-109188.stderr
@@ -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`.
diff --git a/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
index 3f7316a2279..4b013983a4a 100644
--- a/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
+++ b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Ztrait-solver=next
 // check-pass
 
 trait Mirror {
diff --git a/tests/ui/traits/new-solver/destruct.rs b/tests/ui/traits/new-solver/destruct.rs
new file mode 100644
index 00000000000..30d7777b78a
--- /dev/null
+++ b/tests/ui/traits/new-solver/destruct.rs
@@ -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);
+}