diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d2e3c00bb0c07..dc6bc0a8123e9 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -466,7 +466,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { let spans = sess.psess.gated_spans.spans.borrow(); macro_rules! gate_all { ($feature:ident, $explain:literal $(, $help:literal)?) => { - for &span in spans.get(&sym::$feature).into_iter().flatten() { + for &span in spans.get(&sym::$feature).into_flat_iter() { gate!(visitor, $feature, span, $explain $(, $help)?); } }; @@ -527,13 +527,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { ); // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. - for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() { + for &span in spans.get(&sym::associated_const_equality).into_flat_iter() { gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete"); } // `mgca_type_const_syntax` is part of `min_generic_const_args` so if // either or both are enabled we don't need to emit a feature error. - for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() { + for &span in spans.get(&sym::mgca_type_const_syntax).into_flat_iter() { if visitor.features.min_generic_const_args() || visitor.features.mgca_type_const_syntax() || span.allows_unstable(sym::min_generic_const_args) @@ -561,13 +561,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { // it does **not** mean "`T` doesn't implement `Bound` (positively or negatively)"! // The latter would be a SemVer hazard! if !sess.opts.unstable_opts.internal_testing_features || !visitor.features.negative_bounds() { - for &span in spans.get(&sym::negative_bounds).into_iter().flatten() { + for &span in spans.get(&sym::negative_bounds).into_flat_iter() { sess.dcx().emit_err(diagnostics::NegativeBoundUnsupported { span }); } } if !visitor.features.never_patterns() { - for &span in spans.get(&sym::never_patterns).into_iter().flatten() { + for &span in spans.get(&sym::never_patterns).into_flat_iter() { if span.allows_unstable(sym::never_patterns) { continue; } @@ -585,7 +585,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`. - for &span in spans.get(&sym::yield_expr).into_iter().flatten() { + for &span in spans.get(&sym::yield_expr).into_flat_iter() { if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) @@ -607,7 +607,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { macro_rules! soft_gate_all_legacy_dont_use { ($feature:ident, $explain:literal) => { - for &span in spans.get(&sym::$feature).into_iter().flatten() { + for &span in spans.get(&sym::$feature).into_flat_iter() { if !visitor.features.$feature() && !span.allows_unstable(sym::$feature) { feature_warn(&visitor.sess, sym::$feature, span, $explain); } @@ -625,7 +625,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); // tidy-alphabetical-end - for &span in spans.get(&sym::min_specialization).into_iter().flatten() { + for &span in spans.get(&sym::min_specialization).into_flat_iter() { if !visitor.features.specialization() && !visitor.features.min_specialization() && !span.allows_unstable(sym::specialization) diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 86ad758807584..918a623b41752 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -6,6 +6,7 @@ #![feature(deref_patterns)] #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] +#![feature(option_into_flat_iter)] // tidy-alphabetical-end pub mod ast_validation; diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs index 89cae4b7c55f1..38c1f9ab6c945 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs @@ -18,6 +18,8 @@ pub(crate) struct OnTypeErrorParser { impl OnTypeErrorParser { fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser, mode: Mode) { if !cx.features().diagnostic_on_type_error() { + // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs + args.ignore_args(); return; } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 42af99fc64d81..0bc06ade95ea1 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -476,9 +476,8 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { .borrow_set .local_map .get(&place.local) - .into_iter() - .flat_map(|bs| bs.iter()) - .copied(); + .map(|bs| bs.iter().copied()) + .into_flat_iter(); // If the borrowed place is a local with no projections, all other borrows of this // local must conflict. This is purely an optimization so we don't have to call diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 22e7d83e5b509..9d66863ef70e1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -7,6 +7,7 @@ #![feature(file_buffered)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 559b1bdc38d83..2808cbee99fb0 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -152,7 +152,7 @@ impl LocalizedConstraintGraph { // The physical edges present at this node are: // // 1. the typeck edges that flow from region to region *at this point*. - for &succ in self.edges.get(&node).into_iter().flatten() { + for &succ in self.edges.get(&node).into_flat_iter() { let succ = LocalizedNode { region: succ, point: node.point }; successor_found(succ); } @@ -229,7 +229,7 @@ impl LocalizedConstraintGraph { } // And finally, we have the logical edges, materialized at this point. - for &logical_succ in self.logical_edges.get(&node.region).into_iter().flatten() { + for &logical_succ in self.logical_edges.get(&node.region).into_flat_iter() { let succ = LocalizedNode { region: logical_succ, point: node.point }; successor_found(succ); } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs index db38879ea1d9b..e7e05e561d13f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs @@ -49,7 +49,7 @@ pub(super) fn apply_member_constraints<'tcx>( rcx.scc_values.add_region(scc_a, scc_b); } - for defining_use in member_constraints.get(&scc_a).into_iter().flatten() { + for defining_use in member_constraints.get(&scc_a).into_flat_iter() { apply_member_constraint(rcx, scc_a, &defining_use.arg_regions); } } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index e96dc44fab7c4..841e5713751cd 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -178,7 +178,7 @@ impl LivenessValues { /// Returns an iterator of all the points where `region` is live. fn live_points(&self, region: RegionVid) -> impl Iterator { - self.point_liveness(region).into_iter().flat_map(|set| set.iter()) + self.point_liveness(region).map(|set| set.iter()).into_flat_iter() } /// For debugging purposes, returns a pretty-printed string of the points where the `region` is @@ -348,13 +348,13 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> { pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator { self.points .row(r) - .into_iter() - .flat_map(move |set| set.iter().map(move |p| self.location_map.to_location(p))) + .map(move |set| set.iter().map(move |p| self.location_map.to_location(p))) + .into_flat_iter() } /// Returns just the universal regions that are contained in a given region's value. pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator { - self.free_regions.row(r).into_iter().flat_map(|set| set.iter()) + self.free_regions.row(r).map(|set| set.iter()).into_flat_iter() } /// Returns all the elements contained in a given region's value. @@ -364,8 +364,8 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> { ) -> impl Iterator> { self.placeholders .row(r) - .into_iter() - .flat_map(|set| set.iter()) + .map(|set| set.iter()) + .into_flat_iter() .map(move |p| self.placeholder_indices.lookup_placeholder(p)) } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 123bc1f568495..a0a2d1c135aa3 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -928,7 +928,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.super_local_decl(local, local_decl); for user_ty in - local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections) + local_decl.user_ty.as_deref().map(UserTypeProjections::projections).into_flat_iter() { let span = self.user_type_annotations[user_ty.base].span; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 24383eea3600f..c2b70e2ea5e42 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -597,27 +597,7 @@ impl<'b, 'tcx> PredicateEmittingRelation> for NllTypeRelating<'_ ); } - fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - self.register_predicates([ty::Binder::dummy(match self.ambient_variance { - ty::Covariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Subtype, - ), - // a :> b is b <: a - ty::Contravariant => ty::PredicateKind::AliasRelate( - b.into(), - a.into(), - ty::AliasRelationDirection::Subtype, - ), - ty::Invariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ), - ty::Bivariant => { - unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)") - } - })]); + fn ambient_variance(&self) -> ty::Variance { + self.ambient_variance } } diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 39123b8bade59..f34a7b956e040 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -90,8 +90,7 @@ impl<'tcx> AssertModuleSource<'tcx> { fn check_attrs(&mut self, attrs: &[hir::Attribute]) { for &(span, cgu_fields) in find_attr!(attrs, RustcCguTestAttr(e) => e) - .into_iter() - .flatten() + .into_flat_iter() { let (expected_reuse, comp_kind) = match cgu_fields { CguFields::PartitionReused { .. } => (CguReuse::PreLto, ComparisonKind::AtLeast), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c41f6f30a1da3..3d09b7aab8854 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1091,9 +1091,7 @@ fn link_natively( let get_objects = |objects: &CrtObjects, kind| { objects .get(&kind) - .iter() - .copied() - .flatten() + .into_flat_iter() .map(|obj| { get_object_file_path(sess, obj, self_contained_crt_objects).into_os_string() }) @@ -2073,7 +2071,7 @@ fn add_pre_link_objects( } else { &empty }; - for obj in objects.get(&link_output_kind).iter().copied().flatten() { + for obj in objects.get(&link_output_kind).into_flat_iter() { cmd.add_object(&get_object_file_path(sess, obj, self_contained)); } } @@ -2090,7 +2088,7 @@ fn add_post_link_objects( } else { &sess.target.post_link_objects }; - for obj in objects.get(&link_output_kind).iter().copied().flatten() { + for obj in objects.get(&link_output_kind).into_flat_iter() { cmd.add_object(&get_object_file_path(sess, obj, self_contained)); } } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f3f19f9e90d83..200f6aac12502 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,6 +2,7 @@ #![feature(deref_patterns)] #![feature(file_buffered)] #![feature(negative_impls)] +#![feature(option_into_flat_iter)] #![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index a47b3443ea664..0246da3f27829 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -718,6 +718,34 @@ impl<'a, 'tcx, V: CodegenObject> OperandRefBuilder<'tcx, V> { OperandRefBuilder { val, layout } } + /// Creates an initialized builder for updating an existing `operand`. + /// + /// ICEs for [`BackendRepr::Memory`] types (other than ZSTs), which use + /// which use [`OperandValue::Ref`]. In this case, updates should be + /// performed by writing into the place + pub(super) fn from_existing(operand: OperandRef<'tcx, V>) -> Self { + let layout = operand.layout; + let val = match (operand.val, layout.backend_repr) { + (OperandValue::ZeroSized, _) => OperandValueBuilder::ZeroSized, + (OperandValue::Immediate(v), BackendRepr::Scalar(_)) => { + OperandValueBuilder::Immediate(Either::Left(v)) + } + (OperandValue::Immediate(v), BackendRepr::SimdVector { .. }) => { + OperandValueBuilder::Vector(Either::Left(v)) + } + (OperandValue::Pair(a, b), BackendRepr::ScalarPair(_, _)) => { + OperandValueBuilder::Pair(Either::Left(a), Either::Left(b)) + } + (_, BackendRepr::Memory { .. }) => { + bug!("Cannot use non-ZST Memory-ABI type in operand builder: {layout:?}"); + } + _ => { + bug!("Operand cannot be used with `from_existing`: {operand:?}") + } + }; + OperandRefBuilder { val, layout } + } + pub(super) fn insert_field>( &mut self, bx: &mut Bx, @@ -829,6 +857,27 @@ impl<'a, 'tcx, V: CodegenObject> OperandRefBuilder<'tcx, V> { } } + /// Replaces the current immediate value at the offset `offset` + /// with the value `imm`. A value must already be present. + /// + /// This is used along with [`Self::from_existing`] to perform in-place updates + /// of any operand. + pub(super) fn update_imm(&mut self, offset: Size, imm: V) { + let is_zero_offset = offset == Size::ZERO; + match &mut self.val { + OperandValueBuilder::Immediate(val @ Either::Left(_)) if is_zero_offset => { + *val = Either::Left(imm); + } + OperandValueBuilder::Pair(fst @ Either::Left(_), _) if is_zero_offset => { + *fst = Either::Left(imm); + } + OperandValueBuilder::Pair(_, snd @ Either::Left(_)) if !is_zero_offset => { + *snd = Either::Left(imm); + } + _ => bug!("Tried to update {imm:?} at offset {offset:?} of {self:?}"), + } + } + /// After having set all necessary fields, this converts the builder back /// to the normal `OperandRef`. /// diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index b8bb926ead67d..3f839d7945afd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -4,19 +4,20 @@ //! of an assignment. The first step to retagging is to generate a [`RetagPlan`], which //! describes which pointers within the place or operand can be retagged. -#![allow(unused)] -use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, VariantIdx, Variants}; +use rustc_abi::{FieldIdx, FieldsShape, Size, VariantIdx, Variants}; use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::{Rvalue, WithRetag}; use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; -use crate::RetagInfo; use crate::mir::FunctionCx; -use crate::mir::operand::OperandRef; +use crate::mir::operand::{OperandRef, OperandRefBuilder, OperandValue}; use crate::mir::place::PlaceRef; -use crate::traits::BuilderMethods; +use crate::traits::{ + BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods, +}; +use crate::{RetagFlags, RetagInfo}; pub(crate) fn rvalue_needs_retag(rvalue: &Rvalue<'_>) -> bool { // `Ref` has its own internal retagging @@ -58,12 +59,6 @@ impl<'a, 'tcx, V> RetagPlan { if layout.is_sized() && layout.size < bx.tcx().data_layout.pointer_size() { return None; } - // SIMD vectors may only contain raw pointers, integers, and floating point values, - // which do not need to be retagged. - if matches!(layout.backend_repr, BackendRepr::SimdVector { .. }) { - return None; - } - // Check the type of this value to see what to do with it (retag, or recurse). match layout.ty.kind() { &ty::Ref(_, pointee, mt) => { @@ -168,12 +163,42 @@ impl<'a, 'tcx, V> RetagPlan { /// to types that are entirely covered by `UnsafePinned`, for which retags /// are a no-op. fn emit_retag>( - _bx: &mut Bx, - _pointee_layout: TyAndLayout<'tcx>, - _ptr_kind: Option, - _is_fn_entry: bool, + bx: &mut Bx, + pointee_layout: TyAndLayout<'tcx>, + ptr_kind: Option, + is_fn_entry: bool, ) -> Option> { - None + let tcx = bx.tcx(); + + let pointee_ty = pointee_layout.ty; + + let is_mutable = matches!(ptr_kind, Some(Mutability::Mut) | None); + let is_unpin = pointee_ty.is_unpin(tcx, bx.typing_env()); + let is_freeze = pointee_ty.is_freeze(tcx, bx.typing_env()); + let is_box = ptr_kind.is_none(); + + // `&mut !Unpin` is not protected + let is_protected = is_fn_entry && (!is_mutable || is_unpin); + + if is_mutable && !is_unpin { + return None; + } + + let im_layout = bx.const_null(bx.type_ptr()); + let pin_layout = bx.const_null(bx.type_ptr()); + + let mut flags = RetagFlags::empty(); + flags.set(RetagFlags::IS_PROTECTED, is_protected); + flags.set(RetagFlags::IS_MUTABLE, is_mutable); + flags.set(RetagFlags::IS_FREEZE, is_freeze); + flags.set(RetagFlags::IS_BOX, is_box); + + Some(RetagPlan::EmitRetag(RetagInfo { + size: pointee_layout.size, + im_layout, + pin_layout, + flags, + })) } } @@ -181,19 +206,158 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Retags the pointers within an [`OperandRef`]. pub(crate) fn codegen_retag_operand( &mut self, - _bx: &mut Bx, + bx: &mut Bx, operand: OperandRef<'tcx, Bx::Value>, - _is_fn_entry: bool, + is_fn_entry: bool, ) -> OperandRef<'tcx, Bx::Value> { + if let OperandValue::Ref(place_ref) = operand.val { + let place_ref = place_ref.with_type(operand.layout); + self.codegen_retag_place(bx, place_ref, is_fn_entry); + } else if let Some(plan) = RetagPlan::::build(bx, operand.layout, is_fn_entry) { + let mut builder = OperandRefBuilder::from_existing(operand); + self.retag_operand(bx, &plan, operand, &mut builder, Size::ZERO); + return builder.build(bx.cx()); + } operand } /// Retags the pointers within a [`PlaceRef`]. pub(crate) fn codegen_retag_place( &mut self, - _bx: &mut Bx, - _place_ref: PlaceRef<'tcx, Bx::Value>, - _is_fn_entry: bool, + bx: &mut Bx, + place_ref: PlaceRef<'tcx, Bx::Value>, + is_fn_entry: bool, ) { + if let Some(plan) = RetagPlan::::build(bx, place_ref.layout, is_fn_entry) { + self.retag_place(bx, &plan, place_ref); + } + } + + fn retag_operand( + &mut self, + bx: &mut Bx, + plan: &RetagPlan, + curr_operand: OperandRef<'tcx, Bx::Value>, + builder: &mut OperandRefBuilder<'tcx, Bx::Value>, + offset: Size, + ) { + match plan { + RetagPlan::EmitRetag(info) => { + let (pointer, _) = curr_operand.val.pointer_parts(); + let retagged_pointer = bx.retag_reg(pointer, info); + builder.update_imm(offset, retagged_pointer); + } + RetagPlan::Recurse { field_plans, variant_plans } => { + let layout = curr_operand.layout; + for (ix, plan) in field_plans { + let inner_offset = layout.fields.offset(ix.as_usize()); + let field_offset = offset + inner_offset; + + let field_layout = curr_operand.layout.field(bx, ix.index()); + // Part of https://github.com/rust-lang/compiler-team/issues/838 + if !bx.is_backend_ref(curr_operand.layout) && bx.is_backend_ref(field_layout) { + // FIXME: support vector types, requires insert_element as part of cg-ssa + } else { + let field_operand = curr_operand.extract_field(self, bx, ix.as_usize()); + self.retag_operand(bx, &plan, field_operand, builder, field_offset); + } + } + + if !variant_plans.is_empty() { + let discr_ty = layout.ty.discriminant_ty(bx.tcx()); + let discr_val = curr_operand.codegen_get_discr(self, bx, discr_ty); + + if let Some(val) = bx.const_to_opt_u128(discr_val, false) { + let ix = VariantIdx::from_usize(val as usize); + if let Some(plan) = variant_plans.get(&ix) { + let mut variant_op = curr_operand; + variant_op.layout = curr_operand.layout.for_variant(bx, ix); + + self.retag_operand(bx, plan, variant_op, builder, offset); + } + } else { + // We create a temporary place to store the operand, because its value will differ + // depending on the variant that we have. + let scratch = PlaceRef::alloca(bx, curr_operand.layout); + scratch.storage_live(bx); + curr_operand.store_with_annotation(bx, scratch); + + // We retag the contents of the place + self.retag_variants(bx, scratch, discr_val, variant_plans); + + // Afterward, we load the now-updated operand and end the lifetime of the place. + let updated_op = bx.load_operand(scratch); + scratch.storage_dead(bx); + + match updated_op.val { + OperandValue::ZeroSized | OperandValue::Ref(_) => {} + OperandValue::Immediate(imm) => builder.update_imm(offset, imm), + OperandValue::Pair(fst, snd) => { + builder.update_imm(offset, fst); + builder.update_imm(offset + Size::from_bytes(1), snd) + } + } + } + } + } + } + } + + fn retag_place( + &mut self, + bx: &mut Bx, + plan: &RetagPlan, + place: PlaceRef<'tcx, Bx::Value>, + ) { + match plan { + RetagPlan::EmitRetag(info) => { + bx.retag_mem(place.val.llval, info); + } + RetagPlan::Recurse { field_plans, variant_plans } => { + for (ix, plan) in field_plans { + let field_place = place.project_field(bx, ix.as_usize()); + self.retag_place(bx, &plan, field_place); + } + if !variant_plans.is_empty() { + let operand = bx.load_operand(place); + let discr_ty = place.layout.ty.discriminant_ty(bx.tcx()); + let discr_val = operand.codegen_get_discr(self, bx, discr_ty); + self.retag_variants(bx, place, discr_val, variant_plans); + } + } + } + } + + /// Retags each variant of a [`PlaceRef`] with the given discriminant. + fn retag_variants( + &mut self, + bx: &mut Bx, + place: PlaceRef<'tcx, Bx::Value>, + discr: Bx::Value, + variant_plans: &FxIndexMap>, + ) { + let layout = place.layout; + + let root_block = bx.llbb(); + let mut variant_blocks = Vec::with_capacity(variant_plans.len()); + let join_block = bx.append_sibling_block("retag_join"); + + for (ix, plan) in variant_plans { + let variant_discr = layout.ty.discriminant_for_variant(bx.tcx(), *ix); + let variant_discr_val = variant_discr.expect("Invalid variant index.").val; + + let variant_block = bx.append_sibling_block("retag_variant"); + bx.switch_to_block(variant_block); + + let variant_place = place.project_downcast(bx, *ix); + self.retag_place(bx, plan, variant_place); + + variant_blocks.push((variant_discr_val, variant_block)); + bx.br(join_block); + } + + bx.switch_to_block(root_block); + bx.switch(discr, join_block, variant_blocks.into_iter()); + bx.switch_to_block(join_block); } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 821f541170f62..ee516991cfbfc 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -503,39 +503,27 @@ pub trait MacResult { } } -macro_rules! make_MacEager { - ( $( $fld:ident: $t:ty, )* ) => { - /// `MacResult` implementation for the common case where you've already - /// built each form of AST that you might return. - #[derive(Default)] - pub struct MacEager { - $( - pub $fld: Option<$t>, - )* - } +/// `MacResult` implementation for the common case where you've already +/// built each form of AST that you might return. +#[derive(Default)] +pub struct MacEager { + pub expr: Option>, + pub items: Option; 1]>>, + pub ty: Option>, +} - impl MacEager { - $( - pub fn $fld(v: $t) -> Box { - Box::new(MacEager { - $fld: Some(v), - ..Default::default() - }) - } - )* - } +impl MacEager { + pub fn expr(v: Box) -> Box { + Box::new(MacEager { expr: Some(v), ..Default::default() }) + } + + pub fn items(v: SmallVec<[Box; 1]>) -> Box { + Box::new(MacEager { items: Some(v), ..Default::default() }) } -} -make_MacEager! { - expr: Box, - pat: Box, - items: SmallVec<[Box; 1]>, - impl_items: SmallVec<[Box; 1]>, - trait_items: SmallVec<[Box; 1]>, - foreign_items: SmallVec<[Box; 1]>, - stmts: SmallVec<[ast::Stmt; 1]>, - ty: Box, + pub fn ty(v: Box) -> Box { + Box::new(MacEager { ty: Some(v), ..Default::default() }) + } } impl MacResult for MacEager { @@ -547,34 +535,7 @@ impl MacResult for MacEager { self.items } - fn make_impl_items(self: Box) -> Option; 1]>> { - self.impl_items - } - - fn make_trait_impl_items(self: Box) -> Option; 1]>> { - self.impl_items - } - - fn make_trait_items(self: Box) -> Option; 1]>> { - self.trait_items - } - - fn make_foreign_items(self: Box) -> Option; 1]>> { - self.foreign_items - } - - fn make_stmts(self: Box) -> Option> { - if self.stmts.as_ref().is_none_or(|s| s.is_empty()) { - make_stmts_default(self.make_expr()) - } else { - self.stmts - } - } - fn make_pat(self: Box) -> Option> { - if let Some(p) = self.pat { - return Some(p); - } if let Some(e) = self.expr { if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) { return Some(Box::new(ast::Pat { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 9d8e0a512ab66..f0c5f6b85423c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -479,10 +479,9 @@ fn fn_sig_suggestion<'tcx>( } } }; - Some(format!("{splat}{arg_ty}")) + format!("{splat}{arg_ty}") }) - .chain(std::iter::once(if sig.c_variadic() { Some("...".to_string()) } else { None })) - .flatten() + .chain(if sig.c_variadic() { Some("...".to_string()) } else { None }) .collect::>() .join(", "); let mut output = sig.output(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1d17621be217f..f2a6c2747f380 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1217,7 +1217,7 @@ fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { // does the function have an EiiImpl attribute? that contains the defid of a *macro* // that was used to mark the implementation. This is a two step process. for EiiImpl { resolution, span, .. } in - find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten() + find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() { let (foreign_item, name) = match resolution { EiiImplResolution::Macro(def_id) => { @@ -1244,7 +1244,7 @@ fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) // does the function have an EiiImpl attribute? that contains the defid of a *macro* // that was used to mark the implementation. This is a two step process. for EiiImpl { resolution, span, .. } in - find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten() + find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() { let (foreign_item, name) = match resolution { EiiImplResolution::Macro(def_id) => { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 9d22d3060e1ff..b9495c8519fa2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -984,15 +984,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { // `::Item = String`. let projection_term = pred.projection_term; - let quiet_projection_term = projection_term - .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO)); - let term = pred.term; + let self_ty = projection_term.args.get(0).and_then(|arg| arg.as_type())?; + let obligation = format!("{projection_term} = {term}"); + let quiet_projection_term = projection_term + .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO)); let quiet = format!("{quiet_projection_term} = {term}"); - bound_span_label(projection_term.self_ty(), &obligation, &quiet); - Some((obligation, projection_term.self_ty())) + bound_span_label(self_ty, &obligation, &quiet); + + Some(obligation) } ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => { let p = poly_trait_ref.trait_ref; @@ -1001,7 +1003,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let obligation = format!("{self_ty}: {path}"); let quiet = format!("_: {path}"); bound_span_label(self_ty, &obligation, &quiet); - Some((obligation, self_ty)) + Some(obligation) } _ => None, } @@ -1013,7 +1015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into_iter() .map(|error| error.root_obligation.predicate) .filter_map(format_pred) - .map(|(p, _)| format!("`{p}`")) + .map(|p| format!("`{p}`")) .collect(); bounds.sort(); bounds.dedup(); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index ff00e18783706..a6f55eb8dea72 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -60,6 +60,7 @@ This API is completely unstable and subject to change. #![feature(gen_blocks)] #![feature(iter_intersperse)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] #![feature(unwrap_infallible)] diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f7a58d278a519..2ecbb8863bf91 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -673,7 +673,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut coercion = self.unify_and( coerce_target, target, - reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]), + reborrow.map(|(deref, autoref)| [deref, autoref]).into_flat_iter(), Adjust::Pointer(PointerCoercion::Unsize), ForceLeakCheck::No, )?; @@ -737,19 +737,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { { self.resolve_vars_if_possible(trait_pred) } - // Eagerly process alias-relate obligations in new trait solver, - // since these can be emitted in the process of solving trait goals, - // but we need to constrain vars before processing goals mentioning - // them. - Some(ty::PredicateKind::AliasRelate(..)) => { - let ocx = ObligationCtxt::new(self); - ocx.register_obligation(obligation); - if !ocx.try_evaluate_obligations().is_empty() { - return Err(TypeError::Mismatch); - } - coercion.obligations.extend(ocx.into_pending_obligations()); - continue; - } _ => { coercion.obligations.push(obligation); continue; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 8142b6ad57f3f..04b095dc8c92c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -55,7 +55,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) | ty::PredicateKind::DynCompatible(..) | ty::PredicateKind::NormalizesTo(..) - | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 3b3f5caa85c09..335caf571aa6f 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -3,6 +3,7 @@ #![feature(iter_intersperse)] #![feature(iter_order_by)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(option_reference_flattening)] #![feature(trim_prefix_suffix)] // tidy-alphabetical-end diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e7116b7492584..0a72f1d47b8b8 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // NOTE: Reporting a method error should also suppress any unused trait errors, // since the method error is very possibly the reason why the trait wasn't used. for &import_id in - self.tcx.in_scope_traits(call_id).into_iter().flatten().flat_map(|c| c.import_ids) + self.tcx.in_scope_traits(call_id).into_flat_iter().flat_map(|c| c.import_ids) { self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 7881b85997e8c..ee6e13250e709 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, + self, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, }; use rustc_span::Span; use tracing::{debug, instrument, warn}; @@ -168,25 +168,61 @@ impl<'tcx> InferCtxt<'tcx> { // cyclic type. We instead delay the unification in case // the alias can be normalized to something which does not // mention `?0`. + let Some(source_alias) = source_term.to_alias_term() else { + bug!("generalized `{source_term:?} to infer, not an alias"); + }; if self.next_trait_solver() { - let (lhs, rhs, direction) = match instantiation_variance { - ty::Invariant => { - (generalized_term, source_term, AliasRelationDirection::Equate) - } - ty::Covariant => { - (generalized_term, source_term, AliasRelationDirection::Subtype) - } - ty::Contravariant => { - (source_term, generalized_term, AliasRelationDirection::Subtype) + if let Some(generalized_ty) = generalized_term.as_type() { + match instantiation_variance { + ty::Invariant => relation.register_predicates([ty::ProjectionPredicate { + projection_term: source_alias.into(), + term: generalized_ty.into(), + }]), + ty::Covariant => { + // Generate a new var, then do: + // `source_alias == ?A && ?A <: generalized_ty` + let new_var = self.next_ty_var(relation.span()); + relation.register_predicates([ + ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: !target_is_expected, + a: new_var, + b: generalized_ty, + }), + ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { + projection_term: source_alias.into(), + term: new_var.into(), + }, + )), + ]); + } + ty::Contravariant => { + // a :> b is b <: a + let new_var = self.next_ty_var(relation.span()); + relation.register_predicates([ + ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: target_is_expected, + a: generalized_ty, + b: new_var, + }), + ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { + projection_term: source_alias.into(), + term: new_var.into(), + }, + )), + ]); + } + ty::Bivariant => unreachable!("bivariant generalization"), } - ty::Bivariant => unreachable!("bivariant generalization"), - }; - - relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]); + } else { + debug_assert_eq!(instantiation_variance, ty::Variance::Invariant); + relation.register_predicates([ty::ProjectionPredicate { + projection_term: source_alias, + term: generalized_term, + }]); + } } else { - let Some(source_alias) = source_term.to_alias_term() else { - bug!("generalized `{source_term:?} to infer, not an alias"); - }; match source_alias.kind { ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 2c14a7d44e8c6..0ae7842a9d593 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -291,12 +291,8 @@ impl<'tcx> PredicateEmittingRelation> for LatticeOp<'_, 'tcx> { })) } - fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - // FIXME(deferred_projection_equality): This isn't right, I think? - ty::AliasRelationDirection::Equate, - ))]); + fn ambient_variance(&self) -> ty::Variance { + // FIXME(deferred_projection_equality): This isn't right, I think? + ty::Variance::Invariant } } diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index d5e98f262db39..2e3a50ac953e7 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -384,27 +384,7 @@ impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, 'tcx> })) } - fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { - self.register_predicates([ty::Binder::dummy(match self.ambient_variance { - ty::Covariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Subtype, - ), - // a :> b is b <: a - ty::Contravariant => ty::PredicateKind::AliasRelate( - b.into(), - a.into(), - ty::AliasRelationDirection::Subtype, - ), - ty::Invariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ), - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - })]); + fn ambient_variance(&self) -> ty::Variance { + self.ambient_variance } } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 97b7cdc135142..60ee55e299d87 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -349,8 +349,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { closing_brackets .empty_alt .then_some(" _ => {}".chars()) - .into_iter() - .flatten() + .into_flat_iter() .chain(repeat_n('}', closing_brackets.count)) .collect(), )); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 0e96b9f118790..eaf9360cc3358 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -23,6 +23,7 @@ #![allow(internal_features)] #![feature(deref_patterns)] #![feature(iter_order_by)] +#![feature(option_into_flat_iter)] #![feature(rustc_attrs)] #![feature(titlecase)] #![feature(try_blocks)] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a12e347284f7c..58599db734c49 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -793,7 +793,7 @@ fn get_nullable_type<'tcx>( return get_nullable_type(tcx, typing_env, inner_field_ty); } ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base), - ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty, + ty::Int(_) | ty::Uint(_) | ty::Char | ty::RawPtr(..) => ty, // As these types are always non-null, the nullable equivalent of // `Option` of these types are their raw pointer counterparts. ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), @@ -895,10 +895,14 @@ pub(crate) fn repr_nullable_ptr<'tcx>( WrappingRange { start: 0, end } if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).expect( + "known non-null scalar type should have a nullable representation", + )); } WrappingRange { start: 1, .. } => { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).expect( + "known non-null scalar type should have a nullable representation", + )); } WrappingRange { start, end } => { unreachable!("Unhandled start and end range: ({}, {})", start, end) diff --git a/compiler/rustc_metadata/src/eii.rs b/compiler/rustc_metadata/src/eii.rs index f3ce07aa75a11..11ea4cc492921 100644 --- a/compiler/rustc_metadata/src/eii.rs +++ b/compiler/rustc_metadata/src/eii.rs @@ -25,7 +25,7 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap // iterate over all items in the current crate for id in tcx.hir_crate_items(()).eiis() { - for i in find_attr!(tcx, id, EiiImpls(e) => e).into_iter().flatten() { + for i in find_attr!(tcx, id, EiiImpls(e) => e).into_flat_iter() { let decl = match i.resolution { EiiImplResolution::Macro(macro_defid) => { // find the decl for this one if it wasn't in yet (maybe it's from the local crate? not very useful but not illegal) diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 840b1c4c6fa2f..9ef9422a9e5a0 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -8,6 +8,7 @@ #![feature(macro_metavar_expr)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(proc_macro_internals)] #![feature(trusted_len)] // tidy-alphabetical-end diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 874d4812502e6..f970be089f2ee 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -325,9 +325,8 @@ impl<'a> CrateLocator<'a> { sess.opts .externs .get(crate_name.as_str()) - .into_iter() - .filter_map(|entry| entry.files()) - .flatten() + .and_then(|entry| entry.files()) + .into_flat_iter() .cloned() .collect() } else { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index c9e4ce60e1a01..b2cfc2f079e89 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -248,9 +248,7 @@ impl<'tcx> Collector<'tcx> { return; } - for attr in - find_attr!(self.tcx, def_id, Link(links, _) => links).iter().map(|v| v.iter()).flatten() - { + for attr in find_attr!(self.tcx, def_id, Link(links, _) => links).into_flat_iter() { let dll_imports = match attr.kind { NativeLibKind::RawDylib { .. } => foreign_items .iter() diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index bd3b2445759e7..bed2be51a3468 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -2038,10 +2038,12 @@ impl CrateMetadata { krate: CrateNum, ) -> impl Iterator { gen move { - for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| { - data.macros.decode((self, tcx)).map(move |(index, _)| DefId { index, krate }) - }) { - yield def_id; + if let Some(data) = &self.root.proc_macro_data { + for def_id in + data.macros.decode((self, tcx)).map(move |(index, _)| DefId { index, krate }) + { + yield def_id; + } } } } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 3ab2690c7a6f4..da7ad32ae9dc0 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -46,6 +46,7 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(ptr_alignment_type)] #![feature(range_bounds_is_empty)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 44c5e66279c14..e2a9bbd2960b6 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -18,7 +18,7 @@ use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; /// Represents the result of const evaluation via the `eval_to_allocation` query. /// Not to be confused with `ConstAllocation`, which directly refers to the underlying data! /// Here we indirect via an `AllocId`. -#[derive(Copy, Clone, StableHash, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)] +#[derive(Copy, Clone, StableHash, TyEncodable, TyDecodable, Debug, Eq, PartialEq)] pub struct ConstAlloc<'tcx> { /// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory` /// (so you can use `AllocMap::unwrap_memory`). diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index cdb373cf01de5..828868057c294 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -70,7 +70,7 @@ impl Debug for CovTerm { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash)] pub enum CoverageKind { /// Marks a span that might otherwise not be represented in MIR, so that /// coverage instrumentation can associate it with its enclosing block/BCB. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1d809a2c84ca0..ce30b3fae47ae 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1558,7 +1558,7 @@ impl UserTypeProjections { /// * `let (x, _): T = ...` -- here, the `projs` vector would contain /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. -#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] #[derive(TypeFoldable, TypeVisitable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 91ff3f52390e1..5e2ef47f9076d 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -300,7 +300,7 @@ pub enum FakeBorrowKind { /// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which /// ones you do not have to worry about. The MIR validator will generally enforce such restrictions, /// causing an ICE if they are violated. -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum StatementKind<'tcx> { /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except @@ -455,17 +455,8 @@ pub enum StatementKind<'tcx> { }, } -#[derive( - Clone, - TyEncodable, - TyDecodable, - Debug, - PartialEq, - Hash, - StableHash, - TypeFoldable, - TypeVisitable -)] +#[derive(Clone, TyEncodable, TyDecodable, Debug, PartialEq, StableHash)] +#[derive(TypeFoldable, TypeVisitable)] pub enum NonDivergingIntrinsic<'tcx> { /// Denotes a call to the intrinsic function `assume`. /// @@ -492,7 +483,7 @@ pub enum NonDivergingIntrinsic<'tcx> { } /// Describes whether this operand use performs a retag. -#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, StableHash)] +#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, StableHash)] #[rustc_pass_by_value] pub enum WithRetag { Yes, @@ -511,7 +502,7 @@ impl WithRetag { } /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. -#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, StableHash, PartialEq)] +#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, StableHash, PartialEq)] pub enum FakeReadCause { /// A fake read injected into a match guard to ensure that the discriminants /// that are being matched on aren't modified while the match guard is being @@ -617,7 +608,7 @@ pub enum FakeReadCause { ForIndex, } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub struct CopyNonOverlapping<'tcx> { pub src: Operand<'tcx>, @@ -628,7 +619,7 @@ pub struct CopyNonOverlapping<'tcx> { /// Represents how a [`TerminatorKind::Call`] was constructed. /// Used only for diagnostics. -#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, StableHash)] +#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum CallSource { /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` @@ -648,7 +639,7 @@ pub enum CallSource { Normal, } -#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] #[derive(TypeFoldable, TypeVisitable)] /// The macro that an inline assembly block was created by pub enum InlineAsmMacro { @@ -688,7 +679,7 @@ pub enum InlineAsmMacro { /// deleting self edges and duplicate edges in the process. Now remove all vertices from `G` /// that are not cleanup vertices or are not reachable. The resulting graph must be an inverted /// tree, that is each vertex may have at most one successor and there may be no cycles. -#[derive(Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq, TypeFoldable, TypeVisitable)] +#[derive(Clone, TyEncodable, TyDecodable, StableHash, PartialEq, TypeFoldable, TypeVisitable)] pub enum TerminatorKind<'tcx> { /// Block has one successor; we continue execution there. Goto { target: BasicBlock }, @@ -973,22 +964,13 @@ pub enum TerminatorKind<'tcx> { }, } -#[derive( - Clone, - Debug, - TyEncodable, - TyDecodable, - Hash, - StableHash, - PartialEq, - TypeFoldable, - TypeVisitable -)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] pub enum BackwardIncompatibleDropReason { Edition2024, } -#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] +#[derive(Debug, Clone, TyEncodable, TyDecodable, StableHash, PartialEq)] pub struct SwitchTargets { /// Possible values. For each value, the location to branch to is found in /// the corresponding element in the `targets` vector. @@ -1018,7 +1000,7 @@ pub struct SwitchTargets { } /// Action to be taken when a stack unwind happens. -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UnwindAction { /// No action is to be taken. Continue unwinding. @@ -1037,7 +1019,7 @@ pub enum UnwindAction { } /// The reason we are terminating the process during unwinding. -#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UnwindTerminateReason { /// Unwinding is just not possible given the ABI of this function. @@ -1048,7 +1030,7 @@ pub enum UnwindTerminateReason { } /// Information about an assertion failure. -#[derive(Clone, Hash, StableHash, PartialEq, Debug)] +#[derive(Clone, StableHash, PartialEq, Debug)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum AssertKind { BoundsCheck { len: O, index: O }, @@ -1064,7 +1046,7 @@ pub enum AssertKind { InvalidEnumConstruction(O), } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum InlineAsmOperand<'tcx> { In { @@ -1292,7 +1274,7 @@ pub type PlaceElem<'tcx> = ProjectionElem>; /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri /// currently implements it, but it seems like this may be something to check against in the /// validator. -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash, TypeFoldable, TypeVisitable)] pub enum Operand<'tcx> { /// Creates a value by loading the given place. /// @@ -1327,7 +1309,7 @@ pub enum Operand<'tcx> { RuntimeChecks(RuntimeChecks), } -#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub struct ConstOperand<'tcx> { pub span: Span, @@ -1352,7 +1334,7 @@ pub struct ConstOperand<'tcx> { /// Computing any rvalue begins by evaluating the places and operands in some order (**Needs /// clarification**: Which order?). These are then used to produce a "value" - the same kind of /// value that an [`Operand`] produces. -#[derive(Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq, TypeFoldable, TypeVisitable)] +#[derive(Clone, TyEncodable, TyDecodable, StableHash, PartialEq, TypeFoldable, TypeVisitable)] pub enum Rvalue<'tcx> { /// Yields the operand unchanged, except for a potential retag. Use(Operand<'tcx>, WithRetag), @@ -1534,7 +1516,7 @@ pub enum CoercionSource { Implicit, } -#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] +#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] #[derive(TypeFoldable, TypeVisitable)] pub enum AggregateKind<'tcx> { /// The type is of the element @@ -1703,7 +1685,7 @@ pub enum BinOp { // Assignment operators, e.g. `+=`. See comments on the corresponding variants // in `BinOp` for details. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, StableHash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, StableHash)] pub enum AssignOp { AddAssign, SubAssign, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6852c952658e7..03d13e6a81a6e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3269,11 +3269,6 @@ define_print! { } ty::PredicateKind::Ambiguous => write!(p, "ambiguous")?, ty::PredicateKind::NormalizesTo(data) => data.print(p)?, - ty::PredicateKind::AliasRelate(t1, t2, dir) => { - t1.print(p)?; - write!(p, " {dir} ")?; - t2.print(p)?; - } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0042c87c3eda7..ad3b8e009320d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -769,25 +769,22 @@ impl<'tcx> Ty<'tcx> { .projection_bounds() .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) .count(); - let expected_count: usize = obj - .principal_def_id() - .into_iter() - .flat_map(|principal_def_id| { - // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! - elaborate::supertraits( - tcx, - ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), - ) - .map(|principal| { - tcx.associated_items(principal.def_id()) - .in_definition_order() - .filter(|item| item.is_type() || item.is_type_const()) - .filter(|item| !item.is_impl_trait_in_trait()) - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .count() - }) + let expected_count: usize = obj.principal_def_id().map_or(0, |principal_def_id| { + // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! + elaborate::supertraits( + tcx, + ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), + ) + .map(|principal| { + tcx.associated_items(principal.def_id()) + .in_definition_order() + .filter(|item| item.is_type() || item.is_type_const()) + .filter(|item| !item.is_impl_trait_in_trait()) + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) + .count() }) - .sum(); + .sum() + }); assert_eq!( projection_count, expected_count, "expected {obj:?} to have {expected_count} projections, \ diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 77820beef0228..65a713602ed07 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -537,8 +537,8 @@ impl<'tcx> TypeckResults<'tcx> { ) -> impl Iterator> { self.closure_min_captures .get(&closure_def_id) - .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter())) - .into_iter() + .map(|closure_min_captures| closure_min_captures.values()) + .into_flat_iter() .flatten() } diff --git a/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs b/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs index 4c20722a04347..616d24d87b719 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs @@ -126,6 +126,6 @@ where sink_edge = self.sink_edge_nodes.contains(node).then_some(self.sink); } - real_edges.into_iter().flatten().chain(sink_edge) + real_edges.into_flat_iter().chain(sink_edge) } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index edf0dcca775ca..2bb14589db36a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -4,6 +4,7 @@ #![feature(deref_patterns)] #![feature(impl_trait_in_assoc_type)] #![feature(iterator_try_collect)] +#![feature(option_into_flat_iter)] #![feature(try_blocks)] #![feature(yeet_expr)] // tidy-alphabetical-end diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 80b4d3be172ef..b2f6ac78040b6 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -100,7 +100,6 @@ pub(super) fn instantiate_and_apply_query_response( param_env: I::ParamEnv, original_values: &[I::GenericArg], response: CanonicalResponse, - visible_for_leak_check: VisibleForLeakCheck, span: I::Span, ) -> (NestedNormalizationGoals, Certainty) where @@ -121,7 +120,15 @@ where match region_constraints { ExternalRegionConstraints::Old(r) => register_region_constraints( delegate, - r.iter().map(|(c, vis)| (*c, vis.and(visible_for_leak_check))), + r.iter().map(|(c, vis)| { + // FIXME: We should revisit and consider removing this after *assumptions on + // binders* is available, like once we had done in the stabilization of + // `-Znext-solver=coherence`(#121848). + // We ignore constraints from the nested goals in leak check. This is to match with + // the old solver's behavior, which has separated evaluation and fulfillment, and + // the former doesn't consider outlives obligations from the later. + (*c, vis.and(VisibleForLeakCheck::No)) + }), span, ), ExternalRegionConstraints::NextGen(r) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs deleted file mode 100644 index 9d94a2b5ac520..0000000000000 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Implements the `AliasRelate` goal, which is used when unifying aliases. -//! Doing this via a separate goal is called "deferred alias relation" and part -//! of our more general approach to "lazy normalization". -//! -//! This is done by first structurally normalizing both sides of the goal, ending -//! up in either a concrete type, rigid alias, or an infer variable. -//! These are related further according to the rules below: -//! -//! (1.) If we end up with two rigid aliases, then we relate them structurally. -//! -//! (2.) If we end up with an infer var and a rigid alias, then we instantiate -//! the infer var with the constructor of the alias and then recursively relate -//! the terms. -//! -//! (3.) Otherwise, if we end with two rigid (non-projection) or infer types, -//! relate them structurally. - -use rustc_type_ir::inherent::*; -use rustc_type_ir::solve::{GoalSource, QueryResultOrRerunNonErased}; -use rustc_type_ir::{self as ty, Interner}; -use tracing::{instrument, trace}; - -use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal}; - -impl EvalCtxt<'_, D> -where - D: SolverDelegate, - I: Interner, -{ - #[instrument(level = "trace", skip(self), ret)] - pub(super) fn compute_alias_relate_goal( - &mut self, - goal: Goal, - ) -> QueryResultOrRerunNonErased { - let cx = self.cx(); - let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; - - // Check that the alias-relate goal is reasonable. Writeback for - // `coroutine_stalled_predicates` can replace alias terms with - // `{type error}` if the alias still contains infer vars, so we also - // accept alias-relate goals where one of the terms is an error. - debug_assert!( - lhs.to_alias_term().is_some() - || rhs.to_alias_term().is_some() - || lhs.is_error() - || rhs.is_error() - ); - - // Structurally normalize the lhs. - let lhs = if let Some(alias) = lhs.to_alias_term() { - let term = self.next_term_infer_of_alias_kind(alias); - self.add_goal( - GoalSource::TypeRelating, - goal.with(cx, ty::ProjectionPredicate { projection_term: alias, term }), - )?; - term - } else { - lhs - }; - - // Structurally normalize the rhs. - let rhs = if let Some(alias) = rhs.to_alias_term() { - let term = self.next_term_infer_of_alias_kind(alias); - self.add_goal( - GoalSource::TypeRelating, - goal.with(cx, ty::ProjectionPredicate { projection_term: alias, term }), - )?; - term - } else { - rhs - }; - - // Add a `make_canonical_response` probe step so that we treat this as - // a candidate, even if `try_evaluate_added_goals` bails due to an error. - // It's `Certainty::AMBIGUOUS` because this candidate is not "finished", - // since equating the normalized terms will lead to additional constraints. - self.inspect.make_canonical_response(Certainty::AMBIGUOUS); - - // Apply the constraints. - self.try_evaluate_added_goals()?; - let lhs = self.resolve_vars_if_possible(lhs); - let rhs = self.resolve_vars_if_possible(rhs); - trace!(?lhs, ?rhs); - - let variance = match direction { - ty::AliasRelationDirection::Equate => ty::Invariant, - ty::AliasRelationDirection::Subtype => ty::Covariant, - }; - self.relate(param_env, lhs, variance, rhs)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } -} diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 5e1d202f8f994..20f384c1436c0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -733,29 +733,11 @@ where let has_changed = if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; - // FIXME: We should revisit and consider removing this after - // *assumptions on binders* is available, like once we had done in the - // stabilization of `-Znext-solver=coherence`(#121848). - // We ignore constraints from the nested goals in leak check. This is to match - // with the old solver's behavior, which has separated evaluation and fulfillment, - // and the former doesn't consider outlives obligations from the later. - let vis = match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(_) - | ty::PredicateKind::DynCompatible(_) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::NormalizesTo(_) => VisibleForLeakCheck::No, - ty::PredicateKind::AliasRelate(_, _, _) => VisibleForLeakCheck::Yes, - }; - let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response( self.delegate, goal.param_env, &orig_values, response, - vis, self.origin_span, ); @@ -965,11 +947,6 @@ where ty::PredicateKind::NormalizesTo(predicate) => { ecx.compute_normalizes_to_goal(Goal { param_env, predicate })? } - ty::PredicateKind::AliasRelate(lhs, rhs, direction) => ecx - .compute_alias_relate_goal(Goal { - param_env, - predicate: (lhs, rhs, direction), - })?, ty::PredicateKind::Ambiguous => { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)? } @@ -1276,7 +1253,8 @@ where let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { + ty::PredicateKind::Subtype { .. } + | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { GoalSource::TypeRelating } // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive? @@ -1814,7 +1792,6 @@ pub(super) fn evaluate_root_goal_for_proof_tree, goal.param_env, &proof_tree.orig_values, response, - VisibleForLeakCheck::Yes, origin_span, ); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 8b838f3567c84..fcf8ddf59fe3c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -11,7 +11,6 @@ //! For a high-level overview of how this solver works, check out the relevant //! section of the rustc-dev-guide. -mod alias_relate; mod assembly; mod effect_goals; mod eval_ctxt; diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index 3427044915f88..bf25617df6573 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -82,7 +82,7 @@ where }, |ecx| { ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| { - this.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + this.instantiate_normalizes_to_as_rigid(goal)?; this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) }, @@ -111,13 +111,9 @@ where Ok(()) } - /// When normalizing an associated item, constrain the expected term to `term`. + /// When normalizing an associated item, constrain the expected term to `value`. /// - /// We know `term` to always be a fully unconstrained inference variable, so - /// `eq` should never fail here. However, in case `term` contains aliases, we - /// emit nested `AliasRelate` goals to structurally normalize the alias. - /// - /// Additionally, when `term` is a const, this registers a `ConstArgHasType` + /// Additionally, when `value` is a const, this registers a `ConstArgHasType` /// goal to ensure that the const value's type matches the declared type of /// the alias it was normalized from. /// @@ -140,28 +136,25 @@ where fn instantiate_normalizes_to_term( &mut self, goal: Goal>, - term: I::Term, + value: I::Term, ) -> Result<(), NoSolutionOrRerunNonErased> { - self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, term)?; - self.eq(goal.param_env, goal.predicate.term, term) - .expect("expected goal term to be fully unconstrained"); + self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, value)?; + // While `goal.predicate.term` should always be a fully unconstrained inference variable, + // `eq` can still fail if `value` is not fully normalized, due to `eq` eagerly normalizing, + // and that normalization can fail. + self.eq(goal.param_env, goal.predicate.term, value)?; Ok(()) } - /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term - /// with a rigid alias. Using this is pretty much always wrong. - fn structurally_instantiate_normalizes_to_term( + fn instantiate_normalizes_to_as_rigid( &mut self, goal: Goal>, - term: ty::AliasTerm, - ) { - self.relate( + ) -> Result<(), NoSolutionOrRerunNonErased> { + self.eq( goal.param_env, - term.to_term(self.cx(), ty::IsRigid::Yes), - ty::Invariant, goal.predicate.term, + goal.predicate.alias.to_term(self.cx(), ty::IsRigid::Yes), ) - .expect("expected goal term to be fully unconstrained"); } } @@ -356,10 +349,7 @@ where | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => { - ecx.structurally_instantiate_normalizes_to_term( - goal, - goal.predicate.alias, - ); + ecx.instantiate_normalizes_to_as_rigid(goal)?; return ecx.evaluate_added_goals_and_make_canonical_response( Certainty::Yes, ); @@ -394,7 +384,7 @@ where ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?; return then(ecx, Certainty::Yes); } else { - ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + ecx.instantiate_normalizes_to_as_rigid(goal)?; return then(ecx, Certainty::Yes); } } else { @@ -767,10 +757,7 @@ where // as rigid. return alias_bound_result.or_else(|NoSolution| { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| { - this.structurally_instantiate_normalizes_to_term( - goal, - goal.predicate.alias, - ); + this.instantiate_normalizes_to_as_rigid(goal)?; this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) }); @@ -1026,7 +1013,7 @@ where // this impl candidate anyways. It's still a bit scuffed. ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => { return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + ecx.instantiate_normalizes_to_as_rigid(goal)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index ea26d4043b25f..66cc83b41ac3a 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -4,6 +4,10 @@ //! //! This API is completely unstable and subject to change. +// tidy-alphabetical-start +#![feature(option_into_flat_iter)] +// tidy-alphabetical-end + use rustc_middle::query::Providers; pub mod abi_test; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 14f631b84a781..bf5a1dc2ec4b8 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1112,8 +1112,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { .iter() .flat_map(|&cnum| { find_attr!(tcx, cnum.as_def_id(), UnstableRemoved(rem_features) => rem_features) - .into_iter() - .flatten() + .into_flat_iter() }) .collect::>(); diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index cf62b2c623381..8a739df7d9ad2 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -1526,7 +1526,6 @@ pub enum PredicateKind { Coerce(CoercePredicate), ConstEquate(TyConst, TyConst), Ambiguous, - AliasRelate(TermKind, TermKind, AliasRelationDirection), } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] @@ -1559,12 +1558,6 @@ pub struct CoercePredicate { pub b: Ty, } -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum AliasRelationDirection { - Equate, - Subtype, -} - #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct TraitPredicate { pub trait_ref: TraitRef, diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 2f280ef9fe4c0..e0e212ee47d59 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -749,13 +749,6 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { } PredicateKind::Ambiguous => crate::ty::PredicateKind::Ambiguous, PredicateKind::NormalizesTo(_pred) => unimplemented!(), - PredicateKind::AliasRelate(a, b, alias_relation_direction) => { - crate::ty::PredicateKind::AliasRelate( - a.kind().stable(tables, cx), - b.kind().stable(tables, cx), - alias_relation_direction.stable(tables, cx), - ) - } } } } @@ -845,18 +838,6 @@ impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { } } -impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { - type T = crate::ty::AliasRelationDirection; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::ty::AliasRelationDirection::*; - match self { - Equate => crate::ty::AliasRelationDirection::Equate, - Subtype => crate::ty::AliasRelationDirection::Subtype, - } - } -} - impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { type T = crate::ty::TraitPredicate; diff --git a/compiler/rustc_resolve/src/error_helper.rs b/compiler/rustc_resolve/src/error_helper.rs index c8abc3556f8fe..8ab193afe0eee 100644 --- a/compiler/rustc_resolve/src/error_helper.rs +++ b/compiler/rustc_resolve/src/error_helper.rs @@ -1469,13 +1469,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::DeriveHelpers(expn_id) => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { - suggestions.extend( - this.helper_attrs.get(&expn_id).into_iter().flatten().map( - |&(ident, orig_ident_span, _)| { - TypoSuggestion::new(ident.name, orig_ident_span, res) - }, - ), - ); + suggestions.extend(this.helper_attrs.get(&expn_id).into_flat_iter().map( + |&(ident, orig_ident_span, _)| { + TypoSuggestion::new(ident.name, orig_ident_span, res) + }, + )); } } Scope::DeriveHelpersCompat => { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index d5babe2e94a90..4f22ff3c3e5f9 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -26,6 +26,7 @@ use crate::{ Determinacy, ExternModule, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, LocalModule, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, diagnostics, + module_to_string, }; #[derive(Copy, Clone)] @@ -1869,6 +1870,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module = Some(ModuleOrUniformRoot::Module(parent)); continue; } + let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); + let current_module = self.resolve_self(&mut ctxt, parent_scope.module); + let current_module_path = module_to_string(current_module) + .map_or_else(|| "crate".to_string(), |path| format!("crate::{path}")); return PathResult::failed( ident, false, @@ -1877,8 +1882,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module, || { ( - "too many leading `super` keywords".to_string(), - "there are too many leading `super` keywords".to_string(), + format!( + "too many leading `super` keywords within `{current_module_path}`" + ), + "this `super` would go above the crate root".to_string(), None, None, ) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3b93f2d1fd130..ca0704a9f4352 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -15,6 +15,7 @@ #![feature(default_field_values)] #![feature(deref_patterns)] #![feature(iter_intersperse)] +#![feature(option_into_flat_iter)] #![feature(rustc_attrs)] #![feature(trim_prefix_suffix)] #![recursion_limit = "256"] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index c5b7a5e8450da..cc83867dc1a9e 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -6,6 +6,7 @@ #![feature(iter_intersperse)] #![feature(macro_derive)] #![feature(macro_metavar_expr)] +#![feature(option_into_flat_iter)] #![feature(rustc_attrs)] // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers"). diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4e5b38d34b824..e8e405f4a3df0 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1621,7 +1621,7 @@ pub mod parse { let mut seen_instruction_threshold = false; let mut seen_skip_entry = false; let mut seen_skip_exit = false; - for option in v.into_iter().flat_map(|v| v.split(',')) { + for option in v.map(|v| v.split(',')).into_flat_iter() { match option { "always" if !seen_always && !seen_never => { options.always = true; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 78f4690443525..5c19b35e1605c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1687,6 +1687,7 @@ supported_targets! { ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), + ("riscv32imfc-unknown-none-elf", riscv32imfc_unknown_none_elf), ("riscv32imc-esp-espidf", riscv32imc_esp_espidf), ("riscv32imac-esp-espidf", riscv32imac_esp_espidf), ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs new file mode 100644 index 0000000000000..da88f860b3935 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs @@ -0,0 +1,44 @@ +use crate::spec::{ + Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, + TargetOptions, +}; + +// Bare-metal RV32IMFC for cores that have hardware single-precision float (the `F` +// extension, with the `ilp32f` ABI) but NO atomic ('a') extension. +// This is `riscv32imafc-unknown-none-elf` MINUS the atomic extension, handled the +// same way the in-tree `riscv32imc-unknown-none-elf` handles a no-`a` core: +// `+forced-atomics` makes atomic load/store lower to plain ld/st (sound on a single +// hart) while `atomic_cas = false` keeps RMW/CAS off — downstream crates use a +// critical-section polyfill (e.g. portable-atomic) for those. No lr.w/sc.w/amo* are +// ever emitted, so it does not trap on a core without the A extension. +pub(crate) fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), + llvm_target: "riscv32".into(), + metadata: TargetMetadata { + description: Some( + "Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics)".into(), + ), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: Arch::RiscV32, + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+m,+f,+c,+forced-atomics".into(), + llvm_abiname: LlvmAbi::Ilp32f, + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 973a088a7f5d4..e1b1a41f37a74 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -735,7 +735,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ty::PredicateKind::Ambiguous | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. }) | ty::PredicateKind::NormalizesTo { .. } - | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { span_bug!( span, @@ -1643,55 +1642,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (None, error.err) } } - ty::PredicateKind::AliasRelate(lhs, rhs, _) => { - let derive_better_type_error = - |alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| { - let ocx = ObligationCtxt::new(self); - - let normalized_term = ocx.normalize( - &ObligationCause::dummy(), - obligation.param_env, - Unnormalized::new_wip( - alias_term.to_term(self.tcx, ty::IsRigid::No), - ), - ); - - if let Err(terr) = ocx.eq( - &ObligationCause::dummy(), - obligation.param_env, - expected_term, - normalized_term, - ) { - Some((terr, self.resolve_vars_if_possible(normalized_term))) - } else { - None - } - }; - - if let Some(lhs) = lhs.to_alias_term() - && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind - && let Some((better_type_err, expected_term)) = - derive_better_type_error(lhs, rhs) - { - ( - Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)), - better_type_err, - ) - } else if let Some(rhs) = rhs.to_alias_term() - && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind - && let Some((better_type_err, expected_term)) = - derive_better_type_error(rhs, lhs) - { - ( - Some((rhs, self.resolve_vars_if_possible(expected_term), lhs)), - better_type_err, - ) - } else { - (None, error.err) - } - } _ => (None, error.err), }; @@ -2326,18 +2276,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { return false; } + let mut multi_span = MultiSpan::from_span(self.tcx.def_span(def_id)); let (desc, mention_castable) = match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) { (ty::FnPtr(..), ty::FnDef(..)) => { (" implemented for fn pointer `", ", cast using `as`") } (ty::FnPtr(..), _) => (" implemented for fn pointer `", ""), - _ => (" implemented for `", ""), + _ => { + let evaluate_obligations = || { + let ocx = ObligationCtxt::new_with_diagnostics(self); + self.enter_forall(trait_pred, |obligation_trait_ref| { + let impl_args = self.fresh_args_for_item(DUMMY_SP, def_id); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + ty::EarlyBinder::bind(self.tcx, cand) + .instantiate(self.tcx, impl_args), + ); + if ocx + .eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref.trait_ref, + impl_trait_ref, + ) + .is_err() + { + return Vec::new(); + } + ocx.register_obligations( + self.tcx + .predicates_of(def_id) + .instantiate(self.tcx, impl_args) + .into_iter() + .map(|(clause, span)| { + Obligation::new( + self.tcx, + ObligationCause::dummy_with_span(span), + param_env, + clause.skip_normalization(), + ) + }), + ); + ocx.try_evaluate_obligations() + }) + }; + let failing_obligations = + if !self.tcx.predicates_of(def_id).predicates.is_empty() { + self.probe(|_| evaluate_obligations()) + } else { + Vec::new() + }; + + if failing_obligations.is_empty() { + (" implemented for `", "") + } else { + for error in failing_obligations { + multi_span.push_span_label( + error.root_obligation.cause.span, + format!( + "unsatisfied requirement introduced here: `{}`", + error.root_obligation.predicate, + ), + ); + } + + (" conditionally implemented for `", "") + } + } }; let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path()); let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path()); err.highlighted_span_help( - self.tcx.def_span(def_id), + multi_span, vec![ StringPart::normal(format!("the trait `{trait_}` ")), StringPart::highlighted("is"), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index b0fda96078c54..139aa6bd77a87 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => None, }; - [typeck_results.expr_ty_adjusted_opt(expr)].into_iter().flatten().any(|expr_ty| { + typeck_results.expr_ty_adjusted_opt(expr).is_some_and(|expr_ty| { self.can_eq(obligation.param_env, expr_ty, old_self_ty) || inner_old_self_ty .is_some_and(|inner_ty| self.can_eq(obligation.param_env, expr_ty, inner_ty)) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 8900687036d41..463555c456264 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -19,6 +19,7 @@ #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] #![feature(never_type)] +#![feature(option_into_flat_iter)] #![feature(try_blocks)] #![feature(unwrap_infallible)] #![feature(yeet_expr)] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 098dcfb30a7b6..816bf7248f3bf 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -52,9 +52,6 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( expected_ty, }) } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } ty::PredicateKind::Subtype(pred) => { let (a, b) = infcx.enter_forall_and_leak_universe( obligation.predicate.kind().rebind((pred.a, pred.b)), @@ -264,8 +261,7 @@ impl<'tcx> BestObligation<'tcx> { let body_id = self.obligation.cause.body_id; for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id) - .into_iter() - .flatten() + .into_flat_iter() { let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( GoalSource::Misc, @@ -544,21 +540,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; } - // alias-relate may fail because the lhs or rhs can't be normalized, - // and therefore is treated as rigid. - if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() { - goal.infcx().visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs)), - goal.depth() + 1, - self, - )?; - goal.infcx().visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs)), - goal.depth() + 1, - self, - )?; - } - self.detect_trait_error_in_higher_ranked_projection(goal)?; ControlFlow::Break(self.obligation.clone()) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index a39f498e36fd8..469eb4fc0630c 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -813,7 +813,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::NormalizesTo(..) - | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::DynCompatible(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 12b9940a83f44..00ad863f38346 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -461,9 +461,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::NormalizesTo(..) => { bug!("NormalizesTo is only used by the new solver") } - ty::PredicateKind::AliasRelate(..) => { - bug!("AliasRelate is only used by the new solver") - } ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => { unreachable!("unexpected higher ranked `UnstableFeature` goal") } @@ -535,9 +532,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::NormalizesTo(..) => { bug!("NormalizesTo is only used by the new solver") } - ty::PredicateKind::AliasRelate(..) => { - bug!("AliasRelate is only used by the new solver") - } // Compute `ConstArgHasType` above the overflow check below. // This is because this is not ever a useful obligation to report // as the cause of an overflow. diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 233e124fc60f5..a98f8b9a9af88 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -98,8 +98,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // From the full set of obligations, just filter down to the region relationships. for obligation in wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) - .into_iter() - .flatten() + .into_flat_iter() { let pred = ocx .deeply_normalize( @@ -125,8 +124,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::NormalizesTo(..) - | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) - | ty::PredicateKind::AliasRelate(..) => {} + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => {} // We need to search through *all* WellFormed predicates ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b278c32cb61ae..90fdc3ff939d2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1030,10 +1030,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // supertraits. let a_auto_traits: FxIndexSet = a_data .auto_traits() - .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { - elaborate::supertrait_def_ids(self.tcx(), principal_def_id) - .filter(|def_id| self.tcx().trait_is_auto(*def_id)) - })) + .chain( + principal_def_id_a + .map(|principal_def_id| { + elaborate::supertrait_def_ids(self.tcx(), principal_def_id) + .filter(|def_id| self.tcx().trait_is_auto(*def_id)) + }) + .into_flat_iter(), + ) .collect(); let auto_traits_compatible = b_data .auto_traits() diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 73dc9bff6343d..f0a6ff9a58b51 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -771,10 +771,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(EvaluatedToOkModuloRegions) } - ty::PredicateKind::DynCompatible(_) => { - bug!( - "Obligation {obligation:?} should have been handled by fulfillment already." - ) + ty::PredicateKind::DynCompatible(trait_def_id) => { + // `DynCompatible` obligations are only emitted as + // nested obligations of `WellFormed` goals. It is quite + // rare, but possible, that we encounter them during + // evaluation. See #158665 for more details here. + if self.tcx().is_dyn_compatible(trait_def_id) { + Ok(EvaluatedToOk) + } else { + Ok(EvaluatedToErr) + } } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { @@ -972,9 +978,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::NormalizesTo(..) => { bug!("NormalizesTo is only used by the new solver") } - ty::PredicateKind::AliasRelate(..) => { - bug!("AliasRelate is only used by the new solver") - } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { let ct = self.infcx.shallow_resolve_const(ct); @@ -2594,10 +2597,15 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // supertraits. let a_auto_traits: FxIndexSet = a_data .auto_traits() - .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - elaborate::supertrait_def_ids(tcx, principal_def_id) - .filter(|def_id| tcx.trait_is_auto(*def_id)) - })) + .chain( + a_data + .principal_def_id() + .map(|principal_def_id| { + elaborate::supertrait_def_ids(tcx, principal_def_id) + .filter(|def_id| tcx.trait_is_auto(*def_id)) + }) + .into_flat_iter(), + ) .collect(); let upcast_principal = normalize_with_depth_to( diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 72f1b51d19e9d..83d493f077539 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -188,8 +188,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( /// Turns option of iterator into an iterator (this is just flatten) fn maybe_iter(i: Option) -> impl Iterator { - // Flatten is bad perf-vise, we could probably implement a special case here that is better - i.into_iter().flatten() + i.into_flat_iter() } fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 1e6089dc37f95..1ba385e86b310 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -70,7 +70,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::NormalizesTo(..) - | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) | ty::PredicateKind::DynCompatible(..) | ty::PredicateKind::Subtype(..) diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index 6fc40ce42d88c..92f1898658b07 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -257,15 +257,15 @@ where pub(crate) fn bytes_from(&self, start: State) -> impl Iterator { self.transitions .get(&start) - .into_iter() - .flat_map(|transitions| transitions.byte_transitions.iter()) + .map(|transitions| transitions.byte_transitions.iter()) + .into_flat_iter() } pub(crate) fn refs_from(&self, start: State) -> impl Iterator, State)> { self.transitions .get(&start) - .into_iter() - .flat_map(|transitions| transitions.ref_transitions.iter()) + .map(|transitions| transitions.ref_transitions.iter()) + .into_flat_iter() .map(|(r, s)| (*r, *s)) } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 732881f12d2cb..e504ce0051398 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(test, feature(test))] #![feature(never_type)] +#![feature(option_into_flat_iter)] // tidy-alphabetical-end pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 58fadff1e6e5d..268386692dc3f 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -32,7 +32,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { let item_def_id = trait_item_ref.owner_id.to_def_id(); [item_def_id] .into_iter() - .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) + .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied()) })) } hir::ItemKind::Impl(impl_) => { @@ -44,7 +44,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { let item_def_id = impl_item_ref.owner_id.to_def_id(); [item_def_id] .into_iter() - .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) + .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied()) })) } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index e83525c16b965..174f1c50964a9 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -176,13 +176,13 @@ fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator if let hir::ItemKind::Impl(impl_) = item.kind { let trait_args = impl_ .of_trait - .into_iter() - .flat_map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args) + .map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args) + .into_flat_iter() .map(|arg| arg.span()); let dummy_spans_for_default_args = impl_ .of_trait - .into_iter() - .flat_map(|of_trait| iter::repeat(of_trait.trait_ref.path.span)); + .map(|of_trait| iter::repeat(of_trait.trait_ref.path.span)) + .into_flat_iter(); iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args) } else { bug!("unexpected item for impl {def_id:?}: {item:?}") diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index cdf280381247a..be0042f697e5d 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -718,8 +718,7 @@ fn layout_of_uncached<'tcx>( let discriminants_iter = || { def.is_enum() .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128))) - .into_iter() - .flatten() + .into_flat_iter() }; let maybe_unsized = def.is_struct() diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 6d7afba71098a..d775a7bfceff2 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -9,6 +9,7 @@ #![feature(deref_patterns)] #![feature(iterator_try_collect)] #![feature(never_type)] +#![feature(option_into_flat_iter)] // tidy-alphabetical-end use rustc_middle::query::Providers; diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index da7d8b5acbc1e..e63b72e47833e 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -443,10 +443,6 @@ impl FlagComputation { self.add_alias_term(alias); self.add_term(term); } - ty::PredicateKind::AliasRelate(t1, t2, _) => { - self.add_term(t1); - self.add_term(t2); - } ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_sym)) => {} ty::PredicateKind::Ambiguous => {} } diff --git a/compiler/rustc_type_ir/src/generic_visit.rs b/compiler/rustc_type_ir/src/generic_visit.rs index 6adaf4d158f40..4010ac3da5ece 100644 --- a/compiler/rustc_type_ir/src/generic_visit.rs +++ b/compiler/rustc_type_ir/src/generic_visit.rs @@ -198,7 +198,6 @@ trivial_impls!( usize, crate::PredicatePolarity, crate::BoundConstness, - crate::AliasRelationDirection, crate::DebruijnIndex, crate::solve::Certainty, crate::UniverseIndex, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 77e5fcac07b3f..d730696a38677 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -499,9 +499,7 @@ pub trait Predicate>: fn allow_normalization(self) -> bool { match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { - false - } + PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, PredicateKind::Clause(ClauseKind::Trait(_)) | PredicateKind::Clause(ClauseKind::HostEffect(..)) | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index ea92699958094..6a2d86b4419c3 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -50,7 +50,6 @@ TrivialTypeTraversalImpls! { u32, u64, // tidy-alphabetical-start - crate::AliasRelationDirection, crate::BoundConstness, crate::DebruijnIndex, crate::PredicatePolarity, diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index e905c1849a31d..ddb4fecb3eb1a 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -2,7 +2,7 @@ use std::fmt; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash, StableHash_NoContext}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::{self as ty, Interner}; @@ -103,32 +103,10 @@ pub enum PredicateKind { /// It is likely more useful to think of this as a function `normalizes_to(alias)`, /// whose return value is written into `term`. NormalizesTo(ty::NormalizesTo), - - /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. - /// This predicate requires two terms to be equal to eachother. - /// - /// Only used for new solver. - AliasRelate(I::Term, I::Term, AliasRelationDirection), } impl Eq for PredicateKind {} -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(StableHash, Encodable_NoContext, Decodable_NoContext))] -pub enum AliasRelationDirection { - Equate, - Subtype, -} - -impl std::fmt::Display for AliasRelationDirection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - AliasRelationDirection::Equate => write!(f, "=="), - AliasRelationDirection::Subtype => write!(f, "<:"), - } - } -} - impl fmt::Debug for ClauseKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -161,9 +139,6 @@ impl fmt::Debug for PredicateKind { PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"), PredicateKind::Ambiguous => write!(f, "Ambiguous"), PredicateKind::NormalizesTo(p) => p.fmt(f), - PredicateKind::AliasRelate(t1, t2, dir) => { - write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") - } } } } diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index d5f9df2249df7..b292be195e103 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -38,8 +38,7 @@ where obligations: impl IntoIterator>, ); - /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); + fn ambient_variance(&self) -> ty::Variance; } pub fn super_combine_tys( @@ -115,60 +114,69 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } - (ty::Alias(is_rigid_a, _), ty::Alias(is_rigid_b, _)) if infcx.next_trait_solver() => { - match (is_rigid_a, is_rigid_b) { - (ty::IsRigid::Yes, ty::IsRigid::Yes) => structurally_relate_tys(relation, a, b), - _ => match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), - StructurallyRelateAliases::No => { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } - }, - } - } - - (other, ty::Alias(is_rigid, _)) | (ty::Alias(is_rigid, _), other) - if infcx.next_trait_solver() => + (ty::Alias(ty::IsRigid::No, alias), _) | (_, ty::Alias(ty::IsRigid::No, alias)) + if infcx.next_trait_solver() + && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() => { - if let StructurallyRelateAliases::No = relation.structurally_relate_aliases() - && is_rigid == ty::IsRigid::No - { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } else { - match other { - ty::Infer(infer_ty) => match infer_ty { - // Normally, we shouldn't be combining an infer ty with an alias here. But - // when we evaluate a `Projection(assoc_ty, expected)` goal, we normalize - // the projection term and structurally equate it with the expected term. If - // the normalized term is an alias type and the expected term is a ty var, - // the ty var just instantiated with the alias type without combining them. - // However, if the expected term is either an int var or a float var, e.g., - // when the expected term is an int literal that only can be fully inferred - // after the fallback, they are passed to this function because int/float - // vars can't be instantiated. As we can't structurally relate infer ty with - // another type, we just error them out here instead. - ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) => { - Err(TypeError::Sorts(ExpectedFound::new(a, b))) - } - - ty::InferTy::TyVar(_) - | ty::InferTy::FreshTy(_) - | ty::InferTy::FreshIntTy(_) - | ty::InferTy::FreshFloatTy(_) => unreachable!(), - }, - _ => structurally_relate_tys(relation, a, b), + // If both sides are aliases, arbitrarily do the LHS first + let terms_are_inverted = !matches!(a.kind(), ty::Alias(ty::IsRigid::No, _)); + let other = if terms_are_inverted { a } else { b }; + match (relation.ambient_variance(), terms_are_inverted) { + (ty::Invariant, _) => relation.register_predicates([ty::ProjectionPredicate { + projection_term: alias.into(), + term: other.into(), + }]), + (ty::Covariant, false) | (ty::Contravariant, true) => { + // Generate a new var to represent `alias <: other` + // with `alias == ?A && ?A <: other` + let new_var = infcx.next_ty_infer(); + relation.register_predicates([ + ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { + projection_term: alias.into(), + term: new_var.into(), + }, + )), + ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: !terms_are_inverted, + a: new_var, + b: other, + }), + ]); + } + (ty::Contravariant, false) | (ty::Covariant, true) => { + // a :> b is b <: a + let new_var = infcx.next_ty_infer(); + relation.register_predicates([ + ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { + projection_term: alias.into(), + term: new_var.into(), + }, + )), + ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: terms_are_inverted, + a: other, + b: new_var, + }), + ]); + } + (ty::Bivariant, _) => { + unreachable!( + "cannot handle bivariant aliases in register_projection_with_variance" + ) } } + Ok(a) } // All other cases of inference are errors (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))), (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) - | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { - assert!(!infcx.next_trait_solver()); + | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) + if !infcx.next_trait_solver() => + { match infcx.typing_mode_raw().assert_not_erased() { // During coherence, opaque types should be treated as *possibly* // equal to any other type. This is an @@ -239,32 +247,24 @@ where Ok(a) } - (ty::ConstKind::Alias(ty::IsRigid::Yes, _), ty::ConstKind::Alias(ty::IsRigid::Yes, _)) - if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) => + (ty::ConstKind::Alias(ty::IsRigid::No, alias), _) + | (_, ty::ConstKind::Alias(ty::IsRigid::No, alias)) + if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) + && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() => { - structurally_relate_consts(relation, a, b) - } - - (ty::ConstKind::Alias(..), _) | (_, ty::ConstKind::Alias(..)) - if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() => - { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::No => { - relation.register_predicates([if infcx.next_trait_solver() { - ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ) - } else { - ty::PredicateKind::ConstEquate(a, b) - }]); - - Ok(b) - } - StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + if infcx.next_trait_solver() { + let other = if matches!(a.kind(), ty::ConstKind::Alias(..)) { b } else { a }; + relation.register_predicates([ty::ProjectionPredicate { + projection_term: alias.into(), + term: other.into(), + }]) + } else { + relation.register_predicates([ty::PredicateKind::ConstEquate(a, b)]); } + + Ok(b) } + _ => structurally_relate_consts(relation, a, b), } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 96e30f06473cf..a3ed4ac4b6e7f 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -383,27 +383,7 @@ where self.goals.extend(obligations); } - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { - self.register_predicates([ty::Binder::dummy(match self.ambient_variance { - ty::Covariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Subtype, - ), - // a :> b is b <: a - ty::Contravariant => ty::PredicateKind::AliasRelate( - b.into(), - a.into(), - ty::AliasRelationDirection::Subtype, - ), - ty::Invariant => ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ), - ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - })]); + fn ambient_variance(&self) -> ty::Variance { + self.ambient_variance } } diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index e8d36483f3139..e3679ecd4d309 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -8,10 +8,10 @@ /// /// This is most common on types that represent an important state or outcome. For example, /// [`Result`] is marked `#[must_use]` because ignoring an error value can hide a failed operation. -/// In the following example, the returned `Result` is the only sign that writing the message +/// In the following example, the returned [`Result`] is the only sign that writing the message /// might have failed: /// -/// ```rust +/// ``` /// # #![allow(unused_must_use)] /// fn write_message() -> std::io::Result<()> { /// // Write the message... @@ -21,7 +21,7 @@ /// write_message(); /// ``` /// -/// Ignoring that `Result` triggers this warning: +/// Ignoring that [`Result`] triggers this warning: /// /// ```text /// warning: unused `Result` that must be used @@ -36,7 +36,7 @@ /// You can also place `#[must_use]` on a function, method, or trait declaration. On a function or /// method, the warning is tied to ignoring that call's return value: /// -/// ```rust +/// ``` /// # #![allow(unused_must_use)] /// #[must_use] /// fn make_token() -> String { @@ -53,7 +53,7 @@ /// /// The attribute can include a message explaining what the caller should do with the value: /// -/// ```rust +/// ``` /// # #![allow(dead_code)] /// #[must_use = "call `.finish()` to complete the operation"] /// fn start_operation() -> Operation { @@ -65,7 +65,7 @@ /// /// If intentionally ignoring the value is correct, bind it to `_` or call [`drop`]: /// -/// ```rust +/// ``` /// # #[must_use] /// # fn make_token() -> String { /// # String::from("token") @@ -80,8 +80,6 @@ /// /// For more information, see the Reference on [the `must_use` attribute]. /// -/// [`Result`]: result::Result -/// [`Future`]: future::Future /// [`unused_must_use`]: ../rustc/lints/listing/warn-by-default.html#unused-must-use /// [the `must_use` attribute]: ../reference/attributes/diagnostics.html#the-must_use-attribute mod must_use_attribute {} @@ -90,9 +88,9 @@ mod must_use_attribute {} // /// The `allow` attribute suppresses lint diagnostics that would otherwise produce /// warnings or errors. It can be used on any lint or lint group (except those -/// set to `forbid`). +/// set to [`forbid`]). /// -/// ```rust +/// ``` /// #[allow(dead_code)] /// fn unused_function() { /// // ... @@ -119,7 +117,7 @@ mod must_use_attribute {} /// /// Multiple lints can be set to `allow` at once with commas: /// -/// ```rust +/// ``` /// #[allow(unused_variables, unused_mut)] /// fn main() { /// let mut x: u32 = 42; @@ -128,12 +126,12 @@ mod must_use_attribute {} /// /// This is mostly used to prevent lint warnings or errors while still under development. /// -/// It cannot override a lint that has been set to `forbid`. +/// It cannot override a lint that has been set to [`forbid`]. /// /// It's also important to consider that overusing `allow` could make code harder to maintain /// and possibly hide issues. To mitigate this issue, using the `expect` attribute is preferred. /// -/// `allow` can be overridden by `warn`, `deny`, and `forbid`. +/// `allow` can be overridden by [`warn`], [`deny`], and [`forbid`]. /// /// The lint checks supported by rustc can be found via `rustc -W help`, /// along with their default settings and are documented in [the `rustc` book]. @@ -143,6 +141,9 @@ mod must_use_attribute {} /// For more information, see the Reference on [the `allow` attribute]. /// /// [the `allow` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes +/// [`forbid`]: ./attribute.forbid.html +/// [`warn`]: ./attribute.warn.html +/// [`deny`]: ./attribute.deny.html mod allow_attribute {} #[doc(attribute = "cfg")] @@ -152,7 +153,7 @@ mod allow_attribute {} /// The `cfg` attribute allows compiling an item under specific conditions, otherwise it /// will be ignored. /// -/// ```rust +/// ``` /// // Only compiles this function for Linux. /// #[cfg(target_os = "linux")] /// fn platform_specific() { @@ -169,19 +170,20 @@ mod allow_attribute {} /// Depending on the platform you're targeting, only one of these two functions will be considered /// during the compilation. /// -/// Conditions can also be combined with `all(...)`, `any(...)`, and `not(...)`. +/// Conditions can also be combined with `all(...)`, `any(...)`, and `not(...)`: /// /// * `all`: True if all given predicates are true. /// * `any`: True if at least one of the given predicates is true. /// * `not`: True if the predicate is false and false if the predicate is true. /// -/// ```rust +/// ``` /// #[cfg(all(unix, target_pointer_width = "64"))] /// fn unix_64bit() { +/// // ... /// } /// ``` /// -/// If you want to use this mechanism in an `if` condition in your code, you +/// If you want to use this mechanism in an [`if`] condition in your code, you /// can use the [`cfg!`] macro. To conditionally apply an attribute, /// see [`cfg_attr`]. /// @@ -189,6 +191,7 @@ mod allow_attribute {} /// /// [`cfg_attr`]: ../reference/conditional-compilation.html#the-cfg_attr-attribute /// [the `cfg` attribute]: ../reference/conditional-compilation.html#the-cfg-attribute +/// [`if`]: ./keyword.if.html mod cfg_attribute {} #[doc(attribute = "deny")] @@ -196,16 +199,16 @@ mod cfg_attribute {} /// Emits an error, preventing the compilation from finishing, when a lint check has failed. /// This is useful for enforcing rules or preventing certain patterns: /// -/// ```rust,compile_fail +/// ```compile_fail /// #[deny(unused)] /// fn foo() { /// let x = 42; // Emits an error because x is unused. /// } /// ``` /// -/// `deny` can be overridden by `allow`, `warn`, and `forbid`: +/// `deny` can be overridden by [`allow`], [`warn`], and [`forbid`]: /// -/// ```rust +/// ``` /// #![deny(unused)] /// /// #[allow(unused)] // We override the `deny` for this function. @@ -216,7 +219,7 @@ mod cfg_attribute {} /// /// Multiple lints can also be set to `deny` at once: /// -/// ```rust,compile_fail +/// ```compile_fail /// #![deny(unused_imports, unused_variables)] /// use std::collections::*; /// @@ -233,20 +236,24 @@ mod cfg_attribute {} /// For more information, see the Reference on [the `deny` attribute]. /// /// [the `deny` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes +/// [`forbid`]: ./attribute.forbid.html +/// [`allow`]: ./attribute.allow.html +/// [`warn`]: ./attribute.warn.html +/// [`deny`]: ./attribute.deny.html mod deny_attribute {} #[doc(attribute = "forbid")] // /// Emits an error, preventing the compilation from finishing, when a lint check has failed. /// -/// A lint set to `forbid` cannot be overridden by `allow` or `warn`. +/// A lint set to `forbid` cannot be overridden by [`allow`] or [`warn`]. /// Attempting either will result in a compilation error. Writing `#[deny(...)]` on the same lint inside a /// `forbid` scope is permitted, but has no effect; the lint remains at the `forbid` level. /// /// This is useful for enforcing strict policies that should not be relaxed /// anywhere in the codebase. Example: /// -/// ```rust +/// ``` /// #![forbid(unsafe_code)] /// /// // This would cause a compilation error if uncommented: @@ -255,7 +262,7 @@ mod deny_attribute {} /// /// Multiple lints can be set to `forbid` at once: /// -/// ```rust +/// ``` /// #![forbid(unsafe_code, unused)] /// ``` /// @@ -267,6 +274,8 @@ mod deny_attribute {} /// For more information, see the Reference on [the `forbid` attribute]. /// /// [the `forbid` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes +/// [`allow`]: ./attribute.allow.html +/// [`warn`]: ./attribute.warn.html mod forbid_attribute {} #[doc(attribute = "deprecated")] @@ -279,15 +288,16 @@ mod forbid_attribute {} /// /// Example: /// -/// ```rust +/// ``` /// #[deprecated(since = "1.0.0", note = "Use bar instead")] /// struct Foo; /// struct Bar; /// ``` /// -/// `deprecated` attribute helps developers transition away from old code by providing warnings when -/// deprecated items are used. Note that during `Cargo` builds, warnings on dependencies get silenced -/// by default, so you may not see a deprecation warning unless you build that dependency directly. +/// The `deprecated` attribute helps developers transition away from old code by providing warnings +/// when deprecated items are used. Note that during `Cargo` builds, warnings on dependencies get +/// silenced by default, so you may not see a deprecation warning unless you build that dependency +/// directly. /// /// For more information, see the Reference on [the `deprecated` attribute]. /// @@ -298,12 +308,13 @@ mod deprecated_attribute {} // /// Emits a warning during compilation when a lint check failed. /// -/// Unlike `deny` or `forbid`, `warn` does not produce a hard error: the compilation continues, but -/// the compiler emits a warning message. `warn` can be overridden by `allow`, `deny`, and `forbid`. +/// Unlike [`deny`] or [`forbid`], `warn` does not produce a hard error: the compilation +/// continues, but the compiler emits a warning message. `warn` can be overridden by [`allow`], +/// [`deny`], and [`forbid`]. /// /// Example: /// -/// ```rust,compile_fail +/// ```compile_fail /// #![allow(unused)] /// /// #[warn(unused)] // We override the allowed `unused` lint. @@ -315,11 +326,11 @@ mod deprecated_attribute {} /// /// /// Many lints, including `unused`, are already set to `warn` by default so this attribute is -/// mainly useful for lints that are normally `allow` by default. +/// mainly useful for lints that are normally [`allow`] by default. /// /// Multiple lints can be set to `warn` at once: /// -/// ```rust,compile_fail +/// ```compile_fail /// #[warn(unused_mut, unused_variables)] /// fn main() { /// let mut x = 42; @@ -334,4 +345,7 @@ mod deprecated_attribute {} /// For more information, see the Reference on [the `warn` attribute]. /// /// [the `warn` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes +/// [`allow`]: ./attribute.allow.html +/// [`deny`]: ./attribute.deny.html +/// [`forbid`]: ./attribute.forbid.html mod warn_attribute {} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 58b5ad4a924b1..bc96c768c0c94 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -818,19 +818,19 @@ pub const fn forget(_: T); /// /// // This is how the standard library does it. This is the best method, if /// // you need to do something like this -/// fn split_at_stdlib(slice: &mut [T], mid: usize) +/// fn split_at_stdlib(to_split: &mut [T], mid: usize) /// -> (&mut [T], &mut [T]) { -/// let len = slice.len(); +/// let len = to_split.len(); /// assert!(mid <= len); /// unsafe { -/// let ptr = slice.as_mut_ptr(); -/// // This now has three mutable references pointing at the same -/// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1. -/// // `slice` is never used after `let ptr = ...`, and so one can -/// // treat it as "dead", and therefore, you only have two real -/// // mutable slices. -/// (slice::from_raw_parts_mut(ptr, mid), -/// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) +/// let ptr = to_split.as_mut_ptr(); +/// let fst = slice::from_raw_parts_mut(ptr, mid); +/// let snd = slice::from_raw_parts_mut(ptr.add(mid), len - mid); +/// // The function now has three mutable references to overlapping memory: +/// // `to_split`, `fst`, and `snd`. +/// // `to_split` is never used after `let ptr = ...` so it can be treated as "dead". +/// // This leaves two "live" mutable slice references, `fst` and `snd`, with no overlap. +/// (fst, snd) /// } /// } /// ``` diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 66dde8377a37a..4f3b27ec5c837 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -300,27 +300,25 @@ //! represent the tagged pointer as an actual pointer and not a `usize`*. For instance: //! //! ``` -//! unsafe { -//! // A flag we want to pack into our pointer -//! static HAS_DATA: usize = 0x1; -//! static FLAG_MASK: usize = !HAS_DATA; -//! -//! // Our value, which must have enough alignment to have spare least-significant-bits. -//! let my_precious_data: u32 = 17; -//! assert!(align_of::() > 1); -//! -//! // Create a tagged pointer -//! let ptr = &my_precious_data as *const u32; -//! let tagged = ptr.map_addr(|addr| addr | HAS_DATA); -//! -//! // Check the flag: -//! if tagged.addr() & HAS_DATA != 0 { -//! // Untag and read the pointer -//! let data = *tagged.map_addr(|addr| addr & FLAG_MASK); -//! assert_eq!(data, 17); -//! } else { -//! unreachable!() -//! } +//! // A flag we want to pack into our pointer +//! static HAS_DATA: usize = 0x1; +//! static FLAG_MASK: usize = !HAS_DATA; +//! +//! // Our value, which must have enough alignment to have spare least-significant-bits. +//! let my_precious_data: u32 = 17; +//! assert!(align_of::() > 1); +//! +//! // Create a tagged pointer +//! let ptr = &my_precious_data as *const u32; +//! let tagged = ptr.map_addr(|addr| addr | HAS_DATA); +//! +//! // Check the flag: +//! if tagged.addr() & HAS_DATA != 0 { +//! // Untag and read the pointer +//! let data = unsafe { *tagged.map_addr(|addr| addr & FLAG_MASK) }; +//! assert_eq!(data, 17); +//! } else { +//! unreachable!() //! } //! ``` //! diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index c5acff2bdd3c5..bea057ceed1b0 100644 --- a/library/std/src/sys/process/unix/vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -124,7 +124,17 @@ impl Command { Ok(t) => unsafe { let mut status = 0 as c_int; libc::waitpid(t.0.pid, &mut status, 0); - libc::exit(0); + // If the task was killed by a signal, terminate the same way by + // restoring the default disposition and resending it to ourselves. + if libc::WIFSIGNALED(status) { + let signal = libc::WTERMSIG(status); + libc::signal(signal, libc::SIG_DFL); + libc::kill(libc::getpid(), signal); + // The signal should have already terminated us; abort if it + // was blocked or ignored. + libc::abort(); + } + libc::exit(libc::WEXITSTATUS(status)); }, Err(e) => e, } diff --git a/src/ci/run.sh b/src/ci/run.sh index 18b5bf2e2bbb3..a65063a36dd79 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -79,14 +79,6 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1" # of our CPU resources. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set dist.compression-profile=balanced" -# When building for mingw, limit the number of parallel linker jobs during -# the LLVM build, as not to run out of memory. -# This is an attempt to fix the spurious build error tracked by -# https://github.com/rust-lang/rust/issues/108227. -if isKnownToBeMingwBuild; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.link-jobs=1" -fi - # Only produce xz tarballs on CI. gz tarballs will be generated by the release # process by recompressing the existing xz ones. This decreases the storage # space required for CI artifacts. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 1bdbae13bdaec..280b0b195634e 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -401,6 +401,7 @@ target | std | host | notes `riscv32gc-unknown-linux-musl` | ? | | RISC-V Linux (kernel 5.4, musl 1.2.5) [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA) [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA) +[`riscv32imfc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics) [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) diff --git a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md index 38742143c4ba2..f76a981bd281a 100644 --- a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md @@ -1,4 +1,4 @@ -# `riscv32{i,im,ima,imc,imac,imafc}-unknown-none-elf` +# `riscv32{i,im,ima,imc,imfc,imac,imafc}-unknown-none-elf` **Tier: 2** @@ -6,12 +6,25 @@ Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and **Tier: 3** -Bare-metal target for RISC-V CPUs with the RV32IMA ISA. +Bare-metal target for RISC-V CPUs with the RV32IMA and RV32IMFC ISAs. + +The `riscv32imfc-unknown-none-elf` target covers RV32IMFC cores that have +hardware single-precision floating point (the `F` extension, using the `ilp32f` +ABI) but *no* atomic (`A`) extension. Like `riscv32imc-unknown-none-elf`, it is +built with `+forced-atomics`: atomic loads/stores lower to plain loads/stores +(sound on a single hart) and `lr`/`sc`/`amo*` instructions are never emitted, so +it does not trap on a core without the `A` extension. Compare-and-swap and other +read-modify-write atomics are disabled (`atomic_cas = false`); downstream crates +that need them use a critical-section polyfill (e.g. `portable-atomic`). ## Target maintainers * Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) +The `riscv32imfc-unknown-none-elf` target is additionally maintained by: + +* [@sanchuanhehe](https://github.com/sanchuanhehe) + ## Requirements The target is cross-compiled, and uses static linking. No external toolchain diff --git a/src/llvm-project b/src/llvm-project index 3c3f13025bf9f..a04c1eced55f2 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 3c3f13025bf9f99bb2a757eb37dad4f09e7d6c36 +Subproject commit a04c1eced55f2f3ea8dbd3d17db0b6df271c0809 diff --git a/src/tools/test-float-parse/Cargo.lock b/src/tools/test-float-parse/Cargo.lock deleted file mode 100644 index 3f60423fed352..0000000000000 --- a/src/tools/test-float-parse/Cargo.lock +++ /dev/null @@ -1,75 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "test-float-parse" -version = "0.1.0" -dependencies = [ - "rand", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 92977143e1f7a..7512adef34e2c 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -508,6 +508,9 @@ //@ revisions: riscv32imc_unknown_none_elf //@ [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf //@ [riscv32imc_unknown_none_elf] needs-llvm-components: riscv +//@ revisions: riscv32imfc_unknown_none_elf +//@ [riscv32imfc_unknown_none_elf] compile-flags: --target riscv32imfc-unknown-none-elf +//@ [riscv32imfc_unknown_none_elf] needs-llvm-components: riscv //@ revisions: riscv64_linux_android //@ [riscv64_linux_android] compile-flags: --target riscv64-linux-android //@ [riscv64_linux_android] needs-llvm-components: riscv diff --git a/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.rs b/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.rs new file mode 100644 index 0000000000000..3a76e7bbb4af1 --- /dev/null +++ b/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(inherent_associated_types)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +struct Foo(T); + +impl Foo> { + //~^ ERROR the size for values of type `[u32]` cannot be known at compilation time + type Assoc = u32; +} + +type Tait = impl Sized; + +#[define_opaque(Tait)] +fn bar() { + let _: Foo::Assoc = 42; + //~^ ERROR the associated type `Assoc` exists for `Foo`, but its trait bounds were not satisfied +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.stderr b/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.stderr new file mode 100644 index 0000000000000..36ba160e38a14 --- /dev/null +++ b/tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/next-solver-unsatisfied-bounds-inherent-tait.rs:9:10 + | +LL | impl Foo> { + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: the associated type `Assoc` exists for `Foo`, but its trait bounds were not satisfied + --> $DIR/next-solver-unsatisfied-bounds-inherent-tait.rs:18:23 + | +LL | struct Foo(T); + | ------------- associated type `Assoc` not found for this struct +... +LL | let _: Foo::Assoc = 42; + | ^^^^^ associated type cannot be referenced on `Foo` due to unsatisfied trait bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr index dcb1639593a58..09b45212c3c9a 100644 --- a/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr +++ b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr @@ -7,11 +7,13 @@ LL | println!("{:?}", S(X)); | required by this formatting parameter | = help: the trait `Debug` is not implemented for `X` -help: the trait `Debug` is implemented for `S` +help: the trait `Debug` is conditionally implemented for `S` --> $DIR/redundant-derive-note-on-unimplemented.rs:8:10 | LL | #[derive(Debug)] | ^^^^^ +LL | struct S(T); + | - unsatisfied requirement introduced here: `X: Debug` note: required for `S` to implement `Debug` --> $DIR/redundant-derive-note-on-unimplemented.rs:9:8 | diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index a28b28c0fe16c..b301f5f6bc09b 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -39,11 +39,13 @@ LL | want(Some(())); | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` -help: the trait `T1` is implemented for `Option` +help: the trait `T1` is conditionally implemented for `Option` --> $DIR/blame-trait-error.rs:21:1 | LL | impl T1 for Option {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^--------^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied requirement introduced here: `(): Iterator` note: required for `Option<()>` to implement `T1` --> $DIR/blame-trait-error.rs:21:20 | diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.rs b/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.rs new file mode 100644 index 0000000000000..5bacedcb76493 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.rs @@ -0,0 +1,9 @@ +//@ check-pass + +// Regression test for https://github.com/rust-lang/rust/issues/158628. + +#[diagnostic::on_type_error(unknown = "")] +//~^ WARN unknown diagnostic attribute +pub struct Foo {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.stderr b/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.stderr new file mode 100644 index 0000000000000..c8b4aac78d6e1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.stderr @@ -0,0 +1,11 @@ +warning: unknown diagnostic attribute + --> $DIR/feature-gate-diagnostic-on-type-error-malformed-args.rs:5:15 + | +LL | #[diagnostic::on_type_error(unknown = "")] + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(diagnostic_on_type_error)]` to the crate attributes to enable + = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.rs b/tests/ui/impl-restriction/restriction_resolution_errors.rs index 5cc9f86bcaaa4..4c70755f5e420 100644 --- a/tests/ui/impl-restriction/restriction_resolution_errors.rs +++ b/tests/ui/impl-restriction/restriction_resolution_errors.rs @@ -23,7 +23,7 @@ pub mod a { pub impl(in super::E) trait T6 {} //~ ERROR expected module, found enum `super::E` [E0577] - pub impl(in super::super::super) trait T7 {} //~ ERROR too many leading `super` keywords [E0433] + pub impl(in super::super::super) trait T7 {} //~ ERROR too many leading `super` keywords within `crate::a::b` [E0433] // OK paths pub impl(crate) trait T8 {} @@ -53,7 +53,7 @@ pub impl(in crate::a::E) trait T14 {} //~ ERROR expected module, found enum `cra pub impl(crate) trait T15 {} pub impl(self) trait T16 {} -pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords [E0433] +pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords within `crate` [E0433] pub impl(in external) trait T18 {} //~ ERROR trait implementation can only be restricted to ancestor modules diff --git a/tests/ui/impl-restriction/restriction_resolution_errors.stderr b/tests/ui/impl-restriction/restriction_resolution_errors.stderr index 019ad0eda8249..70af66c9186bf 100644 --- a/tests/ui/impl-restriction/restriction_resolution_errors.stderr +++ b/tests/ui/impl-restriction/restriction_resolution_errors.stderr @@ -16,11 +16,11 @@ error: trait implementation can only be restricted to ancestor modules LL | pub impl(in super::d) trait T4 {} | ^^^^^^^^ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate::a::b` --> $DIR/restriction_resolution_errors.rs:26:35 | LL | pub impl(in super::super::super) trait T7 {} - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: trait implementation can only be restricted to ancestor modules --> $DIR/restriction_resolution_errors.rs:36:21 @@ -40,11 +40,11 @@ error: trait implementation can only be restricted to ancestor modules LL | pub impl(in crate::a) trait T13 {} | ^^^^^^^^ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/restriction_resolution_errors.rs:56:10 | LL | pub impl(super) trait T17 {} - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: trait implementation can only be restricted to ancestor modules --> $DIR/restriction_resolution_errors.rs:58:13 diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 406f21941dc97..91b38b5176516 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -50,8 +50,11 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | | | the trait `From>` is not implemented for `impl Debug` | -help: the trait `Into` is implemented for `T` +help: the trait `Into` is conditionally implemented for `T` --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL + | + = note: unsatisfied requirement introduced here: `impl Debug: From>` = note: required for `impl Into` to implement `Into` error[E0277]: the trait bound `impl Debug: From>` is not satisfied @@ -62,8 +65,11 @@ LL | fn bad(x: impl Into) -> impl Into { x } | | | the trait `From>` is not implemented for `impl Debug` | -help: the trait `Into` is implemented for `T` +help: the trait `Into` is conditionally implemented for `T` --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL + | + = note: unsatisfied requirement introduced here: `impl Debug: From>` = note: required for `impl Into` to implement `Into` error: aborting due to 7 previous errors diff --git a/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs b/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs new file mode 100644 index 0000000000000..195e11754226d --- /dev/null +++ b/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs @@ -0,0 +1,21 @@ +//! Regression test for . + +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ check-pass + +trait Trait {} + +trait WithAssoc { + type Assoc: ?Sized; +} +struct Thing; +impl WithAssoc for Thing { + type Assoc = dyn Trait; +} + +fn foo() -> impl WithAssoc { + Thing +} + +fn main() {} diff --git a/tests/ui/keyword/keyword-super-as-identifier.rs b/tests/ui/keyword/keyword-super-as-identifier.rs index 0aeb224e183be..f3a6b019a9875 100644 --- a/tests/ui/keyword/keyword-super-as-identifier.rs +++ b/tests/ui/keyword/keyword-super-as-identifier.rs @@ -1,3 +1,3 @@ fn main() { - let super = 22; //~ ERROR too many leading `super` keywords + let super = 22; //~ ERROR too many leading `super` keywords within `crate` } diff --git a/tests/ui/keyword/keyword-super-as-identifier.stderr b/tests/ui/keyword/keyword-super-as-identifier.stderr index d8609c6bcbe8c..c89a7a240dafd 100644 --- a/tests/ui/keyword/keyword-super-as-identifier.stderr +++ b/tests/ui/keyword/keyword-super-as-identifier.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/keyword-super-as-identifier.rs:2:9 | LL | let super = 22; - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/keyword/keyword-super.rs b/tests/ui/keyword/keyword-super.rs index c21149a846fe0..d6d0bcaa806ca 100644 --- a/tests/ui/keyword/keyword-super.rs +++ b/tests/ui/keyword/keyword-super.rs @@ -1,3 +1,3 @@ fn main() { - let super: isize; //~ ERROR: too many leading `super` keywords + let super: isize; //~ ERROR: too many leading `super` keywords within `crate` } diff --git a/tests/ui/keyword/keyword-super.stderr b/tests/ui/keyword/keyword-super.stderr index 69af7da09376a..2b06bf3f808a5 100644 --- a/tests/ui/keyword/keyword-super.stderr +++ b/tests/ui/keyword/keyword-super.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/keyword-super.rs:2:9 | LL | let super: isize; - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/lint/improper-ctypes/nonzero-char.rs b/tests/ui/lint/improper-ctypes/nonzero-char.rs new file mode 100644 index 0000000000000..1c60322060af7 --- /dev/null +++ b/tests/ui/lint/improper-ctypes/nonzero-char.rs @@ -0,0 +1,13 @@ +// Regression test for https://github.com/rust-lang/rust/issues/158511. + +#![allow(dead_code)] +#![deny(improper_ctypes)] + +use std::num; + +extern "C" { + fn result_nonzero_u32_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `char`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/lint/improper-ctypes/nonzero-char.stderr b/tests/ui/lint/improper-ctypes/nonzero-char.stderr new file mode 100644 index 0000000000000..4c1940fe4318f --- /dev/null +++ b/tests/ui/lint/improper-ctypes/nonzero-char.stderr @@ -0,0 +1,16 @@ +error: `extern` block uses type `char`, which is not FFI-safe + --> $DIR/nonzero-char.rs:9:32 + | +LL | fn result_nonzero_u32_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent +note: the lint level is defined here + --> $DIR/nonzero-char.rs:4:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/modules/super-at-crate-root.rs b/tests/ui/modules/super-at-crate-root.rs index 0aac3a0875709..05cd4eb349d7f 100644 --- a/tests/ui/modules/super-at-crate-root.rs +++ b/tests/ui/modules/super-at-crate-root.rs @@ -1,6 +1,6 @@ //! Check that `super` keyword used at the crate root (top-level) results in a compilation error //! as there is no parent module to resolve. -use super::f; //~ ERROR too many leading `super` keywords +use super::f; //~ ERROR too many leading `super` keywords within `crate` fn main() {} diff --git a/tests/ui/modules/super-at-crate-root.stderr b/tests/ui/modules/super-at-crate-root.stderr index cb3855cc033d8..e47ffb0fd63b5 100644 --- a/tests/ui/modules/super-at-crate-root.stderr +++ b/tests/ui/modules/super-at-crate-root.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/super-at-crate-root.rs:4:5 | LL | use super::f; - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/resolve/impl-items-vis-unresolved.rs b/tests/ui/resolve/impl-items-vis-unresolved.rs index bbdc8170d4f6b..b5156a3493c12 100644 --- a/tests/ui/resolve/impl-items-vis-unresolved.rs +++ b/tests/ui/resolve/impl-items-vis-unresolved.rs @@ -19,7 +19,7 @@ pub struct RawFloatState; impl RawFloatState { perftools_inline! { pub(super) fn new() {} - //~^ ERROR: too many leading `super` keywords + //~^ ERROR: too many leading `super` keywords within `crate` } } diff --git a/tests/ui/resolve/impl-items-vis-unresolved.stderr b/tests/ui/resolve/impl-items-vis-unresolved.stderr index e433cb607cdac..7953d56b740d8 100644 --- a/tests/ui/resolve/impl-items-vis-unresolved.stderr +++ b/tests/ui/resolve/impl-items-vis-unresolved.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/impl-items-vis-unresolved.rs:21:13 | LL | pub(super) fn new() {} - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-117920.rs b/tests/ui/resolve/issue-117920.rs index 6fbc412001f5b..0719710666ae5 100644 --- a/tests/ui/resolve/issue-117920.rs +++ b/tests/ui/resolve/issue-117920.rs @@ -1,6 +1,6 @@ #![crate_type = "lib"] -use super::A; //~ ERROR too many leading `super` keywords +use super::A; //~ ERROR too many leading `super` keywords within `crate` mod b { pub trait A {} diff --git a/tests/ui/resolve/issue-117920.stderr b/tests/ui/resolve/issue-117920.stderr index 810c2c06efe7f..a4493e073c393 100644 --- a/tests/ui/resolve/issue-117920.stderr +++ b/tests/ui/resolve/issue-117920.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/issue-117920.rs:3:5 | LL | use super::A; - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-82156.rs b/tests/ui/resolve/issue-82156.rs index fc6840faf636b..dc7eadd508779 100644 --- a/tests/ui/resolve/issue-82156.rs +++ b/tests/ui/resolve/issue-82156.rs @@ -1,3 +1,3 @@ fn main() { - super(); //~ ERROR: too many leading `super` keywords + super(); //~ ERROR: too many leading `super` keywords within `crate` } diff --git a/tests/ui/resolve/issue-82156.stderr b/tests/ui/resolve/issue-82156.stderr index 6fe0d4c4ea157..aa19bfc2f2bf9 100644 --- a/tests/ui/resolve/issue-82156.stderr +++ b/tests/ui/resolve/issue-82156.stderr @@ -1,8 +1,8 @@ -error[E0433]: too many leading `super` keywords +error[E0433]: too many leading `super` keywords within `crate` --> $DIR/issue-82156.rs:2:5 | LL | super(); - | ^^^^^ there are too many leading `super` keywords + | ^^^^^ this `super` would go above the crate root error: aborting due to 1 previous error diff --git a/tests/ui/resolve/too-many-super-issue-158275.rs b/tests/ui/resolve/too-many-super-issue-158275.rs new file mode 100644 index 0000000000000..da6ea658d675c --- /dev/null +++ b/tests/ui/resolve/too-many-super-issue-158275.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +mod outer { + mod inner { + struct Example(super::super::super::Impl); + //~^ ERROR too many leading `super` keywords within `crate::outer::inner` + } +} + +struct Impl; diff --git a/tests/ui/resolve/too-many-super-issue-158275.stderr b/tests/ui/resolve/too-many-super-issue-158275.stderr new file mode 100644 index 0000000000000..df256e478caaf --- /dev/null +++ b/tests/ui/resolve/too-many-super-issue-158275.stderr @@ -0,0 +1,9 @@ +error[E0433]: too many leading `super` keywords within `crate::outer::inner` + --> $DIR/too-many-super-issue-158275.rs:5:38 + | +LL | struct Example(super::super::super::Impl); + | ^^^^^ this `super` would go above the crate root + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/splat/run-splat.rs b/tests/ui/splat/run-splat.rs new file mode 100644 index 0000000000000..06360883d5a43 --- /dev/null +++ b/tests/ui/splat/run-splat.rs @@ -0,0 +1,37 @@ +//! Check that splat codegen works for simple cases. +//@ run-pass +//@ check-run-results +#![feature(splat, tuple_trait)] +#![expect(incomplete_features)] + +use std::marker::Tuple; + +struct Foo; + +trait MethodArgs: Tuple { + fn call_method(self, this: &Foo); +} + +impl Foo { + fn method(&self, #[splat] args: impl MethodArgs) { + args.call_method(self) + } +} + +impl MethodArgs for (i32, String) { + fn call_method(self, _this: &Foo) { + dbg!(self.1, self.0); + } +} + +impl MethodArgs for (f64,) { + fn call_method(self, _this: &Foo) { + dbg!(self.0); + } +} + +fn main() { + let foo = Foo; + foo.method(42, "hello splat".to_string()); + foo.method(3.141); +} diff --git a/tests/ui/splat/run-splat.run.stderr b/tests/ui/splat/run-splat.run.stderr new file mode 100644 index 0000000000000..337f5f01e6029 --- /dev/null +++ b/tests/ui/splat/run-splat.run.stderr @@ -0,0 +1,3 @@ +[$DIR/run-splat.rs:23:9] self.1 = "hello splat" +[$DIR/run-splat.rs:23:9] self.0 = 42 +[$DIR/run-splat.rs:29:9] self.0 = 3.141 diff --git a/tests/ui/splat/splat-dyn-asref-tuple-fail.rs b/tests/ui/splat/splat-dyn-asref-tuple-fail.rs index 40d702346b7a3..d9b3b0351281c 100644 --- a/tests/ui/splat/splat-dyn-asref-tuple-fail.rs +++ b/tests/ui/splat/splat-dyn-asref-tuple-fail.rs @@ -4,11 +4,36 @@ #![feature(splat)] #![feature(tuple_trait)] -fn dyn_asref_splat(#[splat] _t: &dyn AsRef) where T: std::marker::Tuple {} -//~^ ERROR cannot use splat attribute +// Strip binders and their lifetime numbers from error messages +//@ normalize-stderr: "&.*value: (.*), bound_vars: .*" -> "$1" + +// FIXME(splat): Some errors are reported on the callee, but they would be more ergonomic on the +// caller as well +fn dyn_asref_splat(#[splat] _t: &dyn AsRef) +//~^ ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a +//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a +//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a +//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a +where + T: std::marker::Tuple, +{ +} fn main() { + // These error patterns are reported on the function definition, but we can't check for two + // strings in the same error message let s: String = "hello".to_owned(); dyn_asref_splat::(&s); //~^ ERROR `String` is not a tuple + //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<.*String>\) + + dyn_asref_splat(&s); + //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\) + + let t = (1u8, 2f32); + dyn_asref_splat::<(u8, f32)>(&t); + //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<\(u8, f32\)>\) + + dyn_asref_splat(&t); + //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\) } diff --git a/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr b/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr index cba1ab28181a4..e9388eee63de0 100644 --- a/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr +++ b/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr @@ -1,24 +1,54 @@ -error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a &'?3 dyn [Binder { value: Trait(std::convert::AsRef), bound_vars: [] }] + '?3 (&'?3 dyn [Binder { value: Trait(std::convert::AsRef), bound_vars: [] }] + '?3) - --> $DIR/splat-dyn-asref-tuple-fail.rs:7:36 +error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef) + --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 | -LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) where T: std::marker::Tuple {} +LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) | ^^^^^^^^^^^^^ ... LL | dyn_asref_splat::(&s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `String` is not a tuple - --> $DIR/splat-dyn-asref-tuple-fail.rs:12:23 + --> $DIR/splat-dyn-asref-tuple-fail.rs:26:23 | LL | dyn_asref_splat::(&s); | ^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `String` | note: required by a bound in `dyn_asref_splat` - --> $DIR/splat-dyn-asref-tuple-fail.rs:7:60 + --> $DIR/splat-dyn-asref-tuple-fail.rs:18:8 | -LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) where T: std::marker::Tuple {} - | ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat` +LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) + | --------------- required by a bound in this function +... +LL | T: std::marker::Tuple, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat` + +error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>) + --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 + | +LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) + | ^^^^^^^^^^^^^ +... +LL | dyn_asref_splat(&s); + | ^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<(u8, f32)>) + --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 + | +LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) + | ^^^^^^^^^^^^^ +... +LL | dyn_asref_splat::<(u8, f32)>(&t); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>) + --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 + | +LL | fn dyn_asref_splat(#[splat] _t: &dyn AsRef) + | ^^^^^^^^^^^^^ +... +LL | dyn_asref_splat(&t); + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/splat/splat-fn-ptr-cast-fail.rs b/tests/ui/splat/splat-fn-ptr-cast-fail.rs new file mode 100644 index 0000000000000..1cd1bdacf582c --- /dev/null +++ b/tests/ui/splat/splat-fn-ptr-cast-fail.rs @@ -0,0 +1,25 @@ +//! Test casting splatted functions to non-splatted function pointers fails. + +#![allow(incomplete_features)] +#![feature(splat, tuple_trait)] + +use std::marker::Tuple; + +fn tuple_args(#[splat] (_a, _b): (u32, i8)) {} + +fn splat_non_terminal_arg(#[splat] (_a, _b): (u32, i8), _c: f64) {} + +fn f(#[splat] args: Args) {} + +fn main() { + // Function pointers + let _fn_ptr: fn((u32, i8)) = tuple_args; //~ ERROR mismatched types + let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg; //~ ERROR mismatched types + + let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8)); //~ ERROR non-primitive cast + let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64); //~ ERROR non-primitive cast + + // Bug #158603 regression test variants + const _F2: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types + const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>; //~ ERROR mismatched types +} diff --git a/tests/ui/splat/splat-fn-ptr-cast-fail.stderr b/tests/ui/splat/splat-fn-ptr-cast-fail.stderr new file mode 100644 index 0000000000000..93d7c8493048d --- /dev/null +++ b/tests/ui/splat/splat-fn-ptr-cast-fail.stderr @@ -0,0 +1,60 @@ +error[E0308]: mismatched types + --> $DIR/splat-fn-ptr-cast-fail.rs:16:34 + | +LL | let _fn_ptr: fn((u32, i8)) = tuple_args; + | ------------- ^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted + | | + | expected due to this + | + = note: expected fn pointer `fn((_, _))` + found fn item `fn(#[splat] (_, _)) {tuple_args}` + +error[E0308]: mismatched types + --> $DIR/splat-fn-ptr-cast-fail.rs:17:39 + | +LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg; + | ------------------ ^^^^^^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted + | | + | expected due to this + | + = note: expected fn pointer `fn((_, _), _)` + found fn item `fn(#[splat] (_, _), _) {splat_non_terminal_arg}` + +error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8)) {tuple_args}` as `fn((u32, i8))` + --> $DIR/splat-fn-ptr-cast-fail.rs:19:34 + | +LL | let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8), f64) {splat_non_terminal_arg}` as `fn((u32, i8), f64)` + --> $DIR/splat-fn-ptr-cast-fail.rs:20:39 + | +LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error[E0308]: mismatched types + --> $DIR/splat-fn-ptr-cast-fail.rs:23:32 + | +LL | const _F2: fn((u8, u32)) = f::<(u8, u32)>; + | ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted + | | + | expected because of the type of the constant + | + = note: expected fn pointer `fn((_, _))` + found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}` + +error[E0308]: mismatched types + --> $DIR/splat-fn-ptr-cast-fail.rs:24:35 + | +LL | const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>; + | ---------------- ^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted + | | + | expected because of the type of the constant + | + = note: expected fn pointer `fn(((_, _),))` + found fn item `fn(#[splat] ((_, _),)) {f::<((u8, u32),)>}` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0605. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/splat/splat-fn-tuple-generic-fail.rs b/tests/ui/splat/splat-fn-tuple-generic-fail.rs index 8a8651e75c9ff..17e8e46db0672 100644 --- a/tests/ui/splat/splat-fn-tuple-generic-fail.rs +++ b/tests/ui/splat/splat-fn-tuple-generic-fail.rs @@ -4,7 +4,11 @@ #![feature(splat)] #![feature(tuple_trait)] -fn splat_generic_tuple(#[splat] _t: T) {} +use std::marker::Tuple; + +fn splat_generic_tuple(#[splat] _t: T) {} + +fn f(#[splat] args: Args) {} fn main() { // FIXME(splat): should splatted functions be callable with tupled and un-tupled arguments? @@ -24,4 +28,6 @@ fn main() { splat_generic_tuple::<(u32, i8)>((1, 2)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided splat_generic_tuple::<(u32, i8)>((1u32, 2i8)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided + + const F1: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types } diff --git a/tests/ui/splat/splat-fn-tuple-generic-fail.stderr b/tests/ui/splat/splat-fn-tuple-generic-fail.stderr index 7fd4a0719b493..c4fc6aa1d56c1 100644 --- a/tests/ui/splat/splat-fn-tuple-generic-fail.stderr +++ b/tests/ui/splat/splat-fn-tuple-generic-fail.stderr @@ -1,39 +1,51 @@ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:19:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:23:5 | LL | splat_generic_tuple::<(((u32, i8)))>((1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:20:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:24:5 | LL | splat_generic_tuple::<(((u32, i8)))>((1u32, 2i8)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:22:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:26:5 | LL | splat_generic_tuple::<((u32, i8))>((1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:23:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:27:5 | LL | splat_generic_tuple::<((u32, i8))>((1u32, 2i8)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:25:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:29:5 | LL | splat_generic_tuple::<(u32, i8)>((1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this splatted function takes 2 arguments, but 1 was provided - --> $DIR/splat-fn-tuple-generic-fail.rs:26:5 + --> $DIR/splat-fn-tuple-generic-fail.rs:30:5 | LL | splat_generic_tuple::<(u32, i8)>((1u32, 2i8)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/splat-fn-tuple-generic-fail.rs:32:31 + | +LL | const F1: fn((u8, u32)) = f::<(u8, u32)>; + | ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted + | | + | expected because of the type of the constant + | + = note: expected fn pointer `fn((_, _))` + found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}` + +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0057`. +Some errors have detailed explanations: E0057, E0308. +For more information about an error, try `rustc --explain E0057`. diff --git a/tests/ui/splat/splat-generics-everywhere.rs b/tests/ui/splat/splat-generics-everywhere.rs index be4f917ce21df..90335ad31f938 100644 --- a/tests/ui/splat/splat-generics-everywhere.rs +++ b/tests/ui/splat/splat-generics-everywhere.rs @@ -3,11 +3,10 @@ #![allow(incomplete_features)] #![feature(splat)] +#![feature(tuple_trait)] struct Foo(T); -// FIXME(splat): also add assoc/method with splatted generic tuple traits -// also add generics inside the splatted tuple impl Foo { fn new(t: T) -> Self { Self(t) @@ -20,12 +19,13 @@ impl Foo { fn lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} fn const_generic(&self, #[splat] _s: (u32, f64, [u8; N])) {} + + fn generic_in_tuple(&self, #[splat] _s: (U, u32)) {} + + fn generic_tuple_assoc(_u: U, #[splat] _s: ()) {} } -// FIXME(splat): also add generics to the trait -// also add assoc/method with splatted generic tuple traits -// also add generics inside the splatted tuple -trait BarTrait { +trait BarTrait { fn trait_assoc(w: W, #[splat] _s: ()); fn trait_method(&self, x: X, #[splat] _s: (u32, f64)); @@ -33,9 +33,13 @@ trait BarTrait { fn trait_lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} fn trait_const_generic(&self, #[splat] _s: (u32, f64, [u8; N])) {} + + fn trait_generic_in_tuple(&self, #[splat] _s: (T, U)) {} + + fn trait_generic_tuple(&self, #[splat] _s: U) {} } -impl BarTrait for Foo { +impl BarTrait for Foo { fn trait_assoc(_w: W, #[splat] _s: ()) {} fn trait_method(&self, _x: X, #[splat] _s: (u32, f64)) {} @@ -43,6 +47,10 @@ impl BarTrait for Foo { fn trait_lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} fn trait_const_generic(&self, #[splat] _s: (u32, f64, [u8; N])) {} + + fn trait_generic_in_tuple(&self, #[splat] _s: (T, U)) {} + + fn trait_generic_tuple(&self, #[splat] _s: U) {} } fn main() { @@ -57,8 +65,13 @@ fn main() { foo.method("v", 1u32, 2.3); foo.lifetime(1u32, 2.3, "asdf"); foo.const_generic(1u32, 2.3, [1, 2, 3]); + foo.generic_in_tuple(42i32, 1u32); + Foo::::generic_tuple_assoc(()); + Foo::::trait_assoc("w"); foo.trait_method("x", 42u32, 9.8); foo.trait_lifetime(1u32, 2.3, "asdf"); foo.trait_const_generic(1u32, 2.3, [1, 2, 3]); + foo.trait_generic_in_tuple("hello", 42i32); + foo.trait_generic_tuple(); } diff --git a/tests/ui/splat/splat-self.rs b/tests/ui/splat/splat-self.rs new file mode 100644 index 0000000000000..b826a5b30b9bc --- /dev/null +++ b/tests/ui/splat/splat-self.rs @@ -0,0 +1,21 @@ +//@ run-pass +//@ check-run-results +//! Test using `#[splat]` on self arguments of trait methods. + +#![feature(splat)] +#![expect(incomplete_features)] + +trait Trait { + fn method(#[splat] self: Self); +} + +impl Trait for (i32, i64) { + fn method(#[splat] self: Self) { + println!("{self:?}"); + } +} + +fn main() { + (1_i32, 2_i64).method(); + Trait::method(3_i32, 4_i64); +} diff --git a/tests/ui/splat/splat-self.run.stdout b/tests/ui/splat/splat-self.run.stdout new file mode 100644 index 0000000000000..7bb2d763632f2 --- /dev/null +++ b/tests/ui/splat/splat-self.run.stdout @@ -0,0 +1,2 @@ +(1, 2) +(3, 4) diff --git a/tests/ui/traits/copy-bounds-impl-type-params.stderr b/tests/ui/traits/copy-bounds-impl-type-params.stderr index 08fde8fb5df35..4f9600f3f321d 100644 --- a/tests/ui/traits/copy-bounds-impl-type-params.stderr +++ b/tests/ui/traits/copy-bounds-impl-type-params.stderr @@ -80,11 +80,13 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | let a = t as Box>; | ^ the trait `Copy` is not implemented for `String` | -help: the trait `Gettable` is implemented for `S` +help: the trait `Gettable` is conditionally implemented for `S` --> $DIR/copy-bounds-impl-type-params.rs:14:1 | LL | impl Gettable for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied requirement introduced here: `String: Copy` note: required for `S` to implement `Gettable` --> $DIR/copy-bounds-impl-type-params.rs:14:32 | @@ -100,11 +102,13 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied LL | let a: Box> = t; | ^ the trait `Copy` is not implemented for `Foo` | -help: the trait `Gettable` is implemented for `S` +help: the trait `Gettable` is conditionally implemented for `S` --> $DIR/copy-bounds-impl-type-params.rs:14:1 | LL | impl Gettable for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied requirement introduced here: `Foo: Copy` note: required for `S` to implement `Gettable` --> $DIR/copy-bounds-impl-type-params.rs:14:32 | diff --git a/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.rs b/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.rs new file mode 100644 index 0000000000000..3f95e6a7a0da2 --- /dev/null +++ b/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.rs @@ -0,0 +1,28 @@ +struct Test(i32, i64); +trait Foo<'a> { + type Assoc; +} + +trait SimpleFoo { + type SimpleAssoc; +} +impl<'a, T> Foo<'a> for T where T: SimpleFoo { + type Assoc = T::SimpleAssoc; +} + +impl SimpleFoo for i32 { + type SimpleAssoc = i32; +} +impl SimpleFoo for i64 { + type SimpleAssoc = i32; +} + +impl<'a> Foo<'a> for Test where i32: Foo<'a, Assoc = i32>, i64: Foo<'a, Assoc = i64> { + type Assoc = Test; +} + +fn process<'a, T: Foo<'a>>(_input: T) {} +fn test() { process(Test(0, 1)) } +//~^ ERROR the trait bound `Test: Foo<'_>` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.stderr b/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.stderr new file mode 100644 index 0000000000000..b6c6329abc84b --- /dev/null +++ b/tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Test: Foo<'_>` is not satisfied + --> $DIR/conditionally-implemented-trait-158423.rs:25:21 + | +LL | fn test() { process(Test(0, 1)) } + | ------- ^^^^^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `Foo<'_>` is not implemented for `Test` + --> $DIR/conditionally-implemented-trait-158423.rs:1:1 + | +LL | struct Test(i32, i64); + | ^^^^^^^^^^^ +help: the trait `Foo<'_>` is conditionally implemented for `Test` + --> $DIR/conditionally-implemented-trait-158423.rs:20:1 + | +LL | impl<'a> Foo<'a> for Test where i32: Foo<'a, Assoc = i32>, i64: Foo<'a, Assoc = i64> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^ + | | + | unsatisfied requirement introduced here: `>::Assoc == i64` +note: required by a bound in `process` + --> $DIR/conditionally-implemented-trait-158423.rs:24:19 + | +LL | fn process<'a, T: Foo<'a>>(_input: T) {} + | ^^^^^^^ required by this bound in `process` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index 34a45e9363069..ebf3f22276241 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -7,7 +7,7 @@ LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation | - = note: overflow evaluating the requirement `_ == ::Assoc` + = note: overflow evaluating the requirement `::Assoc == _` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs new file mode 100644 index 0000000000000..b469165e4b568 --- /dev/null +++ b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver + +//! This test is extremely similar to `nested-rerun-not-erased-in-normalizes-to.rs`, however, +//! instead of the eager normalization failing due to an anon const when in ErasedNotCoherence, this +//! just straight up fails normalization because u32 is not Iterator + +#![feature(ptr_metadata)] + +struct ThisStructAintValid(::Item); +//~^ ERROR `u32` is not an iterator + +fn main() { + let y: ::Metadata; + //~^ ERROR type mismatch resolving `::Metadata == _` +} diff --git a/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr new file mode 100644 index 0000000000000..60fd1b35b26a7 --- /dev/null +++ b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr @@ -0,0 +1,18 @@ +error[E0277]: `u32` is not an iterator + --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:9:28 + | +LL | struct ThisStructAintValid(::Item); + | ^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u32` + +error[E0271]: type mismatch resolving `::Metadata == _` + --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:13:12 + | +LL | let y: ::Metadata; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr index 9b41a88615e4a..4f209fab4c23c 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr @@ -9,13 +9,14 @@ help: the trait `Trait<_, _, _>` is not implemented for `A` | LL | struct A(*const T); | ^^^^^^^^^^^ -help: the trait `Trait` is implemented for `A` +help: the trait `Trait` is conditionally implemented for `A` --> $DIR/incompleteness-unstable-result.rs:34:1 | LL | / impl Trait for A LL | | where LL | | T: IncompleteGuidance, LL | | A: Trait, + | | -------------- unsatisfied requirement introduced here: `A<_>: Trait<_, _, _>` LL | | B: Trait, LL | | (): ToU8, | |________________^ diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr index 9b41a88615e4a..4f209fab4c23c 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr @@ -9,13 +9,14 @@ help: the trait `Trait<_, _, _>` is not implemented for `A` | LL | struct A(*const T); | ^^^^^^^^^^^ -help: the trait `Trait` is implemented for `A` +help: the trait `Trait` is conditionally implemented for `A` --> $DIR/incompleteness-unstable-result.rs:34:1 | LL | / impl Trait for A LL | | where LL | | T: IncompleteGuidance, LL | | A: Trait, + | | -------------- unsatisfied requirement introduced here: `A<_>: Trait<_, _, _>` LL | | B: Trait, LL | | (): ToU8, | |________________^ diff --git a/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs b/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs new file mode 100644 index 0000000000000..b75598d11c83e --- /dev/null +++ b/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs @@ -0,0 +1,28 @@ +//@ build-pass +//@ compile-flags: -Znext-solver + +//! Consider: +//! +//! goal is ::Metadata == ?0, in a typing context of +//! ErasedNotCoherence +//! +//! `consider_builtin_pointee_candidate` looks at StructTailHasAnonConst, realizes it's an ADT, +//! fetches the struct tail (which is `S<{ 2 + 2 }>`), and calls `instantiate_normalizes_to_term` +//! with the result of ` as Pointee>::Metadata` +//! +//! `instantiate_normalizes_to_term` `.eq()`s ` as Pointee>::Metadata` and `?0` +//! +//! this eagerly normalizes, which normalizes the anon const, which fails due to ErasedNotCoherence +//! +//! this causes the `.eq()` in `instantiate_normalizes_to_term` to fail, which used to have an +//! unwrap, which ICEd + +#![feature(ptr_metadata)] + +struct S; + +struct StructTailHasAnonConst(S<{ 2 + 2 }>); + +fn main() { + let y: ::Metadata; +} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index c61fbef05b224..ed52d05b39c99 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -14,6 +14,7 @@ fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { needs_bar::(); //~^ ERROR: the trait bound `::Assoc2: Bar` is not satisfied + //~| ERROR: the size for values of type `::Assoc2` cannot be known at compilation time } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index c4be47e3520da..40291ce0cfb86 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -14,6 +14,27 @@ help: consider further restricting the associated type LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Bar { | ++++++++++++++++++++++++++++++ -error: aborting due to 1 previous error +error[E0277]: the size for values of type `::Assoc2` cannot be known at compilation time + --> $DIR/recursive-self-normalization-2.rs:15:17 + | +LL | needs_bar::(); + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `::Assoc2` +note: required by an implicit `Sized` bound in `needs_bar` + --> $DIR/recursive-self-normalization-2.rs:12:14 + | +LL | fn needs_bar() {} + | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` +help: consider further restricting the associated type + | +LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Sized { + | ++++++++++++++++++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | fn needs_bar() {} + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`.