| author | bors <bors@rust-lang.org> 2026-07-05 07:24:27 UTC |
| committer | bors <bors@rust-lang.org> 2026-07-05 07:24:27 UTC |
| log | 4eb62535fc12dd1a63fd43a4173e224e79313c4d |
| tree | 2df8f5575671e2c13e2ca7aebf6393ee447f143a |
| parent | ea088e0a3dd50c494b4589c3c121d7469dceec8f |
| parent | 3755fd95ad3146b1565b342c57073d5341ae664c |
Rollup of 21 pull requests
Successful merges:
- rust-lang/rust#158100 (Emit retags in codegen to support BorrowSanitizer (part 4))
- rust-lang/rust#158494 (Improve E0277 diagnostics for conditionally implemented traits)
- rust-lang/rust#158606 (use ProjectionPredicate instead of AliasRelate)
- rust-lang/rust#158627 (Simplify option-iterator flattening in the compiler)
- rust-lang/rust#158658 (Update LLVM submodule)
- rust-lang/rust#158665 (Revert "Remove redundant dyn-compatibility check.")
- rust-lang/rust#158021 (Remove old MinGW workaround)
- rust-lang/rust#158473 (Add `riscv32imfc-unknown-none-elf` bare-metal target)
- rust-lang/rust#158549 (process::exec: using appropriate exit code on vxworks.)
- rust-lang/rust#158585 (Improve diagnostic for too many super keywords)
- rust-lang/rust#158637 (hir_ty_lowering: avoid self type lookup for inherent aliases)
- rust-lang/rust#158651 (ptr doc: reduce use of unsafe block to where needed)
- rust-lang/rust#158669 (Remove `src/tools/test-float-parse/Cargo.lock`)
- rust-lang/rust#158674 (library: Polish transmute's `split_at_stdlib` example)
- rust-lang/rust#158677 (Add extra splat tests)
- rust-lang/rust#158680 (Avoid ICE for `NonZero<char>` in improper_ctypes)
- rust-lang/rust#158681 (Remove unnecessary `Hash` derives from MIR types)
- rust-lang/rust#158682 (Avoid delayed bug for disabled on_type_error arguments)
- rust-lang/rust#158684 (Add missing generic test coverage for ```#[splat]```)
- rust-lang/rust#158687 (Streamline `MacEager`)
- rust-lang/rust#158688 (Cleanup attribute docs and add links to other mentioned attributes)143 files changed, 1395 insertions(+), 931 deletions(-)
compiler/rustc_ast_passes/src/feature_gate.rs+8-8| ... | ... | @@ -466,7 +466,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { |
| 466 | 466 | let spans = sess.psess.gated_spans.spans.borrow(); |
| 467 | 467 | macro_rules! gate_all { |
| 468 | 468 | ($feature:ident, $explain:literal $(, $help:literal)?) => { |
| 469 | for &span in spans.get(&sym::$feature).into_iter().flatten() { | |
| 469 | for &span in spans.get(&sym::$feature).into_flat_iter() { | |
| 470 | 470 | gate!(visitor, $feature, span, $explain $(, $help)?); |
| 471 | 471 | } |
| 472 | 472 | }; |
| ... | ... | @@ -527,13 +527,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { |
| 527 | 527 | ); |
| 528 | 528 | |
| 529 | 529 | // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. |
| 530 | for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() { | |
| 530 | for &span in spans.get(&sym::associated_const_equality).into_flat_iter() { | |
| 531 | 531 | gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete"); |
| 532 | 532 | } |
| 533 | 533 | |
| 534 | 534 | // `mgca_type_const_syntax` is part of `min_generic_const_args` so if |
| 535 | 535 | // either or both are enabled we don't need to emit a feature error. |
| 536 | for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() { | |
| 536 | for &span in spans.get(&sym::mgca_type_const_syntax).into_flat_iter() { | |
| 537 | 537 | if visitor.features.min_generic_const_args() |
| 538 | 538 | || visitor.features.mgca_type_const_syntax() |
| 539 | 539 | || span.allows_unstable(sym::min_generic_const_args) |
| ... | ... | @@ -561,13 +561,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { |
| 561 | 561 | // it does **not** mean "`T` doesn't implement `Bound` (positively or negatively)"! |
| 562 | 562 | // The latter would be a SemVer hazard! |
| 563 | 563 | if !sess.opts.unstable_opts.internal_testing_features || !visitor.features.negative_bounds() { |
| 564 | for &span in spans.get(&sym::negative_bounds).into_iter().flatten() { | |
| 564 | for &span in spans.get(&sym::negative_bounds).into_flat_iter() { | |
| 565 | 565 | sess.dcx().emit_err(diagnostics::NegativeBoundUnsupported { span }); |
| 566 | 566 | } |
| 567 | 567 | } |
| 568 | 568 | |
| 569 | 569 | if !visitor.features.never_patterns() { |
| 570 | for &span in spans.get(&sym::never_patterns).into_iter().flatten() { | |
| 570 | for &span in spans.get(&sym::never_patterns).into_flat_iter() { | |
| 571 | 571 | if span.allows_unstable(sym::never_patterns) { |
| 572 | 572 | continue; |
| 573 | 573 | } |
| ... | ... | @@ -585,7 +585,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { |
| 585 | 585 | } |
| 586 | 586 | |
| 587 | 587 | // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`. |
| 588 | for &span in spans.get(&sym::yield_expr).into_iter().flatten() { | |
| 588 | for &span in spans.get(&sym::yield_expr).into_flat_iter() { | |
| 589 | 589 | if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) |
| 590 | 590 | && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) |
| 591 | 591 | && (!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) { |
| 607 | 607 | |
| 608 | 608 | macro_rules! soft_gate_all_legacy_dont_use { |
| 609 | 609 | ($feature:ident, $explain:literal) => { |
| 610 | for &span in spans.get(&sym::$feature).into_iter().flatten() { | |
| 610 | for &span in spans.get(&sym::$feature).into_flat_iter() { | |
| 611 | 611 | if !visitor.features.$feature() && !span.allows_unstable(sym::$feature) { |
| 612 | 612 | feature_warn(&visitor.sess, sym::$feature, span, $explain); |
| 613 | 613 | } |
| ... | ... | @@ -625,7 +625,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { |
| 625 | 625 | soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); |
| 626 | 626 | // tidy-alphabetical-end |
| 627 | 627 | |
| 628 | for &span in spans.get(&sym::min_specialization).into_iter().flatten() { | |
| 628 | for &span in spans.get(&sym::min_specialization).into_flat_iter() { | |
| 629 | 629 | if !visitor.features.specialization() |
| 630 | 630 | && !visitor.features.min_specialization() |
| 631 | 631 | && !span.allows_unstable(sym::specialization) |
compiler/rustc_ast_passes/src/lib.rs+1| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | #![feature(deref_patterns)] |
| 7 | 7 | #![feature(iter_intersperse)] |
| 8 | 8 | #![feature(iter_is_partitioned)] |
| 9 | #![feature(option_into_flat_iter)] | |
| 9 | 10 | // tidy-alphabetical-end |
| 10 | 11 | |
| 11 | 12 | pub mod ast_validation; |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs+2| ... | ... | @@ -18,6 +18,8 @@ pub(crate) struct OnTypeErrorParser { |
| 18 | 18 | impl OnTypeErrorParser { |
| 19 | 19 | fn parse<'sess>(&mut self, cx: &mut AcceptContext<'_, 'sess>, args: &ArgParser, mode: Mode) { |
| 20 | 20 | if !cx.features().diagnostic_on_type_error() { |
| 21 | // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs | |
| 22 | args.ignore_args(); | |
| 21 | 23 | return; |
| 22 | 24 | } |
| 23 | 25 |
compiler/rustc_borrowck/src/dataflow.rs+2-3| ... | ... | @@ -476,9 +476,8 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { |
| 476 | 476 | .borrow_set |
| 477 | 477 | .local_map |
| 478 | 478 | .get(&place.local) |
| 479 | .into_iter() | |
| 480 | .flat_map(|bs| bs.iter()) | |
| 481 | .copied(); | |
| 479 | .map(|bs| bs.iter().copied()) | |
| 480 | .into_flat_iter(); | |
| 482 | 481 | |
| 483 | 482 | // If the borrowed place is a local with no projections, all other borrows of this |
| 484 | 483 | // local must conflict. This is purely an optimization so we don't have to call |
compiler/rustc_borrowck/src/lib.rs+1| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | #![feature(file_buffered)] |
| 8 | 8 | #![feature(negative_impls)] |
| 9 | 9 | #![feature(never_type)] |
| 10 | #![feature(option_into_flat_iter)] | |
| 10 | 11 | #![feature(rustc_attrs)] |
| 11 | 12 | #![feature(stmt_expr_attributes)] |
| 12 | 13 | #![feature(try_blocks)] |
compiler/rustc_borrowck/src/polonius/constraints.rs+2-2| ... | ... | @@ -152,7 +152,7 @@ impl LocalizedConstraintGraph { |
| 152 | 152 | // The physical edges present at this node are: |
| 153 | 153 | // |
| 154 | 154 | // 1. the typeck edges that flow from region to region *at this point*. |
| 155 | for &succ in self.edges.get(&node).into_iter().flatten() { | |
| 155 | for &succ in self.edges.get(&node).into_flat_iter() { | |
| 156 | 156 | let succ = LocalizedNode { region: succ, point: node.point }; |
| 157 | 157 | successor_found(succ); |
| 158 | 158 | } |
| ... | ... | @@ -229,7 +229,7 @@ impl LocalizedConstraintGraph { |
| 229 | 229 | } |
| 230 | 230 | |
| 231 | 231 | // And finally, we have the logical edges, materialized at this point. |
| 232 | for &logical_succ in self.logical_edges.get(&node.region).into_iter().flatten() { | |
| 232 | for &logical_succ in self.logical_edges.get(&node.region).into_flat_iter() { | |
| 233 | 233 | let succ = LocalizedNode { region: logical_succ, point: node.point }; |
| 234 | 234 | successor_found(succ); |
| 235 | 235 | } |
compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs+1-1| ... | ... | @@ -49,7 +49,7 @@ pub(super) fn apply_member_constraints<'tcx>( |
| 49 | 49 | rcx.scc_values.add_region(scc_a, scc_b); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | for defining_use in member_constraints.get(&scc_a).into_iter().flatten() { | |
| 52 | for defining_use in member_constraints.get(&scc_a).into_flat_iter() { | |
| 53 | 53 | apply_member_constraint(rcx, scc_a, &defining_use.arg_regions); |
| 54 | 54 | } |
| 55 | 55 | } |
compiler/rustc_borrowck/src/region_infer/values.rs+6-6| ... | ... | @@ -178,7 +178,7 @@ impl LivenessValues { |
| 178 | 178 | |
| 179 | 179 | /// Returns an iterator of all the points where `region` is live. |
| 180 | 180 | fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> { |
| 181 | self.point_liveness(region).into_iter().flat_map(|set| set.iter()) | |
| 181 | self.point_liveness(region).map(|set| set.iter()).into_flat_iter() | |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | 184 | /// 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> { |
| 348 | 348 | pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> { |
| 349 | 349 | self.points |
| 350 | 350 | .row(r) |
| 351 | .into_iter() | |
| 352 | .flat_map(move |set| set.iter().map(move |p| self.location_map.to_location(p))) | |
| 351 | .map(move |set| set.iter().map(move |p| self.location_map.to_location(p))) | |
| 352 | .into_flat_iter() | |
| 353 | 353 | } |
| 354 | 354 | |
| 355 | 355 | /// Returns just the universal regions that are contained in a given region's value. |
| 356 | 356 | pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> { |
| 357 | self.free_regions.row(r).into_iter().flat_map(|set| set.iter()) | |
| 357 | self.free_regions.row(r).map(|set| set.iter()).into_flat_iter() | |
| 358 | 358 | } |
| 359 | 359 | |
| 360 | 360 | /// Returns all the elements contained in a given region's value. |
| ... | ... | @@ -364,8 +364,8 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> { |
| 364 | 364 | ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> { |
| 365 | 365 | self.placeholders |
| 366 | 366 | .row(r) |
| 367 | .into_iter() | |
| 368 | .flat_map(|set| set.iter()) | |
| 367 | .map(|set| set.iter()) | |
| 368 | .into_flat_iter() | |
| 369 | 369 | .map(move |p| self.placeholder_indices.lookup_placeholder(p)) |
| 370 | 370 | } |
| 371 | 371 |
compiler/rustc_borrowck/src/type_check/mod.rs+1-1| ... | ... | @@ -928,7 +928,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { |
| 928 | 928 | self.super_local_decl(local, local_decl); |
| 929 | 929 | |
| 930 | 930 | for user_ty in |
| 931 | local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections) | |
| 931 | local_decl.user_ty.as_deref().map(UserTypeProjections::projections).into_flat_iter() | |
| 932 | 932 | { |
| 933 | 933 | let span = self.user_type_annotations[user_ty.base].span; |
| 934 | 934 |
compiler/rustc_borrowck/src/type_check/relate_tys.rs+2-22| ... | ... | @@ -597,27 +597,7 @@ impl<'b, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_ |
| 597 | 597 | ); |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { | |
| 601 | self.register_predicates([ty::Binder::dummy(match self.ambient_variance { | |
| 602 | ty::Covariant => ty::PredicateKind::AliasRelate( | |
| 603 | a.into(), | |
| 604 | b.into(), | |
| 605 | ty::AliasRelationDirection::Subtype, | |
| 606 | ), | |
| 607 | // a :> b is b <: a | |
| 608 | ty::Contravariant => ty::PredicateKind::AliasRelate( | |
| 609 | b.into(), | |
| 610 | a.into(), | |
| 611 | ty::AliasRelationDirection::Subtype, | |
| 612 | ), | |
| 613 | ty::Invariant => ty::PredicateKind::AliasRelate( | |
| 614 | a.into(), | |
| 615 | b.into(), | |
| 616 | ty::AliasRelationDirection::Equate, | |
| 617 | ), | |
| 618 | ty::Bivariant => { | |
| 619 | unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)") | |
| 620 | } | |
| 621 | })]); | |
| 600 | fn ambient_variance(&self) -> ty::Variance { | |
| 601 | self.ambient_variance | |
| 622 | 602 | } |
| 623 | 603 | } |
compiler/rustc_codegen_ssa/src/assert_module_sources.rs+1-2| ... | ... | @@ -90,8 +90,7 @@ impl<'tcx> AssertModuleSource<'tcx> { |
| 90 | 90 | fn check_attrs(&mut self, attrs: &[hir::Attribute]) { |
| 91 | 91 | for &(span, cgu_fields) in find_attr!(attrs, |
| 92 | 92 | RustcCguTestAttr(e) => e) |
| 93 | .into_iter() | |
| 94 | .flatten() | |
| 93 | .into_flat_iter() | |
| 95 | 94 | { |
| 96 | 95 | let (expected_reuse, comp_kind) = match cgu_fields { |
| 97 | 96 | CguFields::PartitionReused { .. } => (CguReuse::PreLto, ComparisonKind::AtLeast), |
compiler/rustc_codegen_ssa/src/back/link.rs+3-5| ... | ... | @@ -1091,9 +1091,7 @@ fn link_natively( |
| 1091 | 1091 | let get_objects = |objects: &CrtObjects, kind| { |
| 1092 | 1092 | objects |
| 1093 | 1093 | .get(&kind) |
| 1094 | .iter() | |
| 1095 | .copied() | |
| 1096 | .flatten() | |
| 1094 | .into_flat_iter() | |
| 1097 | 1095 | .map(|obj| { |
| 1098 | 1096 | get_object_file_path(sess, obj, self_contained_crt_objects).into_os_string() |
| 1099 | 1097 | }) |
| ... | ... | @@ -2073,7 +2071,7 @@ fn add_pre_link_objects( |
| 2073 | 2071 | } else { |
| 2074 | 2072 | &empty |
| 2075 | 2073 | }; |
| 2076 | for obj in objects.get(&link_output_kind).iter().copied().flatten() { | |
| 2074 | for obj in objects.get(&link_output_kind).into_flat_iter() { | |
| 2077 | 2075 | cmd.add_object(&get_object_file_path(sess, obj, self_contained)); |
| 2078 | 2076 | } |
| 2079 | 2077 | } |
| ... | ... | @@ -2090,7 +2088,7 @@ fn add_post_link_objects( |
| 2090 | 2088 | } else { |
| 2091 | 2089 | &sess.target.post_link_objects |
| 2092 | 2090 | }; |
| 2093 | for obj in objects.get(&link_output_kind).iter().copied().flatten() { | |
| 2091 | for obj in objects.get(&link_output_kind).into_flat_iter() { | |
| 2094 | 2092 | cmd.add_object(&get_object_file_path(sess, obj, self_contained)); |
| 2095 | 2093 | } |
| 2096 | 2094 | } |
compiler/rustc_codegen_ssa/src/lib.rs+1| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | #![feature(deref_patterns)] |
| 3 | 3 | #![feature(file_buffered)] |
| 4 | 4 | #![feature(negative_impls)] |
| 5 | #![feature(option_into_flat_iter)] | |
| 5 | 6 | #![feature(string_from_utf8_lossy_owned)] |
| 6 | 7 | #![feature(trait_alias)] |
| 7 | 8 | #![feature(try_blocks)] |
compiler/rustc_codegen_ssa/src/mir/operand.rs+49| ... | ... | @@ -718,6 +718,34 @@ impl<'a, 'tcx, V: CodegenObject> OperandRefBuilder<'tcx, V> { |
| 718 | 718 | OperandRefBuilder { val, layout } |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | /// Creates an initialized builder for updating an existing `operand`. | |
| 722 | /// | |
| 723 | /// ICEs for [`BackendRepr::Memory`] types (other than ZSTs), which use | |
| 724 | /// which use [`OperandValue::Ref`]. In this case, updates should be | |
| 725 | /// performed by writing into the place | |
| 726 | pub(super) fn from_existing(operand: OperandRef<'tcx, V>) -> Self { | |
| 727 | let layout = operand.layout; | |
| 728 | let val = match (operand.val, layout.backend_repr) { | |
| 729 | (OperandValue::ZeroSized, _) => OperandValueBuilder::ZeroSized, | |
| 730 | (OperandValue::Immediate(v), BackendRepr::Scalar(_)) => { | |
| 731 | OperandValueBuilder::Immediate(Either::Left(v)) | |
| 732 | } | |
| 733 | (OperandValue::Immediate(v), BackendRepr::SimdVector { .. }) => { | |
| 734 | OperandValueBuilder::Vector(Either::Left(v)) | |
| 735 | } | |
| 736 | (OperandValue::Pair(a, b), BackendRepr::ScalarPair(_, _)) => { | |
| 737 | OperandValueBuilder::Pair(Either::Left(a), Either::Left(b)) | |
| 738 | } | |
| 739 | (_, BackendRepr::Memory { .. }) => { | |
| 740 | bug!("Cannot use non-ZST Memory-ABI type in operand builder: {layout:?}"); | |
| 741 | } | |
| 742 | _ => { | |
| 743 | bug!("Operand cannot be used with `from_existing`: {operand:?}") | |
| 744 | } | |
| 745 | }; | |
| 746 | OperandRefBuilder { val, layout } | |
| 747 | } | |
| 748 | ||
| 721 | 749 | pub(super) fn insert_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
| 722 | 750 | &mut self, |
| 723 | 751 | bx: &mut Bx, |
| ... | ... | @@ -829,6 +857,27 @@ impl<'a, 'tcx, V: CodegenObject> OperandRefBuilder<'tcx, V> { |
| 829 | 857 | } |
| 830 | 858 | } |
| 831 | 859 | |
| 860 | /// Replaces the current immediate value at the offset `offset` | |
| 861 | /// with the value `imm`. A value must already be present. | |
| 862 | /// | |
| 863 | /// This is used along with [`Self::from_existing`] to perform in-place updates | |
| 864 | /// of any operand. | |
| 865 | pub(super) fn update_imm(&mut self, offset: Size, imm: V) { | |
| 866 | let is_zero_offset = offset == Size::ZERO; | |
| 867 | match &mut self.val { | |
| 868 | OperandValueBuilder::Immediate(val @ Either::Left(_)) if is_zero_offset => { | |
| 869 | *val = Either::Left(imm); | |
| 870 | } | |
| 871 | OperandValueBuilder::Pair(fst @ Either::Left(_), _) if is_zero_offset => { | |
| 872 | *fst = Either::Left(imm); | |
| 873 | } | |
| 874 | OperandValueBuilder::Pair(_, snd @ Either::Left(_)) if !is_zero_offset => { | |
| 875 | *snd = Either::Left(imm); | |
| 876 | } | |
| 877 | _ => bug!("Tried to update {imm:?} at offset {offset:?} of {self:?}"), | |
| 878 | } | |
| 879 | } | |
| 880 | ||
| 832 | 881 | /// After having set all necessary fields, this converts the builder back |
| 833 | 882 | /// to the normal `OperandRef`. |
| 834 | 883 | /// |
compiler/rustc_codegen_ssa/src/mir/retag.rs+185-21| ... | ... | @@ -4,19 +4,20 @@ |
| 4 | 4 | //! of an assignment. The first step to retagging is to generate a [`RetagPlan`], which |
| 5 | 5 | //! describes which pointers within the place or operand can be retagged. |
| 6 | 6 | |
| 7 | #![allow(unused)] | |
| 8 | use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, VariantIdx, Variants}; | |
| 7 | use rustc_abi::{FieldIdx, FieldsShape, Size, VariantIdx, Variants}; | |
| 9 | 8 | use rustc_ast::Mutability; |
| 10 | 9 | use rustc_data_structures::fx::FxIndexMap; |
| 11 | 10 | use rustc_middle::mir::{Rvalue, WithRetag}; |
| 12 | 11 | use rustc_middle::ty; |
| 13 | 12 | use rustc_middle::ty::layout::TyAndLayout; |
| 14 | 13 | |
| 15 | use crate::RetagInfo; | |
| 16 | 14 | use crate::mir::FunctionCx; |
| 17 | use crate::mir::operand::OperandRef; | |
| 15 | use crate::mir::operand::{OperandRef, OperandRefBuilder, OperandValue}; | |
| 18 | 16 | use crate::mir::place::PlaceRef; |
| 19 | use crate::traits::BuilderMethods; | |
| 17 | use crate::traits::{ | |
| 18 | BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods, | |
| 19 | }; | |
| 20 | use crate::{RetagFlags, RetagInfo}; | |
| 20 | 21 | |
| 21 | 22 | pub(crate) fn rvalue_needs_retag(rvalue: &Rvalue<'_>) -> bool { |
| 22 | 23 | // `Ref` has its own internal retagging |
| ... | ... | @@ -58,12 +59,6 @@ impl<'a, 'tcx, V> RetagPlan<V> { |
| 58 | 59 | if layout.is_sized() && layout.size < bx.tcx().data_layout.pointer_size() { |
| 59 | 60 | return None; |
| 60 | 61 | } |
| 61 | // SIMD vectors may only contain raw pointers, integers, and floating point values, | |
| 62 | // which do not need to be retagged. | |
| 63 | if matches!(layout.backend_repr, BackendRepr::SimdVector { .. }) { | |
| 64 | return None; | |
| 65 | } | |
| 66 | ||
| 67 | 62 | // Check the type of this value to see what to do with it (retag, or recurse). |
| 68 | 63 | match layout.ty.kind() { |
| 69 | 64 | &ty::Ref(_, pointee, mt) => { |
| ... | ... | @@ -168,12 +163,42 @@ impl<'a, 'tcx, V> RetagPlan<V> { |
| 168 | 163 | /// to types that are entirely covered by `UnsafePinned`, for which retags |
| 169 | 164 | /// are a no-op. |
| 170 | 165 | fn emit_retag<Bx: BuilderMethods<'a, 'tcx>>( |
| 171 | _bx: &mut Bx, | |
| 172 | _pointee_layout: TyAndLayout<'tcx>, | |
| 173 | _ptr_kind: Option<Mutability>, | |
| 174 | _is_fn_entry: bool, | |
| 166 | bx: &mut Bx, | |
| 167 | pointee_layout: TyAndLayout<'tcx>, | |
| 168 | ptr_kind: Option<Mutability>, | |
| 169 | is_fn_entry: bool, | |
| 175 | 170 | ) -> Option<RetagPlan<Bx::Value>> { |
| 176 | None | |
| 171 | let tcx = bx.tcx(); | |
| 172 | ||
| 173 | let pointee_ty = pointee_layout.ty; | |
| 174 | ||
| 175 | let is_mutable = matches!(ptr_kind, Some(Mutability::Mut) | None); | |
| 176 | let is_unpin = pointee_ty.is_unpin(tcx, bx.typing_env()); | |
| 177 | let is_freeze = pointee_ty.is_freeze(tcx, bx.typing_env()); | |
| 178 | let is_box = ptr_kind.is_none(); | |
| 179 | ||
| 180 | // `&mut !Unpin` is not protected | |
| 181 | let is_protected = is_fn_entry && (!is_mutable || is_unpin); | |
| 182 | ||
| 183 | if is_mutable && !is_unpin { | |
| 184 | return None; | |
| 185 | } | |
| 186 | ||
| 187 | let im_layout = bx.const_null(bx.type_ptr()); | |
| 188 | let pin_layout = bx.const_null(bx.type_ptr()); | |
| 189 | ||
| 190 | let mut flags = RetagFlags::empty(); | |
| 191 | flags.set(RetagFlags::IS_PROTECTED, is_protected); | |
| 192 | flags.set(RetagFlags::IS_MUTABLE, is_mutable); | |
| 193 | flags.set(RetagFlags::IS_FREEZE, is_freeze); | |
| 194 | flags.set(RetagFlags::IS_BOX, is_box); | |
| 195 | ||
| 196 | Some(RetagPlan::EmitRetag(RetagInfo { | |
| 197 | size: pointee_layout.size, | |
| 198 | im_layout, | |
| 199 | pin_layout, | |
| 200 | flags, | |
| 201 | })) | |
| 177 | 202 | } |
| 178 | 203 | } |
| 179 | 204 | |
| ... | ... | @@ -181,19 +206,158 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { |
| 181 | 206 | /// Retags the pointers within an [`OperandRef`]. |
| 182 | 207 | pub(crate) fn codegen_retag_operand( |
| 183 | 208 | &mut self, |
| 184 | _bx: &mut Bx, | |
| 209 | bx: &mut Bx, | |
| 185 | 210 | operand: OperandRef<'tcx, Bx::Value>, |
| 186 | _is_fn_entry: bool, | |
| 211 | is_fn_entry: bool, | |
| 187 | 212 | ) -> OperandRef<'tcx, Bx::Value> { |
| 213 | if let OperandValue::Ref(place_ref) = operand.val { | |
| 214 | let place_ref = place_ref.with_type(operand.layout); | |
| 215 | self.codegen_retag_place(bx, place_ref, is_fn_entry); | |
| 216 | } else if let Some(plan) = RetagPlan::<Bx::Value>::build(bx, operand.layout, is_fn_entry) { | |
| 217 | let mut builder = OperandRefBuilder::from_existing(operand); | |
| 218 | self.retag_operand(bx, &plan, operand, &mut builder, Size::ZERO); | |
| 219 | return builder.build(bx.cx()); | |
| 220 | } | |
| 188 | 221 | operand |
| 189 | 222 | } |
| 190 | 223 | |
| 191 | 224 | /// Retags the pointers within a [`PlaceRef`]. |
| 192 | 225 | pub(crate) fn codegen_retag_place( |
| 193 | 226 | &mut self, |
| 194 | _bx: &mut Bx, | |
| 195 | _place_ref: PlaceRef<'tcx, Bx::Value>, | |
| 196 | _is_fn_entry: bool, | |
| 227 | bx: &mut Bx, | |
| 228 | place_ref: PlaceRef<'tcx, Bx::Value>, | |
| 229 | is_fn_entry: bool, | |
| 197 | 230 | ) { |
| 231 | if let Some(plan) = RetagPlan::<Bx::Value>::build(bx, place_ref.layout, is_fn_entry) { | |
| 232 | self.retag_place(bx, &plan, place_ref); | |
| 233 | } | |
| 234 | } | |
| 235 | ||
| 236 | fn retag_operand( | |
| 237 | &mut self, | |
| 238 | bx: &mut Bx, | |
| 239 | plan: &RetagPlan<Bx::Value>, | |
| 240 | curr_operand: OperandRef<'tcx, Bx::Value>, | |
| 241 | builder: &mut OperandRefBuilder<'tcx, Bx::Value>, | |
| 242 | offset: Size, | |
| 243 | ) { | |
| 244 | match plan { | |
| 245 | RetagPlan::EmitRetag(info) => { | |
| 246 | let (pointer, _) = curr_operand.val.pointer_parts(); | |
| 247 | let retagged_pointer = bx.retag_reg(pointer, info); | |
| 248 | builder.update_imm(offset, retagged_pointer); | |
| 249 | } | |
| 250 | RetagPlan::Recurse { field_plans, variant_plans } => { | |
| 251 | let layout = curr_operand.layout; | |
| 252 | for (ix, plan) in field_plans { | |
| 253 | let inner_offset = layout.fields.offset(ix.as_usize()); | |
| 254 | let field_offset = offset + inner_offset; | |
| 255 | ||
| 256 | let field_layout = curr_operand.layout.field(bx, ix.index()); | |
| 257 | // Part of https://github.com/rust-lang/compiler-team/issues/838 | |
| 258 | if !bx.is_backend_ref(curr_operand.layout) && bx.is_backend_ref(field_layout) { | |
| 259 | // FIXME: support vector types, requires insert_element as part of cg-ssa | |
| 260 | } else { | |
| 261 | let field_operand = curr_operand.extract_field(self, bx, ix.as_usize()); | |
| 262 | self.retag_operand(bx, &plan, field_operand, builder, field_offset); | |
| 263 | } | |
| 264 | } | |
| 265 | ||
| 266 | if !variant_plans.is_empty() { | |
| 267 | let discr_ty = layout.ty.discriminant_ty(bx.tcx()); | |
| 268 | let discr_val = curr_operand.codegen_get_discr(self, bx, discr_ty); | |
| 269 | ||
| 270 | if let Some(val) = bx.const_to_opt_u128(discr_val, false) { | |
| 271 | let ix = VariantIdx::from_usize(val as usize); | |
| 272 | if let Some(plan) = variant_plans.get(&ix) { | |
| 273 | let mut variant_op = curr_operand; | |
| 274 | variant_op.layout = curr_operand.layout.for_variant(bx, ix); | |
| 275 | ||
| 276 | self.retag_operand(bx, plan, variant_op, builder, offset); | |
| 277 | } | |
| 278 | } else { | |
| 279 | // We create a temporary place to store the operand, because its value will differ | |
| 280 | // depending on the variant that we have. | |
| 281 | let scratch = PlaceRef::alloca(bx, curr_operand.layout); | |
| 282 | scratch.storage_live(bx); | |
| 283 | curr_operand.store_with_annotation(bx, scratch); | |
| 284 | ||
| 285 | // We retag the contents of the place | |
| 286 | self.retag_variants(bx, scratch, discr_val, variant_plans); | |
| 287 | ||
| 288 | // Afterward, we load the now-updated operand and end the lifetime of the place. | |
| 289 | let updated_op = bx.load_operand(scratch); | |
| 290 | scratch.storage_dead(bx); | |
| 291 | ||
| 292 | match updated_op.val { | |
| 293 | OperandValue::ZeroSized | OperandValue::Ref(_) => {} | |
| 294 | OperandValue::Immediate(imm) => builder.update_imm(offset, imm), | |
| 295 | OperandValue::Pair(fst, snd) => { | |
| 296 | builder.update_imm(offset, fst); | |
| 297 | builder.update_imm(offset + Size::from_bytes(1), snd) | |
| 298 | } | |
| 299 | } | |
| 300 | } | |
| 301 | } | |
| 302 | } | |
| 303 | } | |
| 304 | } | |
| 305 | ||
| 306 | fn retag_place( | |
| 307 | &mut self, | |
| 308 | bx: &mut Bx, | |
| 309 | plan: &RetagPlan<Bx::Value>, | |
| 310 | place: PlaceRef<'tcx, Bx::Value>, | |
| 311 | ) { | |
| 312 | match plan { | |
| 313 | RetagPlan::EmitRetag(info) => { | |
| 314 | bx.retag_mem(place.val.llval, info); | |
| 315 | } | |
| 316 | RetagPlan::Recurse { field_plans, variant_plans } => { | |
| 317 | for (ix, plan) in field_plans { | |
| 318 | let field_place = place.project_field(bx, ix.as_usize()); | |
| 319 | self.retag_place(bx, &plan, field_place); | |
| 320 | } | |
| 321 | if !variant_plans.is_empty() { | |
| 322 | let operand = bx.load_operand(place); | |
| 323 | let discr_ty = place.layout.ty.discriminant_ty(bx.tcx()); | |
| 324 | let discr_val = operand.codegen_get_discr(self, bx, discr_ty); | |
| 325 | self.retag_variants(bx, place, discr_val, variant_plans); | |
| 326 | } | |
| 327 | } | |
| 328 | } | |
| 329 | } | |
| 330 | ||
| 331 | /// Retags each variant of a [`PlaceRef`] with the given discriminant. | |
| 332 | fn retag_variants( | |
| 333 | &mut self, | |
| 334 | bx: &mut Bx, | |
| 335 | place: PlaceRef<'tcx, Bx::Value>, | |
| 336 | discr: Bx::Value, | |
| 337 | variant_plans: &FxIndexMap<VariantIdx, RetagPlan<Bx::Value>>, | |
| 338 | ) { | |
| 339 | let layout = place.layout; | |
| 340 | ||
| 341 | let root_block = bx.llbb(); | |
| 342 | let mut variant_blocks = Vec::with_capacity(variant_plans.len()); | |
| 343 | let join_block = bx.append_sibling_block("retag_join"); | |
| 344 | ||
| 345 | for (ix, plan) in variant_plans { | |
| 346 | let variant_discr = layout.ty.discriminant_for_variant(bx.tcx(), *ix); | |
| 347 | let variant_discr_val = variant_discr.expect("Invalid variant index.").val; | |
| 348 | ||
| 349 | let variant_block = bx.append_sibling_block("retag_variant"); | |
| 350 | bx.switch_to_block(variant_block); | |
| 351 | ||
| 352 | let variant_place = place.project_downcast(bx, *ix); | |
| 353 | self.retag_place(bx, plan, variant_place); | |
| 354 | ||
| 355 | variant_blocks.push((variant_discr_val, variant_block)); | |
| 356 | bx.br(join_block); | |
| 357 | } | |
| 358 | ||
| 359 | bx.switch_to_block(root_block); | |
| 360 | bx.switch(discr, join_block, variant_blocks.into_iter()); | |
| 361 | bx.switch_to_block(join_block); | |
| 198 | 362 | } |
| 199 | 363 | } |
compiler/rustc_expand/src/base.rs+18-57| ... | ... | @@ -503,39 +503,27 @@ pub trait MacResult { |
| 503 | 503 | } |
| 504 | 504 | } |
| 505 | 505 | |
| 506 | macro_rules! make_MacEager { | |
| 507 | ( $( $fld:ident: $t:ty, )* ) => { | |
| 508 | /// `MacResult` implementation for the common case where you've already | |
| 509 | /// built each form of AST that you might return. | |
| 510 | #[derive(Default)] | |
| 511 | pub struct MacEager { | |
| 512 | $( | |
| 513 | pub $fld: Option<$t>, | |
| 514 | )* | |
| 515 | } | |
| 506 | /// `MacResult` implementation for the common case where you've already | |
| 507 | /// built each form of AST that you might return. | |
| 508 | #[derive(Default)] | |
| 509 | pub struct MacEager { | |
| 510 | pub expr: Option<Box<ast::Expr>>, | |
| 511 | pub items: Option<SmallVec<[Box<ast::Item>; 1]>>, | |
| 512 | pub ty: Option<Box<ast::Ty>>, | |
| 513 | } | |
| 516 | 514 | |
| 517 | impl MacEager { | |
| 518 | $( | |
| 519 | pub fn $fld(v: $t) -> Box<dyn MacResult> { | |
| 520 | Box::new(MacEager { | |
| 521 | $fld: Some(v), | |
| 522 | ..Default::default() | |
| 523 | }) | |
| 524 | } | |
| 525 | )* | |
| 526 | } | |
| 515 | impl MacEager { | |
| 516 | pub fn expr(v: Box<ast::Expr>) -> Box<dyn MacResult> { | |
| 517 | Box::new(MacEager { expr: Some(v), ..Default::default() }) | |
| 518 | } | |
| 519 | ||
| 520 | pub fn items(v: SmallVec<[Box<ast::Item>; 1]>) -> Box<dyn MacResult> { | |
| 521 | Box::new(MacEager { items: Some(v), ..Default::default() }) | |
| 527 | 522 | } |
| 528 | } | |
| 529 | 523 | |
| 530 | make_MacEager! { | |
| 531 | expr: Box<ast::Expr>, | |
| 532 | pat: Box<ast::Pat>, | |
| 533 | items: SmallVec<[Box<ast::Item>; 1]>, | |
| 534 | impl_items: SmallVec<[Box<ast::AssocItem>; 1]>, | |
| 535 | trait_items: SmallVec<[Box<ast::AssocItem>; 1]>, | |
| 536 | foreign_items: SmallVec<[Box<ast::ForeignItem>; 1]>, | |
| 537 | stmts: SmallVec<[ast::Stmt; 1]>, | |
| 538 | ty: Box<ast::Ty>, | |
| 524 | pub fn ty(v: Box<ast::Ty>) -> Box<dyn MacResult> { | |
| 525 | Box::new(MacEager { ty: Some(v), ..Default::default() }) | |
| 526 | } | |
| 539 | 527 | } |
| 540 | 528 | |
| 541 | 529 | impl MacResult for MacEager { |
| ... | ... | @@ -547,34 +535,7 @@ impl MacResult for MacEager { |
| 547 | 535 | self.items |
| 548 | 536 | } |
| 549 | 537 | |
| 550 | fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> { | |
| 551 | self.impl_items | |
| 552 | } | |
| 553 | ||
| 554 | fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> { | |
| 555 | self.impl_items | |
| 556 | } | |
| 557 | ||
| 558 | fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> { | |
| 559 | self.trait_items | |
| 560 | } | |
| 561 | ||
| 562 | fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> { | |
| 563 | self.foreign_items | |
| 564 | } | |
| 565 | ||
| 566 | fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> { | |
| 567 | if self.stmts.as_ref().is_none_or(|s| s.is_empty()) { | |
| 568 | make_stmts_default(self.make_expr()) | |
| 569 | } else { | |
| 570 | self.stmts | |
| 571 | } | |
| 572 | } | |
| 573 | ||
| 574 | 538 | fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> { |
| 575 | if let Some(p) = self.pat { | |
| 576 | return Some(p); | |
| 577 | } | |
| 578 | 539 | if let Some(e) = self.expr { |
| 579 | 540 | if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) { |
| 580 | 541 | return Some(Box::new(ast::Pat { |
compiler/rustc_hir_analysis/src/check/mod.rs+2-3| ... | ... | @@ -479,10 +479,9 @@ fn fn_sig_suggestion<'tcx>( |
| 479 | 479 | } |
| 480 | 480 | } |
| 481 | 481 | }; |
| 482 | Some(format!("{splat}{arg_ty}")) | |
| 482 | format!("{splat}{arg_ty}") | |
| 483 | 483 | }) |
| 484 | .chain(std::iter::once(if sig.c_variadic() { Some("...".to_string()) } else { None })) | |
| 485 | .flatten() | |
| 484 | .chain(if sig.c_variadic() { Some("...".to_string()) } else { None }) | |
| 486 | 485 | .collect::<Vec<String>>() |
| 487 | 486 | .join(", "); |
| 488 | 487 | let mut output = sig.output(); |
compiler/rustc_hir_analysis/src/check/wfcheck.rs+2-2| ... | ... | @@ -1217,7 +1217,7 @@ fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { |
| 1217 | 1217 | // does the function have an EiiImpl attribute? that contains the defid of a *macro* |
| 1218 | 1218 | // that was used to mark the implementation. This is a two step process. |
| 1219 | 1219 | for EiiImpl { resolution, span, .. } in |
| 1220 | find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten() | |
| 1220 | find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() | |
| 1221 | 1221 | { |
| 1222 | 1222 | let (foreign_item, name) = match resolution { |
| 1223 | 1223 | EiiImplResolution::Macro(def_id) => { |
| ... | ... | @@ -1244,7 +1244,7 @@ fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) |
| 1244 | 1244 | // does the function have an EiiImpl attribute? that contains the defid of a *macro* |
| 1245 | 1245 | // that was used to mark the implementation. This is a two step process. |
| 1246 | 1246 | for EiiImpl { resolution, span, .. } in |
| 1247 | find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten() | |
| 1247 | find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() | |
| 1248 | 1248 | { |
| 1249 | 1249 | let (foreign_item, name) = match resolution { |
| 1250 | 1250 | EiiImplResolution::Macro(def_id) => { |
compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs+9-7| ... | ... | @@ -984,15 +984,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 984 | 984 | ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { |
| 985 | 985 | // `<Foo as Iterator>::Item = String`. |
| 986 | 986 | let projection_term = pred.projection_term; |
| 987 | let quiet_projection_term = projection_term | |
| 988 | .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO)); | |
| 989 | ||
| 990 | 987 | let term = pred.term; |
| 988 | let self_ty = projection_term.args.get(0).and_then(|arg| arg.as_type())?; | |
| 989 | ||
| 991 | 990 | let obligation = format!("{projection_term} = {term}"); |
| 991 | let quiet_projection_term = projection_term | |
| 992 | .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO)); | |
| 992 | 993 | let quiet = format!("{quiet_projection_term} = {term}"); |
| 993 | 994 | |
| 994 | bound_span_label(projection_term.self_ty(), &obligation, &quiet); | |
| 995 | Some((obligation, projection_term.self_ty())) | |
| 995 | bound_span_label(self_ty, &obligation, &quiet); | |
| 996 | ||
| 997 | Some(obligation) | |
| 996 | 998 | } |
| 997 | 999 | ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => { |
| 998 | 1000 | let p = poly_trait_ref.trait_ref; |
| ... | ... | @@ -1001,7 +1003,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 1001 | 1003 | let obligation = format!("{self_ty}: {path}"); |
| 1002 | 1004 | let quiet = format!("_: {path}"); |
| 1003 | 1005 | bound_span_label(self_ty, &obligation, &quiet); |
| 1004 | Some((obligation, self_ty)) | |
| 1006 | Some(obligation) | |
| 1005 | 1007 | } |
| 1006 | 1008 | _ => None, |
| 1007 | 1009 | } |
| ... | ... | @@ -1013,7 +1015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 1013 | 1015 | .into_iter() |
| 1014 | 1016 | .map(|error| error.root_obligation.predicate) |
| 1015 | 1017 | .filter_map(format_pred) |
| 1016 | .map(|(p, _)| format!("`{p}`")) | |
| 1018 | .map(|p| format!("`{p}`")) | |
| 1017 | 1019 | .collect(); |
| 1018 | 1020 | bounds.sort(); |
| 1019 | 1021 | bounds.dedup(); |
compiler/rustc_hir_analysis/src/lib.rs+1| ... | ... | @@ -60,6 +60,7 @@ This API is completely unstable and subject to change. |
| 60 | 60 | #![feature(gen_blocks)] |
| 61 | 61 | #![feature(iter_intersperse)] |
| 62 | 62 | #![feature(never_type)] |
| 63 | #![feature(option_into_flat_iter)] | |
| 63 | 64 | #![feature(slice_partition_dedup)] |
| 64 | 65 | #![feature(try_blocks)] |
| 65 | 66 | #![feature(unwrap_infallible)] |
compiler/rustc_hir_typeck/src/coercion.rs+1-14| ... | ... | @@ -673,7 +673,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { |
| 673 | 673 | let mut coercion = self.unify_and( |
| 674 | 674 | coerce_target, |
| 675 | 675 | target, |
| 676 | reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]), | |
| 676 | reborrow.map(|(deref, autoref)| [deref, autoref]).into_flat_iter(), | |
| 677 | 677 | Adjust::Pointer(PointerCoercion::Unsize), |
| 678 | 678 | ForceLeakCheck::No, |
| 679 | 679 | )?; |
| ... | ... | @@ -737,19 +737,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { |
| 737 | 737 | { |
| 738 | 738 | self.resolve_vars_if_possible(trait_pred) |
| 739 | 739 | } |
| 740 | // Eagerly process alias-relate obligations in new trait solver, | |
| 741 | // since these can be emitted in the process of solving trait goals, | |
| 742 | // but we need to constrain vars before processing goals mentioning | |
| 743 | // them. | |
| 744 | Some(ty::PredicateKind::AliasRelate(..)) => { | |
| 745 | let ocx = ObligationCtxt::new(self); | |
| 746 | ocx.register_obligation(obligation); | |
| 747 | if !ocx.try_evaluate_obligations().is_empty() { | |
| 748 | return Err(TypeError::Mismatch); | |
| 749 | } | |
| 750 | coercion.obligations.extend(ocx.into_pending_obligations()); | |
| 751 | continue; | |
| 752 | } | |
| 753 | 740 | _ => { |
| 754 | 741 | coercion.obligations.push(obligation); |
| 755 | 742 | continue; |
compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs-1| ... | ... | @@ -55,7 +55,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 55 | 55 | | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) |
| 56 | 56 | | ty::PredicateKind::DynCompatible(..) |
| 57 | 57 | | ty::PredicateKind::NormalizesTo(..) |
| 58 | | ty::PredicateKind::AliasRelate(..) | |
| 59 | 58 | | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) |
| 60 | 59 | | ty::PredicateKind::ConstEquate(..) |
| 61 | 60 | | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) |
compiler/rustc_hir_typeck/src/lib.rs+1| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | #![feature(iter_intersperse)] |
| 4 | 4 | #![feature(iter_order_by)] |
| 5 | 5 | #![feature(never_type)] |
| 6 | #![feature(option_into_flat_iter)] | |
| 6 | 7 | #![feature(option_reference_flattening)] |
| 7 | 8 | #![feature(trim_prefix_suffix)] |
| 8 | 9 | // tidy-alphabetical-end |
compiler/rustc_hir_typeck/src/method/suggest.rs+1-1| ... | ... | @@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 266 | 266 | // NOTE: Reporting a method error should also suppress any unused trait errors, |
| 267 | 267 | // since the method error is very possibly the reason why the trait wasn't used. |
| 268 | 268 | for &import_id in |
| 269 | self.tcx.in_scope_traits(call_id).into_iter().flatten().flat_map(|c| c.import_ids) | |
| 269 | self.tcx.in_scope_traits(call_id).into_flat_iter().flat_map(|c| c.import_ids) | |
| 270 | 270 | { |
| 271 | 271 | self.typeck_results.borrow_mut().used_trait_imports.insert(import_id); |
| 272 | 272 | } |
compiler/rustc_infer/src/infer/relate/generalize.rs+54-18| ... | ... | @@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId; |
| 6 | 6 | use rustc_middle::bug; |
| 7 | 7 | use rustc_middle::ty::error::TypeError; |
| 8 | 8 | use rustc_middle::ty::{ |
| 9 | self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, | |
| 10 | TypeVisitableExt, TypeVisitor, | |
| 9 | self, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, | |
| 10 | TypeVisitor, | |
| 11 | 11 | }; |
| 12 | 12 | use rustc_span::Span; |
| 13 | 13 | use tracing::{debug, instrument, warn}; |
| ... | ... | @@ -168,25 +168,61 @@ impl<'tcx> InferCtxt<'tcx> { |
| 168 | 168 | // cyclic type. We instead delay the unification in case |
| 169 | 169 | // the alias can be normalized to something which does not |
| 170 | 170 | // mention `?0`. |
| 171 | let Some(source_alias) = source_term.to_alias_term() else { | |
| 172 | bug!("generalized `{source_term:?} to infer, not an alias"); | |
| 173 | }; | |
| 171 | 174 | if self.next_trait_solver() { |
| 172 | let (lhs, rhs, direction) = match instantiation_variance { | |
| 173 | ty::Invariant => { | |
| 174 | (generalized_term, source_term, AliasRelationDirection::Equate) | |
| 175 | } | |
| 176 | ty::Covariant => { | |
| 177 | (generalized_term, source_term, AliasRelationDirection::Subtype) | |
| 178 | } | |
| 179 | ty::Contravariant => { | |
| 180 | (source_term, generalized_term, AliasRelationDirection::Subtype) | |
| 175 | if let Some(generalized_ty) = generalized_term.as_type() { | |
| 176 | match instantiation_variance { | |
| 177 | ty::Invariant => relation.register_predicates([ty::ProjectionPredicate { | |
| 178 | projection_term: source_alias.into(), | |
| 179 | term: generalized_ty.into(), | |
| 180 | }]), | |
| 181 | ty::Covariant => { | |
| 182 | // Generate a new var, then do: | |
| 183 | // `source_alias == ?A && ?A <: generalized_ty` | |
| 184 | let new_var = self.next_ty_var(relation.span()); | |
| 185 | relation.register_predicates([ | |
| 186 | ty::PredicateKind::Subtype(ty::SubtypePredicate { | |
| 187 | a_is_expected: !target_is_expected, | |
| 188 | a: new_var, | |
| 189 | b: generalized_ty, | |
| 190 | }), | |
| 191 | ty::PredicateKind::Clause(ty::ClauseKind::Projection( | |
| 192 | ty::ProjectionPredicate { | |
| 193 | projection_term: source_alias.into(), | |
| 194 | term: new_var.into(), | |
| 195 | }, | |
| 196 | )), | |
| 197 | ]); | |
| 198 | } | |
| 199 | ty::Contravariant => { | |
| 200 | // a :> b is b <: a | |
| 201 | let new_var = self.next_ty_var(relation.span()); | |
| 202 | relation.register_predicates([ | |
| 203 | ty::PredicateKind::Subtype(ty::SubtypePredicate { | |
| 204 | a_is_expected: target_is_expected, | |
| 205 | a: generalized_ty, | |
| 206 | b: new_var, | |
| 207 | }), | |
| 208 | ty::PredicateKind::Clause(ty::ClauseKind::Projection( | |
| 209 | ty::ProjectionPredicate { | |
| 210 | projection_term: source_alias.into(), | |
| 211 | term: new_var.into(), | |
| 212 | }, | |
| 213 | )), | |
| 214 | ]); | |
| 215 | } | |
| 216 | ty::Bivariant => unreachable!("bivariant generalization"), | |
| 181 | 217 | } |
| 182 | ty::Bivariant => unreachable!("bivariant generalization"), | |
| 183 | }; | |
| 184 | ||
| 185 | relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]); | |
| 218 | } else { | |
| 219 | debug_assert_eq!(instantiation_variance, ty::Variance::Invariant); | |
| 220 | relation.register_predicates([ty::ProjectionPredicate { | |
| 221 | projection_term: source_alias, | |
| 222 | term: generalized_term, | |
| 223 | }]); | |
| 224 | } | |
| 186 | 225 | } else { |
| 187 | let Some(source_alias) = source_term.to_alias_term() else { | |
| 188 | bug!("generalized `{source_term:?} to infer, not an alias"); | |
| 189 | }; | |
| 190 | 226 | match source_alias.kind { |
| 191 | 227 | ty::AliasTermKind::ProjectionTy { .. } |
| 192 | 228 | | ty::AliasTermKind::ProjectionConst { .. } => { |
compiler/rustc_infer/src/infer/relate/lattice.rs+3-7| ... | ... | @@ -291,12 +291,8 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, 'tcx> { |
| 291 | 291 | })) |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { | |
| 295 | self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( | |
| 296 | a.into(), | |
| 297 | b.into(), | |
| 298 | // FIXME(deferred_projection_equality): This isn't right, I think? | |
| 299 | ty::AliasRelationDirection::Equate, | |
| 300 | ))]); | |
| 294 | fn ambient_variance(&self) -> ty::Variance { | |
| 295 | // FIXME(deferred_projection_equality): This isn't right, I think? | |
| 296 | ty::Variance::Invariant | |
| 301 | 297 | } |
| 302 | 298 | } |
compiler/rustc_infer/src/infer/relate/type_relating.rs+2-22| ... | ... | @@ -384,27 +384,7 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx> |
| 384 | 384 | })) |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { | |
| 388 | self.register_predicates([ty::Binder::dummy(match self.ambient_variance { | |
| 389 | ty::Covariant => ty::PredicateKind::AliasRelate( | |
| 390 | a.into(), | |
| 391 | b.into(), | |
| 392 | ty::AliasRelationDirection::Subtype, | |
| 393 | ), | |
| 394 | // a :> b is b <: a | |
| 395 | ty::Contravariant => ty::PredicateKind::AliasRelate( | |
| 396 | b.into(), | |
| 397 | a.into(), | |
| 398 | ty::AliasRelationDirection::Subtype, | |
| 399 | ), | |
| 400 | ty::Invariant => ty::PredicateKind::AliasRelate( | |
| 401 | a.into(), | |
| 402 | b.into(), | |
| 403 | ty::AliasRelationDirection::Equate, | |
| 404 | ), | |
| 405 | ty::Bivariant => { | |
| 406 | unreachable!("Expected bivariance to be handled in relate_with_variance") | |
| 407 | } | |
| 408 | })]); | |
| 387 | fn ambient_variance(&self) -> ty::Variance { | |
| 388 | self.ambient_variance | |
| 409 | 389 | } |
| 410 | 390 | } |
compiler/rustc_lint/src/if_let_rescope.rs+1-2| ... | ... | @@ -349,8 +349,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { |
| 349 | 349 | closing_brackets |
| 350 | 350 | .empty_alt |
| 351 | 351 | .then_some(" _ => {}".chars()) |
| 352 | .into_iter() | |
| 353 | .flatten() | |
| 352 | .into_flat_iter() | |
| 354 | 353 | .chain(repeat_n('}', closing_brackets.count)) |
| 355 | 354 | .collect(), |
| 356 | 355 | )); |
compiler/rustc_lint/src/lib.rs+1| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | #![allow(internal_features)] |
| 24 | 24 | #![feature(deref_patterns)] |
| 25 | 25 | #![feature(iter_order_by)] |
| 26 | #![feature(option_into_flat_iter)] | |
| 26 | 27 | #![feature(rustc_attrs)] |
| 27 | 28 | #![feature(titlecase)] |
| 28 | 29 | #![feature(try_blocks)] |
compiler/rustc_lint/src/types.rs+7-3| ... | ... | @@ -793,7 +793,7 @@ fn get_nullable_type<'tcx>( |
| 793 | 793 | return get_nullable_type(tcx, typing_env, inner_field_ty); |
| 794 | 794 | } |
| 795 | 795 | ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base), |
| 796 | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty, | |
| 796 | ty::Int(_) | ty::Uint(_) | ty::Char | ty::RawPtr(..) => ty, | |
| 797 | 797 | // As these types are always non-null, the nullable equivalent of |
| 798 | 798 | // `Option<T>` of these types are their raw pointer counterparts. |
| 799 | 799 | ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), |
| ... | ... | @@ -895,10 +895,14 @@ pub(crate) fn repr_nullable_ptr<'tcx>( |
| 895 | 895 | WrappingRange { start: 0, end } |
| 896 | 896 | if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => |
| 897 | 897 | { |
| 898 | return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); | |
| 898 | return Some(get_nullable_type(tcx, typing_env, field_ty).expect( | |
| 899 | "known non-null scalar type should have a nullable representation", | |
| 900 | )); | |
| 899 | 901 | } |
| 900 | 902 | WrappingRange { start: 1, .. } => { |
| 901 | return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); | |
| 903 | return Some(get_nullable_type(tcx, typing_env, field_ty).expect( | |
| 904 | "known non-null scalar type should have a nullable representation", | |
| 905 | )); | |
| 902 | 906 | } |
| 903 | 907 | WrappingRange { start, end } => { |
| 904 | 908 | unreachable!("Unhandled start and end range: ({}, {})", start, end) |
compiler/rustc_metadata/src/eii.rs+1-1| ... | ... | @@ -25,7 +25,7 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap |
| 25 | 25 | |
| 26 | 26 | // iterate over all items in the current crate |
| 27 | 27 | for id in tcx.hir_crate_items(()).eiis() { |
| 28 | for i in find_attr!(tcx, id, EiiImpls(e) => e).into_iter().flatten() { | |
| 28 | for i in find_attr!(tcx, id, EiiImpls(e) => e).into_flat_iter() { | |
| 29 | 29 | let decl = match i.resolution { |
| 30 | 30 | EiiImplResolution::Macro(macro_defid) => { |
| 31 | 31 | // 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) |
compiler/rustc_metadata/src/lib.rs+1| ... | ... | @@ -8,6 +8,7 @@ |
| 8 | 8 | #![feature(macro_metavar_expr)] |
| 9 | 9 | #![feature(min_specialization)] |
| 10 | 10 | #![feature(never_type)] |
| 11 | #![feature(option_into_flat_iter)] | |
| 11 | 12 | #![feature(proc_macro_internals)] |
| 12 | 13 | #![feature(trusted_len)] |
| 13 | 14 | // tidy-alphabetical-end |
compiler/rustc_metadata/src/locator.rs+2-3| ... | ... | @@ -325,9 +325,8 @@ impl<'a> CrateLocator<'a> { |
| 325 | 325 | sess.opts |
| 326 | 326 | .externs |
| 327 | 327 | .get(crate_name.as_str()) |
| 328 | .into_iter() | |
| 329 | .filter_map(|entry| entry.files()) | |
| 330 | .flatten() | |
| 328 | .and_then(|entry| entry.files()) | |
| 329 | .into_flat_iter() | |
| 331 | 330 | .cloned() |
| 332 | 331 | .collect() |
| 333 | 332 | } else { |
compiler/rustc_metadata/src/native_libs.rs+1-3| ... | ... | @@ -248,9 +248,7 @@ impl<'tcx> Collector<'tcx> { |
| 248 | 248 | return; |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | for attr in | |
| 252 | find_attr!(self.tcx, def_id, Link(links, _) => links).iter().map(|v| v.iter()).flatten() | |
| 253 | { | |
| 251 | for attr in find_attr!(self.tcx, def_id, Link(links, _) => links).into_flat_iter() { | |
| 254 | 252 | let dll_imports = match attr.kind { |
| 255 | 253 | NativeLibKind::RawDylib { .. } => foreign_items |
| 256 | 254 | .iter() |
compiler/rustc_metadata/src/rmeta/decoder.rs+6-4| ... | ... | @@ -2038,10 +2038,12 @@ impl CrateMetadata { |
| 2038 | 2038 | krate: CrateNum, |
| 2039 | 2039 | ) -> impl Iterator<Item = DefId> { |
| 2040 | 2040 | gen move { |
| 2041 | for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| { | |
| 2042 | data.macros.decode((self, tcx)).map(move |(index, _)| DefId { index, krate }) | |
| 2043 | }) { | |
| 2044 | yield def_id; | |
| 2041 | if let Some(data) = &self.root.proc_macro_data { | |
| 2042 | for def_id in | |
| 2043 | data.macros.decode((self, tcx)).map(move |(index, _)| DefId { index, krate }) | |
| 2044 | { | |
| 2045 | yield def_id; | |
| 2046 | } | |
| 2045 | 2047 | } |
| 2046 | 2048 | } |
| 2047 | 2049 | } |
compiler/rustc_middle/src/lib.rs+1| ... | ... | @@ -46,6 +46,7 @@ |
| 46 | 46 | #![feature(min_specialization)] |
| 47 | 47 | #![feature(negative_impls)] |
| 48 | 48 | #![feature(never_type)] |
| 49 | #![feature(option_into_flat_iter)] | |
| 49 | 50 | #![feature(ptr_alignment_type)] |
| 50 | 51 | #![feature(range_bounds_is_empty)] |
| 51 | 52 | #![feature(rustc_attrs)] |
compiler/rustc_middle/src/mir/consts.rs+1-1| ... | ... | @@ -18,7 +18,7 @@ use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; |
| 18 | 18 | /// Represents the result of const evaluation via the `eval_to_allocation` query. |
| 19 | 19 | /// Not to be confused with `ConstAllocation`, which directly refers to the underlying data! |
| 20 | 20 | /// Here we indirect via an `AllocId`. |
| 21 | #[derive(Copy, Clone, StableHash, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)] | |
| 21 | #[derive(Copy, Clone, StableHash, TyEncodable, TyDecodable, Debug, Eq, PartialEq)] | |
| 22 | 22 | pub struct ConstAlloc<'tcx> { |
| 23 | 23 | /// The value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory` |
| 24 | 24 | /// (so you can use `AllocMap::unwrap_memory`). |
compiler/rustc_middle/src/mir/coverage.rs+1-1| ... | ... | @@ -70,7 +70,7 @@ impl Debug for CovTerm { |
| 70 | 70 | } |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 73 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash)] | |
| 74 | 74 | pub enum CoverageKind { |
| 75 | 75 | /// Marks a span that might otherwise not be represented in MIR, so that |
| 76 | 76 | /// coverage instrumentation can associate it with its enclosing block/BCB. |
compiler/rustc_middle/src/mir/mod.rs+1-1| ... | ... | @@ -1558,7 +1558,7 @@ impl UserTypeProjections { |
| 1558 | 1558 | /// * `let (x, _): T = ...` -- here, the `projs` vector would contain |
| 1559 | 1559 | /// `field[0]` (aka `.0`), indicating that the type of `s` is |
| 1560 | 1560 | /// determined by finding the type of the `.0` field from `T`. |
| 1561 | #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] | |
| 1561 | #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] | |
| 1562 | 1562 | #[derive(TypeFoldable, TypeVisitable)] |
| 1563 | 1563 | pub struct UserTypeProjection { |
| 1564 | 1564 | pub base: UserTypeAnnotationIndex, |
compiler/rustc_middle/src/mir/syntax.rs+21-39| ... | ... | @@ -300,7 +300,7 @@ pub enum FakeBorrowKind { |
| 300 | 300 | /// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which |
| 301 | 301 | /// ones you do not have to worry about. The MIR validator will generally enforce such restrictions, |
| 302 | 302 | /// causing an ICE if they are violated. |
| 303 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 303 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash)] | |
| 304 | 304 | #[derive(TypeFoldable, TypeVisitable)] |
| 305 | 305 | pub enum StatementKind<'tcx> { |
| 306 | 306 | /// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except |
| ... | ... | @@ -455,17 +455,8 @@ pub enum StatementKind<'tcx> { |
| 455 | 455 | }, |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | #[derive( | |
| 459 | Clone, | |
| 460 | TyEncodable, | |
| 461 | TyDecodable, | |
| 462 | Debug, | |
| 463 | PartialEq, | |
| 464 | Hash, | |
| 465 | StableHash, | |
| 466 | TypeFoldable, | |
| 467 | TypeVisitable | |
| 468 | )] | |
| 458 | #[derive(Clone, TyEncodable, TyDecodable, Debug, PartialEq, StableHash)] | |
| 459 | #[derive(TypeFoldable, TypeVisitable)] | |
| 469 | 460 | pub enum NonDivergingIntrinsic<'tcx> { |
| 470 | 461 | /// Denotes a call to the intrinsic function `assume`. |
| 471 | 462 | /// |
| ... | ... | @@ -492,7 +483,7 @@ pub enum NonDivergingIntrinsic<'tcx> { |
| 492 | 483 | } |
| 493 | 484 | |
| 494 | 485 | /// Describes whether this operand use performs a retag. |
| 495 | #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, StableHash)] | |
| 486 | #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, StableHash)] | |
| 496 | 487 | #[rustc_pass_by_value] |
| 497 | 488 | pub enum WithRetag { |
| 498 | 489 | Yes, |
| ... | ... | @@ -511,7 +502,7 @@ impl WithRetag { |
| 511 | 502 | } |
| 512 | 503 | |
| 513 | 504 | /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. |
| 514 | #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, StableHash, PartialEq)] | |
| 505 | #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, StableHash, PartialEq)] | |
| 515 | 506 | pub enum FakeReadCause { |
| 516 | 507 | /// A fake read injected into a match guard to ensure that the discriminants |
| 517 | 508 | /// that are being matched on aren't modified while the match guard is being |
| ... | ... | @@ -617,7 +608,7 @@ pub enum FakeReadCause { |
| 617 | 608 | ForIndex, |
| 618 | 609 | } |
| 619 | 610 | |
| 620 | #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 611 | #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, StableHash)] | |
| 621 | 612 | #[derive(TypeFoldable, TypeVisitable)] |
| 622 | 613 | pub struct CopyNonOverlapping<'tcx> { |
| 623 | 614 | pub src: Operand<'tcx>, |
| ... | ... | @@ -628,7 +619,7 @@ pub struct CopyNonOverlapping<'tcx> { |
| 628 | 619 | |
| 629 | 620 | /// Represents how a [`TerminatorKind::Call`] was constructed. |
| 630 | 621 | /// Used only for diagnostics. |
| 631 | #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, StableHash)] | |
| 622 | #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, StableHash)] | |
| 632 | 623 | #[derive(TypeFoldable, TypeVisitable)] |
| 633 | 624 | pub enum CallSource { |
| 634 | 625 | /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` |
| ... | ... | @@ -648,7 +639,7 @@ pub enum CallSource { |
| 648 | 639 | Normal, |
| 649 | 640 | } |
| 650 | 641 | |
| 651 | #[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] | |
| 642 | #[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] | |
| 652 | 643 | #[derive(TypeFoldable, TypeVisitable)] |
| 653 | 644 | /// The macro that an inline assembly block was created by |
| 654 | 645 | pub enum InlineAsmMacro { |
| ... | ... | @@ -688,7 +679,7 @@ pub enum InlineAsmMacro { |
| 688 | 679 | /// deleting self edges and duplicate edges in the process. Now remove all vertices from `G` |
| 689 | 680 | /// that are not cleanup vertices or are not reachable. The resulting graph must be an inverted |
| 690 | 681 | /// tree, that is each vertex may have at most one successor and there may be no cycles. |
| 691 | #[derive(Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq, TypeFoldable, TypeVisitable)] | |
| 682 | #[derive(Clone, TyEncodable, TyDecodable, StableHash, PartialEq, TypeFoldable, TypeVisitable)] | |
| 692 | 683 | pub enum TerminatorKind<'tcx> { |
| 693 | 684 | /// Block has one successor; we continue execution there. |
| 694 | 685 | Goto { target: BasicBlock }, |
| ... | ... | @@ -973,22 +964,13 @@ pub enum TerminatorKind<'tcx> { |
| 973 | 964 | }, |
| 974 | 965 | } |
| 975 | 966 | |
| 976 | #[derive( | |
| 977 | Clone, | |
| 978 | Debug, | |
| 979 | TyEncodable, | |
| 980 | TyDecodable, | |
| 981 | Hash, | |
| 982 | StableHash, | |
| 983 | PartialEq, | |
| 984 | TypeFoldable, | |
| 985 | TypeVisitable | |
| 986 | )] | |
| 967 | #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq)] | |
| 968 | #[derive(TypeFoldable, TypeVisitable)] | |
| 987 | 969 | pub enum BackwardIncompatibleDropReason { |
| 988 | 970 | Edition2024, |
| 989 | 971 | } |
| 990 | 972 | |
| 991 | #[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq)] | |
| 973 | #[derive(Debug, Clone, TyEncodable, TyDecodable, StableHash, PartialEq)] | |
| 992 | 974 | pub struct SwitchTargets { |
| 993 | 975 | /// Possible values. For each value, the location to branch to is found in |
| 994 | 976 | /// the corresponding element in the `targets` vector. |
| ... | ... | @@ -1018,7 +1000,7 @@ pub struct SwitchTargets { |
| 1018 | 1000 | } |
| 1019 | 1001 | |
| 1020 | 1002 | /// Action to be taken when a stack unwind happens. |
| 1021 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 1003 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] | |
| 1022 | 1004 | #[derive(TypeFoldable, TypeVisitable)] |
| 1023 | 1005 | pub enum UnwindAction { |
| 1024 | 1006 | /// No action is to be taken. Continue unwinding. |
| ... | ... | @@ -1037,7 +1019,7 @@ pub enum UnwindAction { |
| 1037 | 1019 | } |
| 1038 | 1020 | |
| 1039 | 1021 | /// The reason we are terminating the process during unwinding. |
| 1040 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 1022 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] | |
| 1041 | 1023 | #[derive(TypeFoldable, TypeVisitable)] |
| 1042 | 1024 | pub enum UnwindTerminateReason { |
| 1043 | 1025 | /// Unwinding is just not possible given the ABI of this function. |
| ... | ... | @@ -1048,7 +1030,7 @@ pub enum UnwindTerminateReason { |
| 1048 | 1030 | } |
| 1049 | 1031 | |
| 1050 | 1032 | /// Information about an assertion failure. |
| 1051 | #[derive(Clone, Hash, StableHash, PartialEq, Debug)] | |
| 1033 | #[derive(Clone, StableHash, PartialEq, Debug)] | |
| 1052 | 1034 | #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] |
| 1053 | 1035 | pub enum AssertKind<O> { |
| 1054 | 1036 | BoundsCheck { len: O, index: O }, |
| ... | ... | @@ -1064,7 +1046,7 @@ pub enum AssertKind<O> { |
| 1064 | 1046 | InvalidEnumConstruction(O), |
| 1065 | 1047 | } |
| 1066 | 1048 | |
| 1067 | #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 1049 | #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, StableHash)] | |
| 1068 | 1050 | #[derive(TypeFoldable, TypeVisitable)] |
| 1069 | 1051 | pub enum InlineAsmOperand<'tcx> { |
| 1070 | 1052 | In { |
| ... | ... | @@ -1292,7 +1274,7 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; |
| 1292 | 1274 | /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri |
| 1293 | 1275 | /// currently implements it, but it seems like this may be something to check against in the |
| 1294 | 1276 | /// validator. |
| 1295 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, StableHash, TypeFoldable, TypeVisitable)] | |
| 1277 | #[derive(Clone, PartialEq, TyEncodable, TyDecodable, StableHash, TypeFoldable, TypeVisitable)] | |
| 1296 | 1278 | pub enum Operand<'tcx> { |
| 1297 | 1279 | /// Creates a value by loading the given place. |
| 1298 | 1280 | /// |
| ... | ... | @@ -1327,7 +1309,7 @@ pub enum Operand<'tcx> { |
| 1327 | 1309 | RuntimeChecks(RuntimeChecks), |
| 1328 | 1310 | } |
| 1329 | 1311 | |
| 1330 | #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 1312 | #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, StableHash)] | |
| 1331 | 1313 | #[derive(TypeFoldable, TypeVisitable)] |
| 1332 | 1314 | pub struct ConstOperand<'tcx> { |
| 1333 | 1315 | pub span: Span, |
| ... | ... | @@ -1352,7 +1334,7 @@ pub struct ConstOperand<'tcx> { |
| 1352 | 1334 | /// Computing any rvalue begins by evaluating the places and operands in some order (**Needs |
| 1353 | 1335 | /// clarification**: Which order?). These are then used to produce a "value" - the same kind of |
| 1354 | 1336 | /// value that an [`Operand`] produces. |
| 1355 | #[derive(Clone, TyEncodable, TyDecodable, Hash, StableHash, PartialEq, TypeFoldable, TypeVisitable)] | |
| 1337 | #[derive(Clone, TyEncodable, TyDecodable, StableHash, PartialEq, TypeFoldable, TypeVisitable)] | |
| 1356 | 1338 | pub enum Rvalue<'tcx> { |
| 1357 | 1339 | /// Yields the operand unchanged, except for a potential retag. |
| 1358 | 1340 | Use(Operand<'tcx>, WithRetag), |
| ... | ... | @@ -1534,7 +1516,7 @@ pub enum CoercionSource { |
| 1534 | 1516 | Implicit, |
| 1535 | 1517 | } |
| 1536 | 1518 | |
| 1537 | #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, StableHash)] | |
| 1519 | #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] | |
| 1538 | 1520 | #[derive(TypeFoldable, TypeVisitable)] |
| 1539 | 1521 | pub enum AggregateKind<'tcx> { |
| 1540 | 1522 | /// The type is of the element |
| ... | ... | @@ -1703,7 +1685,7 @@ pub enum BinOp { |
| 1703 | 1685 | |
| 1704 | 1686 | // Assignment operators, e.g. `+=`. See comments on the corresponding variants |
| 1705 | 1687 | // in `BinOp` for details. |
| 1706 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, StableHash)] | |
| 1688 | #[derive(Copy, Clone, Debug, PartialEq, Eq, StableHash)] | |
| 1707 | 1689 | pub enum AssignOp { |
| 1708 | 1690 | AddAssign, |
| 1709 | 1691 | SubAssign, |
compiler/rustc_middle/src/ty/print/pretty.rs-5| ... | ... | @@ -3269,11 +3269,6 @@ define_print! { |
| 3269 | 3269 | } |
| 3270 | 3270 | ty::PredicateKind::Ambiguous => write!(p, "ambiguous")?, |
| 3271 | 3271 | ty::PredicateKind::NormalizesTo(data) => data.print(p)?, |
| 3272 | ty::PredicateKind::AliasRelate(t1, t2, dir) => { | |
| 3273 | t1.print(p)?; | |
| 3274 | write!(p, " {dir} ")?; | |
| 3275 | t2.print(p)?; | |
| 3276 | } | |
| 3277 | 3272 | } |
| 3278 | 3273 | } |
| 3279 | 3274 |
compiler/rustc_middle/src/ty/sty.rs+15-18| ... | ... | @@ -769,25 +769,22 @@ impl<'tcx> Ty<'tcx> { |
| 769 | 769 | .projection_bounds() |
| 770 | 770 | .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) |
| 771 | 771 | .count(); |
| 772 | let expected_count: usize = obj | |
| 773 | .principal_def_id() | |
| 774 | .into_iter() | |
| 775 | .flat_map(|principal_def_id| { | |
| 776 | // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! | |
| 777 | elaborate::supertraits( | |
| 778 | tcx, | |
| 779 | ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), | |
| 780 | ) | |
| 781 | .map(|principal| { | |
| 782 | tcx.associated_items(principal.def_id()) | |
| 783 | .in_definition_order() | |
| 784 | .filter(|item| item.is_type() || item.is_type_const()) | |
| 785 | .filter(|item| !item.is_impl_trait_in_trait()) | |
| 786 | .filter(|item| !tcx.generics_require_sized_self(item.def_id)) | |
| 787 | .count() | |
| 788 | }) | |
| 772 | let expected_count: usize = obj.principal_def_id().map_or(0, |principal_def_id| { | |
| 773 | // IMPORTANT: This has to agree with HIR ty lowering of dyn trait! | |
| 774 | elaborate::supertraits( | |
| 775 | tcx, | |
| 776 | ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)), | |
| 777 | ) | |
| 778 | .map(|principal| { | |
| 779 | tcx.associated_items(principal.def_id()) | |
| 780 | .in_definition_order() | |
| 781 | .filter(|item| item.is_type() || item.is_type_const()) | |
| 782 | .filter(|item| !item.is_impl_trait_in_trait()) | |
| 783 | .filter(|item| !tcx.generics_require_sized_self(item.def_id)) | |
| 784 | .count() | |
| 789 | 785 | }) |
| 790 | .sum(); | |
| 786 | .sum() | |
| 787 | }); | |
| 791 | 788 | assert_eq!( |
| 792 | 789 | projection_count, expected_count, |
| 793 | 790 | "expected {obj:?} to have {expected_count} projections, \ |
compiler/rustc_middle/src/ty/typeck_results.rs+2-2| ... | ... | @@ -537,8 +537,8 @@ impl<'tcx> TypeckResults<'tcx> { |
| 537 | 537 | ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> { |
| 538 | 538 | self.closure_min_captures |
| 539 | 539 | .get(&closure_def_id) |
| 540 | .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter())) | |
| 541 | .into_iter() | |
| 540 | .map(|closure_min_captures| closure_min_captures.values()) | |
| 541 | .into_flat_iter() | |
| 542 | 542 | .flatten() |
| 543 | 543 | } |
| 544 | 544 |
compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs+1-1| ... | ... | @@ -126,6 +126,6 @@ where |
| 126 | 126 | sink_edge = self.sink_edge_nodes.contains(node).then_some(self.sink); |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | real_edges.into_iter().flatten().chain(sink_edge) | |
| 129 | real_edges.into_flat_iter().chain(sink_edge) | |
| 130 | 130 | } |
| 131 | 131 | } |
compiler/rustc_mir_transform/src/lib.rs+1| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | #![feature(deref_patterns)] |
| 5 | 5 | #![feature(impl_trait_in_assoc_type)] |
| 6 | 6 | #![feature(iterator_try_collect)] |
| 7 | #![feature(option_into_flat_iter)] | |
| 7 | 8 | #![feature(try_blocks)] |
| 8 | 9 | #![feature(yeet_expr)] |
| 9 | 10 | // tidy-alphabetical-end |
compiler/rustc_next_trait_solver/src/canonical/mod.rs+9-2| ... | ... | @@ -100,7 +100,6 @@ pub(super) fn instantiate_and_apply_query_response<D, I>( |
| 100 | 100 | param_env: I::ParamEnv, |
| 101 | 101 | original_values: &[I::GenericArg], |
| 102 | 102 | response: CanonicalResponse<I>, |
| 103 | visible_for_leak_check: VisibleForLeakCheck, | |
| 104 | 103 | span: I::Span, |
| 105 | 104 | ) -> (NestedNormalizationGoals<I>, Certainty) |
| 106 | 105 | where |
| ... | ... | @@ -121,7 +120,15 @@ where |
| 121 | 120 | match region_constraints { |
| 122 | 121 | ExternalRegionConstraints::Old(r) => register_region_constraints( |
| 123 | 122 | delegate, |
| 124 | r.iter().map(|(c, vis)| (*c, vis.and(visible_for_leak_check))), | |
| 123 | r.iter().map(|(c, vis)| { | |
| 124 | // FIXME: We should revisit and consider removing this after *assumptions on | |
| 125 | // binders* is available, like once we had done in the stabilization of | |
| 126 | // `-Znext-solver=coherence`(#121848). | |
| 127 | // We ignore constraints from the nested goals in leak check. This is to match with | |
| 128 | // the old solver's behavior, which has separated evaluation and fulfillment, and | |
| 129 | // the former doesn't consider outlives obligations from the later. | |
| 130 | (*c, vis.and(VisibleForLeakCheck::No)) | |
| 131 | }), | |
| 125 | 132 | span, |
| 126 | 133 | ), |
| 127 | 134 | ExternalRegionConstraints::NextGen(r) => { |
compiler/rustc_next_trait_solver/src/solve/alias_relate.rs deleted-93| ... | ... | @@ -1,93 +0,0 @@ |
| 1 | //! Implements the `AliasRelate` goal, which is used when unifying aliases. | |
| 2 | //! Doing this via a separate goal is called "deferred alias relation" and part | |
| 3 | //! of our more general approach to "lazy normalization". | |
| 4 | //! | |
| 5 | //! This is done by first structurally normalizing both sides of the goal, ending | |
| 6 | //! up in either a concrete type, rigid alias, or an infer variable. | |
| 7 | //! These are related further according to the rules below: | |
| 8 | //! | |
| 9 | //! (1.) If we end up with two rigid aliases, then we relate them structurally. | |
| 10 | //! | |
| 11 | //! (2.) If we end up with an infer var and a rigid alias, then we instantiate | |
| 12 | //! the infer var with the constructor of the alias and then recursively relate | |
| 13 | //! the terms. | |
| 14 | //! | |
| 15 | //! (3.) Otherwise, if we end with two rigid (non-projection) or infer types, | |
| 16 | //! relate them structurally. | |
| 17 | ||
| 18 | use rustc_type_ir::inherent::*; | |
| 19 | use rustc_type_ir::solve::{GoalSource, QueryResultOrRerunNonErased}; | |
| 20 | use rustc_type_ir::{self as ty, Interner}; | |
| 21 | use tracing::{instrument, trace}; | |
| 22 | ||
| 23 | use crate::delegate::SolverDelegate; | |
| 24 | use crate::solve::{Certainty, EvalCtxt, Goal}; | |
| 25 | ||
| 26 | impl<D, I> EvalCtxt<'_, D> | |
| 27 | where | |
| 28 | D: SolverDelegate<Interner = I>, | |
| 29 | I: Interner, | |
| 30 | { | |
| 31 | #[instrument(level = "trace", skip(self), ret)] | |
| 32 | pub(super) fn compute_alias_relate_goal( | |
| 33 | &mut self, | |
| 34 | goal: Goal<I, (I::Term, I::Term, ty::AliasRelationDirection)>, | |
| 35 | ) -> QueryResultOrRerunNonErased<I> { | |
| 36 | let cx = self.cx(); | |
| 37 | let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; | |
| 38 | ||
| 39 | // Check that the alias-relate goal is reasonable. Writeback for | |
| 40 | // `coroutine_stalled_predicates` can replace alias terms with | |
| 41 | // `{type error}` if the alias still contains infer vars, so we also | |
| 42 | // accept alias-relate goals where one of the terms is an error. | |
| 43 | debug_assert!( | |
| 44 | lhs.to_alias_term().is_some() | |
| 45 | || rhs.to_alias_term().is_some() | |
| 46 | || lhs.is_error() | |
| 47 | || rhs.is_error() | |
| 48 | ); | |
| 49 | ||
| 50 | // Structurally normalize the lhs. | |
| 51 | let lhs = if let Some(alias) = lhs.to_alias_term() { | |
| 52 | let term = self.next_term_infer_of_alias_kind(alias); | |
| 53 | self.add_goal( | |
| 54 | GoalSource::TypeRelating, | |
| 55 | goal.with(cx, ty::ProjectionPredicate { projection_term: alias, term }), | |
| 56 | )?; | |
| 57 | term | |
| 58 | } else { | |
| 59 | lhs | |
| 60 | }; | |
| 61 | ||
| 62 | // Structurally normalize the rhs. | |
| 63 | let rhs = if let Some(alias) = rhs.to_alias_term() { | |
| 64 | let term = self.next_term_infer_of_alias_kind(alias); | |
| 65 | self.add_goal( | |
| 66 | GoalSource::TypeRelating, | |
| 67 | goal.with(cx, ty::ProjectionPredicate { projection_term: alias, term }), | |
| 68 | )?; | |
| 69 | term | |
| 70 | } else { | |
| 71 | rhs | |
| 72 | }; | |
| 73 | ||
| 74 | // Add a `make_canonical_response` probe step so that we treat this as | |
| 75 | // a candidate, even if `try_evaluate_added_goals` bails due to an error. | |
| 76 | // It's `Certainty::AMBIGUOUS` because this candidate is not "finished", | |
| 77 | // since equating the normalized terms will lead to additional constraints. | |
| 78 | self.inspect.make_canonical_response(Certainty::AMBIGUOUS); | |
| 79 | ||
| 80 | // Apply the constraints. | |
| 81 | self.try_evaluate_added_goals()?; | |
| 82 | let lhs = self.resolve_vars_if_possible(lhs); | |
| 83 | let rhs = self.resolve_vars_if_possible(rhs); | |
| 84 | trace!(?lhs, ?rhs); | |
| 85 | ||
| 86 | let variance = match direction { | |
| 87 | ty::AliasRelationDirection::Equate => ty::Invariant, | |
| 88 | ty::AliasRelationDirection::Subtype => ty::Covariant, | |
| 89 | }; | |
| 90 | self.relate(param_env, lhs, variance, rhs)?; | |
| 91 | self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) | |
| 92 | } | |
| 93 | } |
compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs+2-25| ... | ... | @@ -733,29 +733,11 @@ where |
| 733 | 733 | let has_changed = |
| 734 | 734 | if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; |
| 735 | 735 | |
| 736 | // FIXME: We should revisit and consider removing this after | |
| 737 | // *assumptions on binders* is available, like once we had done in the | |
| 738 | // stabilization of `-Znext-solver=coherence`(#121848). | |
| 739 | // We ignore constraints from the nested goals in leak check. This is to match | |
| 740 | // with the old solver's behavior, which has separated evaluation and fulfillment, | |
| 741 | // and the former doesn't consider outlives obligations from the later. | |
| 742 | let vis = match goal.predicate.kind().skip_binder() { | |
| 743 | ty::PredicateKind::Clause(_) | |
| 744 | | ty::PredicateKind::DynCompatible(_) | |
| 745 | | ty::PredicateKind::Subtype(_) | |
| 746 | | ty::PredicateKind::Coerce(_) | |
| 747 | | ty::PredicateKind::ConstEquate(_, _) | |
| 748 | | ty::PredicateKind::Ambiguous | |
| 749 | | ty::PredicateKind::NormalizesTo(_) => VisibleForLeakCheck::No, | |
| 750 | ty::PredicateKind::AliasRelate(_, _, _) => VisibleForLeakCheck::Yes, | |
| 751 | }; | |
| 752 | ||
| 753 | 736 | let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response( |
| 754 | 737 | self.delegate, |
| 755 | 738 | goal.param_env, |
| 756 | 739 | &orig_values, |
| 757 | 740 | response, |
| 758 | vis, | |
| 759 | 741 | self.origin_span, |
| 760 | 742 | ); |
| 761 | 743 | |
| ... | ... | @@ -965,11 +947,6 @@ where |
| 965 | 947 | ty::PredicateKind::NormalizesTo(predicate) => { |
| 966 | 948 | ecx.compute_normalizes_to_goal(Goal { param_env, predicate })? |
| 967 | 949 | } |
| 968 | ty::PredicateKind::AliasRelate(lhs, rhs, direction) => ecx | |
| 969 | .compute_alias_relate_goal(Goal { | |
| 970 | param_env, | |
| 971 | predicate: (lhs, rhs, direction), | |
| 972 | })?, | |
| 973 | 950 | ty::PredicateKind::Ambiguous => { |
| 974 | 951 | ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)? |
| 975 | 952 | } |
| ... | ... | @@ -1276,7 +1253,8 @@ where |
| 1276 | 1253 | let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; |
| 1277 | 1254 | for &goal in goals.iter() { |
| 1278 | 1255 | let source = match goal.predicate.kind().skip_binder() { |
| 1279 | ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => { | |
| 1256 | ty::PredicateKind::Subtype { .. } | |
| 1257 | | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { | |
| 1280 | 1258 | GoalSource::TypeRelating |
| 1281 | 1259 | } |
| 1282 | 1260 | // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive? |
| ... | ... | @@ -1814,7 +1792,6 @@ pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>, |
| 1814 | 1792 | goal.param_env, |
| 1815 | 1793 | &proof_tree.orig_values, |
| 1816 | 1794 | response, |
| 1817 | VisibleForLeakCheck::Yes, | |
| 1818 | 1795 | origin_span, |
| 1819 | 1796 | ); |
| 1820 | 1797 |
compiler/rustc_next_trait_solver/src/solve/mod.rs-1| ... | ... | @@ -11,7 +11,6 @@ |
| 11 | 11 | //! For a high-level overview of how this solver works, check out the relevant |
| 12 | 12 | //! section of the rustc-dev-guide. |
| 13 | 13 | |
| 14 | mod alias_relate; | |
| 15 | 14 | mod assembly; |
| 16 | 15 | mod effect_goals; |
| 17 | 16 | mod eval_ctxt; |
compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs+17-30| ... | ... | @@ -82,7 +82,7 @@ where |
| 82 | 82 | }, |
| 83 | 83 | |ecx| { |
| 84 | 84 | ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| { |
| 85 | this.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); | |
| 85 | this.instantiate_normalizes_to_as_rigid(goal)?; | |
| 86 | 86 | this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) |
| 87 | 87 | }) |
| 88 | 88 | }, |
| ... | ... | @@ -111,13 +111,9 @@ where |
| 111 | 111 | Ok(()) |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | /// When normalizing an associated item, constrain the expected term to `term`. | |
| 114 | /// When normalizing an associated item, constrain the expected term to `value`. | |
| 115 | 115 | /// |
| 116 | /// We know `term` to always be a fully unconstrained inference variable, so | |
| 117 | /// `eq` should never fail here. However, in case `term` contains aliases, we | |
| 118 | /// emit nested `AliasRelate` goals to structurally normalize the alias. | |
| 119 | /// | |
| 120 | /// Additionally, when `term` is a const, this registers a `ConstArgHasType` | |
| 116 | /// Additionally, when `value` is a const, this registers a `ConstArgHasType` | |
| 121 | 117 | /// goal to ensure that the const value's type matches the declared type of |
| 122 | 118 | /// the alias it was normalized from. |
| 123 | 119 | /// |
| ... | ... | @@ -140,28 +136,25 @@ where |
| 140 | 136 | fn instantiate_normalizes_to_term( |
| 141 | 137 | &mut self, |
| 142 | 138 | goal: Goal<I, NormalizesTo<I>>, |
| 143 | term: I::Term, | |
| 139 | value: I::Term, | |
| 144 | 140 | ) -> Result<(), NoSolutionOrRerunNonErased> { |
| 145 | self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, term)?; | |
| 146 | self.eq(goal.param_env, goal.predicate.term, term) | |
| 147 | .expect("expected goal term to be fully unconstrained"); | |
| 141 | self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, value)?; | |
| 142 | // While `goal.predicate.term` should always be a fully unconstrained inference variable, | |
| 143 | // `eq` can still fail if `value` is not fully normalized, due to `eq` eagerly normalizing, | |
| 144 | // and that normalization can fail. | |
| 145 | self.eq(goal.param_env, goal.predicate.term, value)?; | |
| 148 | 146 | Ok(()) |
| 149 | 147 | } |
| 150 | 148 | |
| 151 | /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term | |
| 152 | /// with a rigid alias. Using this is pretty much always wrong. | |
| 153 | fn structurally_instantiate_normalizes_to_term( | |
| 149 | fn instantiate_normalizes_to_as_rigid( | |
| 154 | 150 | &mut self, |
| 155 | 151 | goal: Goal<I, NormalizesTo<I>>, |
| 156 | term: ty::AliasTerm<I>, | |
| 157 | ) { | |
| 158 | self.relate( | |
| 152 | ) -> Result<(), NoSolutionOrRerunNonErased> { | |
| 153 | self.eq( | |
| 159 | 154 | goal.param_env, |
| 160 | term.to_term(self.cx(), ty::IsRigid::Yes), | |
| 161 | ty::Invariant, | |
| 162 | 155 | goal.predicate.term, |
| 156 | goal.predicate.alias.to_term(self.cx(), ty::IsRigid::Yes), | |
| 163 | 157 | ) |
| 164 | .expect("expected goal term to be fully unconstrained"); | |
| 165 | 158 | } |
| 166 | 159 | } |
| 167 | 160 | |
| ... | ... | @@ -356,10 +349,7 @@ where |
| 356 | 349 | | ty::TypingMode::PostBorrowck { .. } |
| 357 | 350 | | ty::TypingMode::PostAnalysis |
| 358 | 351 | | ty::TypingMode::Codegen => { |
| 359 | ecx.structurally_instantiate_normalizes_to_term( | |
| 360 | goal, | |
| 361 | goal.predicate.alias, | |
| 362 | ); | |
| 352 | ecx.instantiate_normalizes_to_as_rigid(goal)?; | |
| 363 | 353 | return ecx.evaluate_added_goals_and_make_canonical_response( |
| 364 | 354 | Certainty::Yes, |
| 365 | 355 | ); |
| ... | ... | @@ -394,7 +384,7 @@ where |
| 394 | 384 | ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?; |
| 395 | 385 | return then(ecx, Certainty::Yes); |
| 396 | 386 | } else { |
| 397 | ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); | |
| 387 | ecx.instantiate_normalizes_to_as_rigid(goal)?; | |
| 398 | 388 | return then(ecx, Certainty::Yes); |
| 399 | 389 | } |
| 400 | 390 | } else { |
| ... | ... | @@ -767,10 +757,7 @@ where |
| 767 | 757 | // as rigid. |
| 768 | 758 | return alias_bound_result.or_else(|NoSolution| { |
| 769 | 759 | ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|this| { |
| 770 | this.structurally_instantiate_normalizes_to_term( | |
| 771 | goal, | |
| 772 | goal.predicate.alias, | |
| 773 | ); | |
| 760 | this.instantiate_normalizes_to_as_rigid(goal)?; | |
| 774 | 761 | this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) |
| 775 | 762 | }) |
| 776 | 763 | }); |
| ... | ... | @@ -1026,7 +1013,7 @@ where |
| 1026 | 1013 | // this impl candidate anyways. It's still a bit scuffed. |
| 1027 | 1014 | ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => { |
| 1028 | 1015 | return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { |
| 1029 | ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); | |
| 1016 | ecx.instantiate_normalizes_to_as_rigid(goal)?; | |
| 1030 | 1017 | ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) |
| 1031 | 1018 | }); |
| 1032 | 1019 | } |
compiler/rustc_passes/src/lib.rs+4| ... | ... | @@ -4,6 +4,10 @@ |
| 4 | 4 | //! |
| 5 | 5 | //! This API is completely unstable and subject to change. |
| 6 | 6 | |
| 7 | // tidy-alphabetical-start | |
| 8 | #![feature(option_into_flat_iter)] | |
| 9 | // tidy-alphabetical-end | |
| 10 | ||
| 7 | 11 | use rustc_middle::query::Providers; |
| 8 | 12 | |
| 9 | 13 | pub mod abi_test; |
compiler/rustc_passes/src/stability.rs+1-2| ... | ... | @@ -1112,8 +1112,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { |
| 1112 | 1112 | .iter() |
| 1113 | 1113 | .flat_map(|&cnum| { |
| 1114 | 1114 | find_attr!(tcx, cnum.as_def_id(), UnstableRemoved(rem_features) => rem_features) |
| 1115 | .into_iter() | |
| 1116 | .flatten() | |
| 1115 | .into_flat_iter() | |
| 1117 | 1116 | }) |
| 1118 | 1117 | .collect::<Vec<_>>(); |
| 1119 | 1118 |
compiler/rustc_public/src/ty.rs-7| ... | ... | @@ -1526,7 +1526,6 @@ pub enum PredicateKind { |
| 1526 | 1526 | Coerce(CoercePredicate), |
| 1527 | 1527 | ConstEquate(TyConst, TyConst), |
| 1528 | 1528 | Ambiguous, |
| 1529 | AliasRelate(TermKind, TermKind, AliasRelationDirection), | |
| 1530 | 1529 | } |
| 1531 | 1530 | |
| 1532 | 1531 | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] |
| ... | ... | @@ -1559,12 +1558,6 @@ pub struct CoercePredicate { |
| 1559 | 1558 | pub b: Ty, |
| 1560 | 1559 | } |
| 1561 | 1560 | |
| 1562 | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] | |
| 1563 | pub enum AliasRelationDirection { | |
| 1564 | Equate, | |
| 1565 | Subtype, | |
| 1566 | } | |
| 1567 | ||
| 1568 | 1561 | #[derive(Clone, Debug, Eq, PartialEq, Serialize)] |
| 1569 | 1562 | pub struct TraitPredicate { |
| 1570 | 1563 | pub trait_ref: TraitRef, |
compiler/rustc_public/src/unstable/convert/stable/ty.rs-19| ... | ... | @@ -749,13 +749,6 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { |
| 749 | 749 | } |
| 750 | 750 | PredicateKind::Ambiguous => crate::ty::PredicateKind::Ambiguous, |
| 751 | 751 | PredicateKind::NormalizesTo(_pred) => unimplemented!(), |
| 752 | PredicateKind::AliasRelate(a, b, alias_relation_direction) => { | |
| 753 | crate::ty::PredicateKind::AliasRelate( | |
| 754 | a.kind().stable(tables, cx), | |
| 755 | b.kind().stable(tables, cx), | |
| 756 | alias_relation_direction.stable(tables, cx), | |
| 757 | ) | |
| 758 | } | |
| 759 | 752 | } |
| 760 | 753 | } |
| 761 | 754 | } |
| ... | ... | @@ -845,18 +838,6 @@ impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { |
| 845 | 838 | } |
| 846 | 839 | } |
| 847 | 840 | |
| 848 | impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { | |
| 849 | type T = crate::ty::AliasRelationDirection; | |
| 850 | ||
| 851 | fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { | |
| 852 | use rustc_middle::ty::AliasRelationDirection::*; | |
| 853 | match self { | |
| 854 | Equate => crate::ty::AliasRelationDirection::Equate, | |
| 855 | Subtype => crate::ty::AliasRelationDirection::Subtype, | |
| 856 | } | |
| 857 | } | |
| 858 | } | |
| 859 | ||
| 860 | 841 | impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { |
| 861 | 842 | type T = crate::ty::TraitPredicate; |
| 862 | 843 |
compiler/rustc_resolve/src/error_helper.rs+5-7| ... | ... | @@ -1469,13 +1469,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1469 | 1469 | Scope::DeriveHelpers(expn_id) => { |
| 1470 | 1470 | let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); |
| 1471 | 1471 | if filter_fn(res) { |
| 1472 | suggestions.extend( | |
| 1473 | this.helper_attrs.get(&expn_id).into_iter().flatten().map( | |
| 1474 | |&(ident, orig_ident_span, _)| { | |
| 1475 | TypoSuggestion::new(ident.name, orig_ident_span, res) | |
| 1476 | }, | |
| 1477 | ), | |
| 1478 | ); | |
| 1472 | suggestions.extend(this.helper_attrs.get(&expn_id).into_flat_iter().map( | |
| 1473 | |&(ident, orig_ident_span, _)| { | |
| 1474 | TypoSuggestion::new(ident.name, orig_ident_span, res) | |
| 1475 | }, | |
| 1476 | )); | |
| 1479 | 1477 | } |
| 1480 | 1478 | } |
| 1481 | 1479 | Scope::DeriveHelpersCompat => { |
compiler/rustc_resolve/src/ident.rs+9-2| ... | ... | @@ -26,6 +26,7 @@ use crate::{ |
| 26 | 26 | Determinacy, ExternModule, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, |
| 27 | 27 | LocalModule, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, |
| 28 | 28 | Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, diagnostics, |
| 29 | module_to_string, | |
| 29 | 30 | }; |
| 30 | 31 | |
| 31 | 32 | #[derive(Copy, Clone)] |
| ... | ... | @@ -1869,6 +1870,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1869 | 1870 | module = Some(ModuleOrUniformRoot::Module(parent)); |
| 1870 | 1871 | continue; |
| 1871 | 1872 | } |
| 1873 | let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); | |
| 1874 | let current_module = self.resolve_self(&mut ctxt, parent_scope.module); | |
| 1875 | let current_module_path = module_to_string(current_module) | |
| 1876 | .map_or_else(|| "crate".to_string(), |path| format!("crate::{path}")); | |
| 1872 | 1877 | return PathResult::failed( |
| 1873 | 1878 | ident, |
| 1874 | 1879 | false, |
| ... | ... | @@ -1877,8 +1882,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1877 | 1882 | module, |
| 1878 | 1883 | || { |
| 1879 | 1884 | ( |
| 1880 | "too many leading `super` keywords".to_string(), | |
| 1881 | "there are too many leading `super` keywords".to_string(), | |
| 1885 | format!( | |
| 1886 | "too many leading `super` keywords within `{current_module_path}`" | |
| 1887 | ), | |
| 1888 | "this `super` would go above the crate root".to_string(), | |
| 1882 | 1889 | None, |
| 1883 | 1890 | None, |
| 1884 | 1891 | ) |
compiler/rustc_resolve/src/lib.rs+1| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #![feature(default_field_values)] |
| 16 | 16 | #![feature(deref_patterns)] |
| 17 | 17 | #![feature(iter_intersperse)] |
| 18 | #![feature(option_into_flat_iter)] | |
| 18 | 19 | #![feature(rustc_attrs)] |
| 19 | 20 | #![feature(trim_prefix_suffix)] |
| 20 | 21 | #![recursion_limit = "256"] |
compiler/rustc_session/src/lib.rs+1| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | #![feature(iter_intersperse)] |
| 7 | 7 | #![feature(macro_derive)] |
| 8 | 8 | #![feature(macro_metavar_expr)] |
| 9 | #![feature(option_into_flat_iter)] | |
| 9 | 10 | #![feature(rustc_attrs)] |
| 10 | 11 | // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums |
| 11 | 12 | // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers"). |
compiler/rustc_session/src/options.rs+1-1| ... | ... | @@ -1621,7 +1621,7 @@ pub mod parse { |
| 1621 | 1621 | let mut seen_instruction_threshold = false; |
| 1622 | 1622 | let mut seen_skip_entry = false; |
| 1623 | 1623 | let mut seen_skip_exit = false; |
| 1624 | for option in v.into_iter().flat_map(|v| v.split(',')) { | |
| 1624 | for option in v.map(|v| v.split(',')).into_flat_iter() { | |
| 1625 | 1625 | match option { |
| 1626 | 1626 | "always" if !seen_always && !seen_never => { |
| 1627 | 1627 | options.always = true; |
compiler/rustc_target/src/spec/mod.rs+1| ... | ... | @@ -1687,6 +1687,7 @@ supported_targets! { |
| 1687 | 1687 | ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), |
| 1688 | 1688 | ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf), |
| 1689 | 1689 | ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), |
| 1690 | ("riscv32imfc-unknown-none-elf", riscv32imfc_unknown_none_elf), | |
| 1690 | 1691 | ("riscv32imc-esp-espidf", riscv32imc_esp_espidf), |
| 1691 | 1692 | ("riscv32imac-esp-espidf", riscv32imac_esp_espidf), |
| 1692 | 1693 | ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf), |
compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | use crate::spec::{ | |
| 2 | Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, | |
| 3 | TargetOptions, | |
| 4 | }; | |
| 5 | ||
| 6 | // Bare-metal RV32IMFC for cores that have hardware single-precision float (the `F` | |
| 7 | // extension, with the `ilp32f` ABI) but NO atomic ('a') extension. | |
| 8 | // This is `riscv32imafc-unknown-none-elf` MINUS the atomic extension, handled the | |
| 9 | // same way the in-tree `riscv32imc-unknown-none-elf` handles a no-`a` core: | |
| 10 | // `+forced-atomics` makes atomic load/store lower to plain ld/st (sound on a single | |
| 11 | // hart) while `atomic_cas = false` keeps RMW/CAS off — downstream crates use a | |
| 12 | // critical-section polyfill (e.g. portable-atomic) for those. No lr.w/sc.w/amo* are | |
| 13 | // ever emitted, so it does not trap on a core without the A extension. | |
| 14 | pub(crate) fn target() -> Target { | |
| 15 | Target { | |
| 16 | data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), | |
| 17 | llvm_target: "riscv32".into(), | |
| 18 | metadata: TargetMetadata { | |
| 19 | description: Some( | |
| 20 | "Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics)".into(), | |
| 21 | ), | |
| 22 | tier: Some(3), | |
| 23 | host_tools: Some(false), | |
| 24 | std: Some(false), | |
| 25 | }, | |
| 26 | pointer_width: 32, | |
| 27 | arch: Arch::RiscV32, | |
| 28 | ||
| 29 | options: TargetOptions { | |
| 30 | linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), | |
| 31 | linker: Some("rust-lld".into()), | |
| 32 | cpu: "generic-rv32".into(), | |
| 33 | max_atomic_width: Some(32), | |
| 34 | atomic_cas: false, | |
| 35 | features: "+m,+f,+c,+forced-atomics".into(), | |
| 36 | llvm_abiname: LlvmAbi::Ilp32f, | |
| 37 | panic_strategy: PanicStrategy::Abort, | |
| 38 | relocation_model: RelocModel::Static, | |
| 39 | emit_debug_gdb_scripts: false, | |
| 40 | eh_frame_header: false, | |
| 41 | ..Default::default() | |
| 42 | }, | |
| 43 | } | |
| 44 | } |
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs+64-52| ... | ... | @@ -735,7 +735,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 735 | 735 | | ty::PredicateKind::Ambiguous |
| 736 | 736 | | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature { .. }) |
| 737 | 737 | | ty::PredicateKind::NormalizesTo { .. } |
| 738 | | ty::PredicateKind::AliasRelate(..) | |
| 739 | 738 | | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { |
| 740 | 739 | span_bug!( |
| 741 | 740 | span, |
| ... | ... | @@ -1643,55 +1642,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 1643 | 1642 | (None, error.err) |
| 1644 | 1643 | } |
| 1645 | 1644 | } |
| 1646 | ty::PredicateKind::AliasRelate(lhs, rhs, _) => { | |
| 1647 | let derive_better_type_error = | |
| 1648 | |alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| { | |
| 1649 | let ocx = ObligationCtxt::new(self); | |
| 1650 | ||
| 1651 | let normalized_term = ocx.normalize( | |
| 1652 | &ObligationCause::dummy(), | |
| 1653 | obligation.param_env, | |
| 1654 | Unnormalized::new_wip( | |
| 1655 | alias_term.to_term(self.tcx, ty::IsRigid::No), | |
| 1656 | ), | |
| 1657 | ); | |
| 1658 | ||
| 1659 | if let Err(terr) = ocx.eq( | |
| 1660 | &ObligationCause::dummy(), | |
| 1661 | obligation.param_env, | |
| 1662 | expected_term, | |
| 1663 | normalized_term, | |
| 1664 | ) { | |
| 1665 | Some((terr, self.resolve_vars_if_possible(normalized_term))) | |
| 1666 | } else { | |
| 1667 | None | |
| 1668 | } | |
| 1669 | }; | |
| 1670 | ||
| 1671 | if let Some(lhs) = lhs.to_alias_term() | |
| 1672 | && let ty::AliasTermKind::ProjectionTy { .. } | |
| 1673 | | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind | |
| 1674 | && let Some((better_type_err, expected_term)) = | |
| 1675 | derive_better_type_error(lhs, rhs) | |
| 1676 | { | |
| 1677 | ( | |
| 1678 | Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)), | |
| 1679 | better_type_err, | |
| 1680 | ) | |
| 1681 | } else if let Some(rhs) = rhs.to_alias_term() | |
| 1682 | && let ty::AliasTermKind::ProjectionTy { .. } | |
| 1683 | | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind | |
| 1684 | && let Some((better_type_err, expected_term)) = | |
| 1685 | derive_better_type_error(rhs, lhs) | |
| 1686 | { | |
| 1687 | ( | |
| 1688 | Some((rhs, self.resolve_vars_if_possible(expected_term), lhs)), | |
| 1689 | better_type_err, | |
| 1690 | ) | |
| 1691 | } else { | |
| 1692 | (None, error.err) | |
| 1693 | } | |
| 1694 | } | |
| 1695 | 1645 | _ => (None, error.err), |
| 1696 | 1646 | }; |
| 1697 | 1647 | |
| ... | ... | @@ -2326,18 +2276,80 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 2326 | 2276 | { |
| 2327 | 2277 | return false; |
| 2328 | 2278 | } |
| 2279 | let mut multi_span = MultiSpan::from_span(self.tcx.def_span(def_id)); | |
| 2329 | 2280 | let (desc, mention_castable) = |
| 2330 | 2281 | match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) { |
| 2331 | 2282 | (ty::FnPtr(..), ty::FnDef(..)) => { |
| 2332 | 2283 | (" implemented for fn pointer `", ", cast using `as`") |
| 2333 | 2284 | } |
| 2334 | 2285 | (ty::FnPtr(..), _) => (" implemented for fn pointer `", ""), |
| 2335 | _ => (" implemented for `", ""), | |
| 2286 | _ => { | |
| 2287 | let evaluate_obligations = || { | |
| 2288 | let ocx = ObligationCtxt::new_with_diagnostics(self); | |
| 2289 | self.enter_forall(trait_pred, |obligation_trait_ref| { | |
| 2290 | let impl_args = self.fresh_args_for_item(DUMMY_SP, def_id); | |
| 2291 | let impl_trait_ref = ocx.normalize( | |
| 2292 | &ObligationCause::dummy(), | |
| 2293 | param_env, | |
| 2294 | ty::EarlyBinder::bind(self.tcx, cand) | |
| 2295 | .instantiate(self.tcx, impl_args), | |
| 2296 | ); | |
| 2297 | if ocx | |
| 2298 | .eq( | |
| 2299 | &ObligationCause::dummy(), | |
| 2300 | param_env, | |
| 2301 | obligation_trait_ref.trait_ref, | |
| 2302 | impl_trait_ref, | |
| 2303 | ) | |
| 2304 | .is_err() | |
| 2305 | { | |
| 2306 | return Vec::new(); | |
| 2307 | } | |
| 2308 | ocx.register_obligations( | |
| 2309 | self.tcx | |
| 2310 | .predicates_of(def_id) | |
| 2311 | .instantiate(self.tcx, impl_args) | |
| 2312 | .into_iter() | |
| 2313 | .map(|(clause, span)| { | |
| 2314 | Obligation::new( | |
| 2315 | self.tcx, | |
| 2316 | ObligationCause::dummy_with_span(span), | |
| 2317 | param_env, | |
| 2318 | clause.skip_normalization(), | |
| 2319 | ) | |
| 2320 | }), | |
| 2321 | ); | |
| 2322 | ocx.try_evaluate_obligations() | |
| 2323 | }) | |
| 2324 | }; | |
| 2325 | let failing_obligations = | |
| 2326 | if !self.tcx.predicates_of(def_id).predicates.is_empty() { | |
| 2327 | self.probe(|_| evaluate_obligations()) | |
| 2328 | } else { | |
| 2329 | Vec::new() | |
| 2330 | }; | |
| 2331 | ||
| 2332 | if failing_obligations.is_empty() { | |
| 2333 | (" implemented for `", "") | |
| 2334 | } else { | |
| 2335 | for error in failing_obligations { | |
| 2336 | multi_span.push_span_label( | |
| 2337 | error.root_obligation.cause.span, | |
| 2338 | format!( | |
| 2339 | "unsatisfied requirement introduced here: `{}`", | |
| 2340 | error.root_obligation.predicate, | |
| 2341 | ), | |
| 2342 | ); | |
| 2343 | } | |
| 2344 | ||
| 2345 | (" conditionally implemented for `", "") | |
| 2346 | } | |
| 2347 | } | |
| 2336 | 2348 | }; |
| 2337 | 2349 | let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path()); |
| 2338 | 2350 | let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path()); |
| 2339 | 2351 | err.highlighted_span_help( |
| 2340 | self.tcx.def_span(def_id), | |
| 2352 | multi_span, | |
| 2341 | 2353 | vec![ |
| 2342 | 2354 | StringPart::normal(format!("the trait `{trait_}` ")), |
| 2343 | 2355 | StringPart::highlighted("is"), |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs+1-1| ... | ... | @@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 1613 | 1613 | _ => None, |
| 1614 | 1614 | }; |
| 1615 | 1615 | |
| 1616 | [typeck_results.expr_ty_adjusted_opt(expr)].into_iter().flatten().any(|expr_ty| { | |
| 1616 | typeck_results.expr_ty_adjusted_opt(expr).is_some_and(|expr_ty| { | |
| 1617 | 1617 | self.can_eq(obligation.param_env, expr_ty, old_self_ty) |
| 1618 | 1618 | || inner_old_self_ty |
| 1619 | 1619 | .is_some_and(|inner_ty| self.can_eq(obligation.param_env, expr_ty, inner_ty)) |
compiler/rustc_trait_selection/src/lib.rs+1| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | #![feature(iter_intersperse)] |
| 20 | 20 | #![feature(iterator_try_reduce)] |
| 21 | 21 | #![feature(never_type)] |
| 22 | #![feature(option_into_flat_iter)] | |
| 22 | 23 | #![feature(try_blocks)] |
| 23 | 24 | #![feature(unwrap_infallible)] |
| 24 | 25 | #![feature(yeet_expr)] |
compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs+1-20| ... | ... | @@ -52,9 +52,6 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( |
| 52 | 52 | expected_ty, |
| 53 | 53 | }) |
| 54 | 54 | } |
| 55 | ty::PredicateKind::AliasRelate(_, _, _) => { | |
| 56 | FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) | |
| 57 | } | |
| 58 | 55 | ty::PredicateKind::Subtype(pred) => { |
| 59 | 56 | let (a, b) = infcx.enter_forall_and_leak_universe( |
| 60 | 57 | obligation.predicate.kind().rebind((pred.a, pred.b)), |
| ... | ... | @@ -264,8 +261,7 @@ impl<'tcx> BestObligation<'tcx> { |
| 264 | 261 | let body_id = self.obligation.cause.body_id; |
| 265 | 262 | |
| 266 | 263 | for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id) |
| 267 | .into_iter() | |
| 268 | .flatten() | |
| 264 | .into_flat_iter() | |
| 269 | 265 | { |
| 270 | 266 | let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( |
| 271 | 267 | GoalSource::Misc, |
| ... | ... | @@ -544,21 +540,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { |
| 544 | 540 | self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; |
| 545 | 541 | } |
| 546 | 542 | |
| 547 | // alias-relate may fail because the lhs or rhs can't be normalized, | |
| 548 | // and therefore is treated as rigid. | |
| 549 | if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() { | |
| 550 | goal.infcx().visit_proof_tree_at_depth( | |
| 551 | goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs)), | |
| 552 | goal.depth() + 1, | |
| 553 | self, | |
| 554 | )?; | |
| 555 | goal.infcx().visit_proof_tree_at_depth( | |
| 556 | goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs)), | |
| 557 | goal.depth() + 1, | |
| 558 | self, | |
| 559 | )?; | |
| 560 | } | |
| 561 | ||
| 562 | 543 | self.detect_trait_error_in_higher_ranked_projection(goal)?; |
| 563 | 544 | |
| 564 | 545 | ControlFlow::Break(self.obligation.clone()) |
compiler/rustc_trait_selection/src/traits/auto_trait.rs-1| ... | ... | @@ -813,7 +813,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { |
| 813 | 813 | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) |
| 814 | 814 | | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) |
| 815 | 815 | | ty::PredicateKind::NormalizesTo(..) |
| 816 | | ty::PredicateKind::AliasRelate(..) | |
| 817 | 816 | | ty::PredicateKind::DynCompatible(..) |
| 818 | 817 | | ty::PredicateKind::Subtype(..) |
| 819 | 818 | | ty::PredicateKind::Coerce(..) |
compiler/rustc_trait_selection/src/traits/fulfill.rs-6| ... | ... | @@ -461,9 +461,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { |
| 461 | 461 | ty::PredicateKind::NormalizesTo(..) => { |
| 462 | 462 | bug!("NormalizesTo is only used by the new solver") |
| 463 | 463 | } |
| 464 | ty::PredicateKind::AliasRelate(..) => { | |
| 465 | bug!("AliasRelate is only used by the new solver") | |
| 466 | } | |
| 467 | 464 | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => { |
| 468 | 465 | unreachable!("unexpected higher ranked `UnstableFeature` goal") |
| 469 | 466 | } |
| ... | ... | @@ -535,9 +532,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { |
| 535 | 532 | ty::PredicateKind::NormalizesTo(..) => { |
| 536 | 533 | bug!("NormalizesTo is only used by the new solver") |
| 537 | 534 | } |
| 538 | ty::PredicateKind::AliasRelate(..) => { | |
| 539 | bug!("AliasRelate is only used by the new solver") | |
| 540 | } | |
| 541 | 535 | // Compute `ConstArgHasType` above the overflow check below. |
| 542 | 536 | // This is because this is not ever a useful obligation to report |
| 543 | 537 | // as the cause of an overflow. |
compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs+2-4| ... | ... | @@ -98,8 +98,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( |
| 98 | 98 | // From the full set of obligations, just filter down to the region relationships. |
| 99 | 99 | for obligation in |
| 100 | 100 | wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) |
| 101 | .into_iter() | |
| 102 | .flatten() | |
| 101 | .into_flat_iter() | |
| 103 | 102 | { |
| 104 | 103 | let pred = ocx |
| 105 | 104 | .deeply_normalize( |
| ... | ... | @@ -125,8 +124,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( |
| 125 | 124 | | ty::PredicateKind::ConstEquate(..) |
| 126 | 125 | | ty::PredicateKind::Ambiguous |
| 127 | 126 | | ty::PredicateKind::NormalizesTo(..) |
| 128 | | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | |
| 129 | | ty::PredicateKind::AliasRelate(..) => {} | |
| 127 | | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => {} | |
| 130 | 128 | |
| 131 | 129 | // We need to search through *all* WellFormed predicates |
| 132 | 130 | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { |
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs+8-4| ... | ... | @@ -1030,10 +1030,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |
| 1030 | 1030 | // supertraits. |
| 1031 | 1031 | let a_auto_traits: FxIndexSet<DefId> = a_data |
| 1032 | 1032 | .auto_traits() |
| 1033 | .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { | |
| 1034 | elaborate::supertrait_def_ids(self.tcx(), principal_def_id) | |
| 1035 | .filter(|def_id| self.tcx().trait_is_auto(*def_id)) | |
| 1036 | })) | |
| 1033 | .chain( | |
| 1034 | principal_def_id_a | |
| 1035 | .map(|principal_def_id| { | |
| 1036 | elaborate::supertrait_def_ids(self.tcx(), principal_def_id) | |
| 1037 | .filter(|def_id| self.tcx().trait_is_auto(*def_id)) | |
| 1038 | }) | |
| 1039 | .into_flat_iter(), | |
| 1040 | ) | |
| 1037 | 1041 | .collect(); |
| 1038 | 1042 | let auto_traits_compatible = b_data |
| 1039 | 1043 | .auto_traits() |
compiler/rustc_trait_selection/src/traits/select/mod.rs+19-11| ... | ... | @@ -771,10 +771,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |
| 771 | 771 | Ok(EvaluatedToOkModuloRegions) |
| 772 | 772 | } |
| 773 | 773 | |
| 774 | ty::PredicateKind::DynCompatible(_) => { | |
| 775 | bug!( | |
| 776 | "Obligation {obligation:?} should have been handled by fulfillment already." | |
| 777 | ) | |
| 774 | ty::PredicateKind::DynCompatible(trait_def_id) => { | |
| 775 | // `DynCompatible` obligations are only emitted as | |
| 776 | // nested obligations of `WellFormed` goals. It is quite | |
| 777 | // rare, but possible, that we encounter them during | |
| 778 | // evaluation. See #158665 for more details here. | |
| 779 | if self.tcx().is_dyn_compatible(trait_def_id) { | |
| 780 | Ok(EvaluatedToOk) | |
| 781 | } else { | |
| 782 | Ok(EvaluatedToErr) | |
| 783 | } | |
| 778 | 784 | } |
| 779 | 785 | |
| 780 | 786 | ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { |
| ... | ... | @@ -972,9 +978,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |
| 972 | 978 | ty::PredicateKind::NormalizesTo(..) => { |
| 973 | 979 | bug!("NormalizesTo is only used by the new solver") |
| 974 | 980 | } |
| 975 | ty::PredicateKind::AliasRelate(..) => { | |
| 976 | bug!("AliasRelate is only used by the new solver") | |
| 977 | } | |
| 978 | 981 | ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), |
| 979 | 982 | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { |
| 980 | 983 | let ct = self.infcx.shallow_resolve_const(ct); |
| ... | ... | @@ -2594,10 +2597,15 @@ impl<'tcx> SelectionContext<'_, 'tcx> { |
| 2594 | 2597 | // supertraits. |
| 2595 | 2598 | let a_auto_traits: FxIndexSet<DefId> = a_data |
| 2596 | 2599 | .auto_traits() |
| 2597 | .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { | |
| 2598 | elaborate::supertrait_def_ids(tcx, principal_def_id) | |
| 2599 | .filter(|def_id| tcx.trait_is_auto(*def_id)) | |
| 2600 | })) | |
| 2600 | .chain( | |
| 2601 | a_data | |
| 2602 | .principal_def_id() | |
| 2603 | .map(|principal_def_id| { | |
| 2604 | elaborate::supertrait_def_ids(tcx, principal_def_id) | |
| 2605 | .filter(|def_id| tcx.trait_is_auto(*def_id)) | |
| 2606 | }) | |
| 2607 | .into_flat_iter(), | |
| 2608 | ) | |
| 2601 | 2609 | .collect(); |
| 2602 | 2610 | |
| 2603 | 2611 | let upcast_principal = normalize_with_depth_to( |
compiler/rustc_trait_selection/src/traits/vtable.rs+1-2| ... | ... | @@ -188,8 +188,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( |
| 188 | 188 | |
| 189 | 189 | /// Turns option of iterator into an iterator (this is just flatten) |
| 190 | 190 | fn maybe_iter<I: Iterator>(i: Option<I>) -> impl Iterator<Item = I::Item> { |
| 191 | // Flatten is bad perf-vise, we could probably implement a special case here that is better | |
| 192 | i.into_iter().flatten() | |
| 191 | i.into_flat_iter() | |
| 193 | 192 | } |
| 194 | 193 | |
| 195 | 194 | fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { |
compiler/rustc_traits/src/normalize_erasing_regions.rs-1| ... | ... | @@ -70,7 +70,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { |
| 70 | 70 | | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) |
| 71 | 71 | | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) |
| 72 | 72 | | ty::PredicateKind::NormalizesTo(..) |
| 73 | | ty::PredicateKind::AliasRelate(..) | |
| 74 | 73 | | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) |
| 75 | 74 | | ty::PredicateKind::DynCompatible(..) |
| 76 | 75 | | ty::PredicateKind::Subtype(..) |
compiler/rustc_transmute/src/layout/dfa.rs+4-4| ... | ... | @@ -257,15 +257,15 @@ where |
| 257 | 257 | pub(crate) fn bytes_from(&self, start: State) -> impl Iterator<Item = (Byte, State)> { |
| 258 | 258 | self.transitions |
| 259 | 259 | .get(&start) |
| 260 | .into_iter() | |
| 261 | .flat_map(|transitions| transitions.byte_transitions.iter()) | |
| 260 | .map(|transitions| transitions.byte_transitions.iter()) | |
| 261 | .into_flat_iter() | |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | 264 | pub(crate) fn refs_from(&self, start: State) -> impl Iterator<Item = (Reference<R, T>, State)> { |
| 265 | 265 | self.transitions |
| 266 | 266 | .get(&start) |
| 267 | .into_iter() | |
| 268 | .flat_map(|transitions| transitions.ref_transitions.iter()) | |
| 267 | .map(|transitions| transitions.ref_transitions.iter()) | |
| 268 | .into_flat_iter() | |
| 269 | 269 | .map(|(r, s)| (*r, *s)) |
| 270 | 270 | } |
| 271 | 271 |
compiler/rustc_transmute/src/lib.rs+1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | // tidy-alphabetical-start |
| 2 | 2 | #![cfg_attr(test, feature(test))] |
| 3 | 3 | #![feature(never_type)] |
| 4 | #![feature(option_into_flat_iter)] | |
| 4 | 5 | // tidy-alphabetical-end |
| 5 | 6 | |
| 6 | 7 | pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; |
compiler/rustc_ty_utils/src/assoc.rs+2-2| ... | ... | @@ -32,7 +32,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { |
| 32 | 32 | let item_def_id = trait_item_ref.owner_id.to_def_id(); |
| 33 | 33 | [item_def_id] |
| 34 | 34 | .into_iter() |
| 35 | .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) | |
| 35 | .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied()) | |
| 36 | 36 | })) |
| 37 | 37 | } |
| 38 | 38 | hir::ItemKind::Impl(impl_) => { |
| ... | ... | @@ -44,7 +44,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] { |
| 44 | 44 | let item_def_id = impl_item_ref.owner_id.to_def_id(); |
| 45 | 45 | [item_def_id] |
| 46 | 46 | .into_iter() |
| 47 | .chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied()) | |
| 47 | .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied()) | |
| 48 | 48 | })) |
| 49 | 49 | } |
| 50 | 50 | _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), |
compiler/rustc_ty_utils/src/implied_bounds.rs+4-4| ... | ... | @@ -176,13 +176,13 @@ fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> |
| 176 | 176 | if let hir::ItemKind::Impl(impl_) = item.kind { |
| 177 | 177 | let trait_args = impl_ |
| 178 | 178 | .of_trait |
| 179 | .into_iter() | |
| 180 | .flat_map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args) | |
| 179 | .map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args) | |
| 180 | .into_flat_iter() | |
| 181 | 181 | .map(|arg| arg.span()); |
| 182 | 182 | let dummy_spans_for_default_args = impl_ |
| 183 | 183 | .of_trait |
| 184 | .into_iter() | |
| 185 | .flat_map(|of_trait| iter::repeat(of_trait.trait_ref.path.span)); | |
| 184 | .map(|of_trait| iter::repeat(of_trait.trait_ref.path.span)) | |
| 185 | .into_flat_iter(); | |
| 186 | 186 | iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args) |
| 187 | 187 | } else { |
| 188 | 188 | bug!("unexpected item for impl {def_id:?}: {item:?}") |
compiler/rustc_ty_utils/src/layout.rs+1-2| ... | ... | @@ -718,8 +718,7 @@ fn layout_of_uncached<'tcx>( |
| 718 | 718 | let discriminants_iter = || { |
| 719 | 719 | def.is_enum() |
| 720 | 720 | .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128))) |
| 721 | .into_iter() | |
| 722 | .flatten() | |
| 721 | .into_flat_iter() | |
| 723 | 722 | }; |
| 724 | 723 | |
| 725 | 724 | let maybe_unsized = def.is_struct() |
compiler/rustc_ty_utils/src/lib.rs+1| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #![feature(deref_patterns)] |
| 10 | 10 | #![feature(iterator_try_collect)] |
| 11 | 11 | #![feature(never_type)] |
| 12 | #![feature(option_into_flat_iter)] | |
| 12 | 13 | // tidy-alphabetical-end |
| 13 | 14 | |
| 14 | 15 | use rustc_middle::query::Providers; |
compiler/rustc_type_ir/src/flags.rs-4| ... | ... | @@ -443,10 +443,6 @@ impl<I: Interner> FlagComputation<I> { |
| 443 | 443 | self.add_alias_term(alias); |
| 444 | 444 | self.add_term(term); |
| 445 | 445 | } |
| 446 | ty::PredicateKind::AliasRelate(t1, t2, _) => { | |
| 447 | self.add_term(t1); | |
| 448 | self.add_term(t2); | |
| 449 | } | |
| 450 | 446 | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_sym)) => {} |
| 451 | 447 | ty::PredicateKind::Ambiguous => {} |
| 452 | 448 | } |
compiler/rustc_type_ir/src/generic_visit.rs-1| ... | ... | @@ -198,7 +198,6 @@ trivial_impls!( |
| 198 | 198 | usize, |
| 199 | 199 | crate::PredicatePolarity, |
| 200 | 200 | crate::BoundConstness, |
| 201 | crate::AliasRelationDirection, | |
| 202 | 201 | crate::DebruijnIndex, |
| 203 | 202 | crate::solve::Certainty, |
| 204 | 203 | crate::UniverseIndex, |
compiler/rustc_type_ir/src/inherent.rs+1-3| ... | ... | @@ -499,9 +499,7 @@ pub trait Predicate<I: Interner<Predicate = Self>>: |
| 499 | 499 | |
| 500 | 500 | fn allow_normalization(self) -> bool { |
| 501 | 501 | match self.kind().skip_binder() { |
| 502 | PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { | |
| 503 | false | |
| 504 | } | |
| 502 | PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, | |
| 505 | 503 | PredicateKind::Clause(ClauseKind::Trait(_)) |
| 506 | 504 | | PredicateKind::Clause(ClauseKind::HostEffect(..)) |
| 507 | 505 | | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) |
compiler/rustc_type_ir/src/macros.rs-1| ... | ... | @@ -50,7 +50,6 @@ TrivialTypeTraversalImpls! { |
| 50 | 50 | u32, |
| 51 | 51 | u64, |
| 52 | 52 | // tidy-alphabetical-start |
| 53 | crate::AliasRelationDirection, | |
| 54 | 53 | crate::BoundConstness, |
| 55 | 54 | crate::DebruijnIndex, |
| 56 | 55 | crate::PredicatePolarity, |
compiler/rustc_type_ir/src/predicate_kind.rs+1-26| ... | ... | @@ -2,7 +2,7 @@ use std::fmt; |
| 2 | 2 | |
| 3 | 3 | use derive_where::derive_where; |
| 4 | 4 | #[cfg(feature = "nightly")] |
| 5 | use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash, StableHash_NoContext}; | |
| 5 | use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; | |
| 6 | 6 | use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; |
| 7 | 7 | |
| 8 | 8 | use crate::{self as ty, Interner}; |
| ... | ... | @@ -103,32 +103,10 @@ pub enum PredicateKind<I: Interner> { |
| 103 | 103 | /// It is likely more useful to think of this as a function `normalizes_to(alias)`, |
| 104 | 104 | /// whose return value is written into `term`. |
| 105 | 105 | NormalizesTo(ty::NormalizesTo<I>), |
| 106 | ||
| 107 | /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. | |
| 108 | /// This predicate requires two terms to be equal to eachother. | |
| 109 | /// | |
| 110 | /// Only used for new solver. | |
| 111 | AliasRelate(I::Term, I::Term, AliasRelationDirection), | |
| 112 | 106 | } |
| 113 | 107 | |
| 114 | 108 | impl<I: Interner> Eq for PredicateKind<I> {} |
| 115 | 109 | |
| 116 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] | |
| 117 | #[cfg_attr(feature = "nightly", derive(StableHash, Encodable_NoContext, Decodable_NoContext))] | |
| 118 | pub enum AliasRelationDirection { | |
| 119 | Equate, | |
| 120 | Subtype, | |
| 121 | } | |
| 122 | ||
| 123 | impl std::fmt::Display for AliasRelationDirection { | |
| 124 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| 125 | match self { | |
| 126 | AliasRelationDirection::Equate => write!(f, "=="), | |
| 127 | AliasRelationDirection::Subtype => write!(f, "<:"), | |
| 128 | } | |
| 129 | } | |
| 130 | } | |
| 131 | ||
| 132 | 110 | impl<I: Interner> fmt::Debug for ClauseKind<I> { |
| 133 | 111 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 134 | 112 | match self { |
| ... | ... | @@ -161,9 +139,6 @@ impl<I: Interner> fmt::Debug for PredicateKind<I> { |
| 161 | 139 | PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"), |
| 162 | 140 | PredicateKind::Ambiguous => write!(f, "Ambiguous"), |
| 163 | 141 | PredicateKind::NormalizesTo(p) => p.fmt(f), |
| 164 | PredicateKind::AliasRelate(t1, t2, dir) => { | |
| 165 | write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") | |
| 166 | } | |
| 167 | 142 | } |
| 168 | 143 | } |
| 169 | 144 | } |
compiler/rustc_type_ir/src/relate/combine.rs+70-70| ... | ... | @@ -38,8 +38,7 @@ where |
| 38 | 38 | obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>, |
| 39 | 39 | ); |
| 40 | 40 | |
| 41 | /// Register `AliasRelate` obligation(s) that both types must be related to each other. | |
| 42 | fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); | |
| 41 | fn ambient_variance(&self) -> ty::Variance; | |
| 43 | 42 | } |
| 44 | 43 | |
| 45 | 44 | pub fn super_combine_tys<Infcx, I, R>( |
| ... | ... | @@ -115,60 +114,69 @@ where |
| 115 | 114 | panic!("We do not expect to encounter `Fresh` variables in the new solver") |
| 116 | 115 | } |
| 117 | 116 | |
| 118 | (ty::Alias(is_rigid_a, _), ty::Alias(is_rigid_b, _)) if infcx.next_trait_solver() => { | |
| 119 | match (is_rigid_a, is_rigid_b) { | |
| 120 | (ty::IsRigid::Yes, ty::IsRigid::Yes) => structurally_relate_tys(relation, a, b), | |
| 121 | _ => match relation.structurally_relate_aliases() { | |
| 122 | StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), | |
| 123 | StructurallyRelateAliases::No => { | |
| 124 | relation.register_alias_relate_predicate(a, b); | |
| 125 | Ok(a) | |
| 126 | } | |
| 127 | }, | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | (other, ty::Alias(is_rigid, _)) | (ty::Alias(is_rigid, _), other) | |
| 132 | if infcx.next_trait_solver() => | |
| 117 | (ty::Alias(ty::IsRigid::No, alias), _) | (_, ty::Alias(ty::IsRigid::No, alias)) | |
| 118 | if infcx.next_trait_solver() | |
| 119 | && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() => | |
| 133 | 120 | { |
| 134 | if let StructurallyRelateAliases::No = relation.structurally_relate_aliases() | |
| 135 | && is_rigid == ty::IsRigid::No | |
| 136 | { | |
| 137 | relation.register_alias_relate_predicate(a, b); | |
| 138 | Ok(a) | |
| 139 | } else { | |
| 140 | match other { | |
| 141 | ty::Infer(infer_ty) => match infer_ty { | |
| 142 | // Normally, we shouldn't be combining an infer ty with an alias here. But | |
| 143 | // when we evaluate a `Projection(assoc_ty, expected)` goal, we normalize | |
| 144 | // the projection term and structurally equate it with the expected term. If | |
| 145 | // the normalized term is an alias type and the expected term is a ty var, | |
| 146 | // the ty var just instantiated with the alias type without combining them. | |
| 147 | // However, if the expected term is either an int var or a float var, e.g., | |
| 148 | // when the expected term is an int literal that only can be fully inferred | |
| 149 | // after the fallback, they are passed to this function because int/float | |
| 150 | // vars can't be instantiated. As we can't structurally relate infer ty with | |
| 151 | // another type, we just error them out here instead. | |
| 152 | ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) => { | |
| 153 | Err(TypeError::Sorts(ExpectedFound::new(a, b))) | |
| 154 | } | |
| 155 | ||
| 156 | ty::InferTy::TyVar(_) | |
| 157 | | ty::InferTy::FreshTy(_) | |
| 158 | | ty::InferTy::FreshIntTy(_) | |
| 159 | | ty::InferTy::FreshFloatTy(_) => unreachable!(), | |
| 160 | }, | |
| 161 | _ => structurally_relate_tys(relation, a, b), | |
| 121 | // If both sides are aliases, arbitrarily do the LHS first | |
| 122 | let terms_are_inverted = !matches!(a.kind(), ty::Alias(ty::IsRigid::No, _)); | |
| 123 | let other = if terms_are_inverted { a } else { b }; | |
| 124 | match (relation.ambient_variance(), terms_are_inverted) { | |
| 125 | (ty::Invariant, _) => relation.register_predicates([ty::ProjectionPredicate { | |
| 126 | projection_term: alias.into(), | |
| 127 | term: other.into(), | |
| 128 | }]), | |
| 129 | (ty::Covariant, false) | (ty::Contravariant, true) => { | |
| 130 | // Generate a new var to represent `alias <: other` | |
| 131 | // with `alias == ?A && ?A <: other` | |
| 132 | let new_var = infcx.next_ty_infer(); | |
| 133 | relation.register_predicates([ | |
| 134 | ty::PredicateKind::Clause(ty::ClauseKind::Projection( | |
| 135 | ty::ProjectionPredicate { | |
| 136 | projection_term: alias.into(), | |
| 137 | term: new_var.into(), | |
| 138 | }, | |
| 139 | )), | |
| 140 | ty::PredicateKind::Subtype(ty::SubtypePredicate { | |
| 141 | a_is_expected: !terms_are_inverted, | |
| 142 | a: new_var, | |
| 143 | b: other, | |
| 144 | }), | |
| 145 | ]); | |
| 146 | } | |
| 147 | (ty::Contravariant, false) | (ty::Covariant, true) => { | |
| 148 | // a :> b is b <: a | |
| 149 | let new_var = infcx.next_ty_infer(); | |
| 150 | relation.register_predicates([ | |
| 151 | ty::PredicateKind::Clause(ty::ClauseKind::Projection( | |
| 152 | ty::ProjectionPredicate { | |
| 153 | projection_term: alias.into(), | |
| 154 | term: new_var.into(), | |
| 155 | }, | |
| 156 | )), | |
| 157 | ty::PredicateKind::Subtype(ty::SubtypePredicate { | |
| 158 | a_is_expected: terms_are_inverted, | |
| 159 | a: other, | |
| 160 | b: new_var, | |
| 161 | }), | |
| 162 | ]); | |
| 163 | } | |
| 164 | (ty::Bivariant, _) => { | |
| 165 | unreachable!( | |
| 166 | "cannot handle bivariant aliases in register_projection_with_variance" | |
| 167 | ) | |
| 162 | 168 | } |
| 163 | 169 | } |
| 170 | Ok(a) | |
| 164 | 171 | } |
| 165 | 172 | |
| 166 | 173 | // All other cases of inference are errors |
| 167 | 174 | (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))), |
| 168 | 175 | |
| 169 | 176 | (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) |
| 170 | | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { | |
| 171 | assert!(!infcx.next_trait_solver()); | |
| 177 | | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) | |
| 178 | if !infcx.next_trait_solver() => | |
| 179 | { | |
| 172 | 180 | match infcx.typing_mode_raw().assert_not_erased() { |
| 173 | 181 | // During coherence, opaque types should be treated as *possibly* |
| 174 | 182 | // equal to any other type. This is an |
| ... | ... | @@ -239,32 +247,24 @@ where |
| 239 | 247 | Ok(a) |
| 240 | 248 | } |
| 241 | 249 | |
| 242 | (ty::ConstKind::Alias(ty::IsRigid::Yes, _), ty::ConstKind::Alias(ty::IsRigid::Yes, _)) | |
| 243 | if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) => | |
| 250 | (ty::ConstKind::Alias(ty::IsRigid::No, alias), _) | |
| 251 | | (_, ty::ConstKind::Alias(ty::IsRigid::No, alias)) | |
| 252 | if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) | |
| 253 | && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() => | |
| 244 | 254 | { |
| 245 | structurally_relate_consts(relation, a, b) | |
| 246 | } | |
| 247 | ||
| 248 | (ty::ConstKind::Alias(..), _) | (_, ty::ConstKind::Alias(..)) | |
| 249 | if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() => | |
| 250 | { | |
| 251 | match relation.structurally_relate_aliases() { | |
| 252 | StructurallyRelateAliases::No => { | |
| 253 | relation.register_predicates([if infcx.next_trait_solver() { | |
| 254 | ty::PredicateKind::AliasRelate( | |
| 255 | a.into(), | |
| 256 | b.into(), | |
| 257 | ty::AliasRelationDirection::Equate, | |
| 258 | ) | |
| 259 | } else { | |
| 260 | ty::PredicateKind::ConstEquate(a, b) | |
| 261 | }]); | |
| 262 | ||
| 263 | Ok(b) | |
| 264 | } | |
| 265 | StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), | |
| 255 | if infcx.next_trait_solver() { | |
| 256 | let other = if matches!(a.kind(), ty::ConstKind::Alias(..)) { b } else { a }; | |
| 257 | relation.register_predicates([ty::ProjectionPredicate { | |
| 258 | projection_term: alias.into(), | |
| 259 | term: other.into(), | |
| 260 | }]) | |
| 261 | } else { | |
| 262 | relation.register_predicates([ty::PredicateKind::ConstEquate(a, b)]); | |
| 266 | 263 | } |
| 264 | ||
| 265 | Ok(b) | |
| 267 | 266 | } |
| 267 | ||
| 268 | 268 | _ => structurally_relate_consts(relation, a, b), |
| 269 | 269 | } |
| 270 | 270 | } |
compiler/rustc_type_ir/src/relate/solver_relating.rs+2-22| ... | ... | @@ -383,27 +383,7 @@ where |
| 383 | 383 | self.goals.extend(obligations); |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { | |
| 387 | self.register_predicates([ty::Binder::dummy(match self.ambient_variance { | |
| 388 | ty::Covariant => ty::PredicateKind::AliasRelate( | |
| 389 | a.into(), | |
| 390 | b.into(), | |
| 391 | ty::AliasRelationDirection::Subtype, | |
| 392 | ), | |
| 393 | // a :> b is b <: a | |
| 394 | ty::Contravariant => ty::PredicateKind::AliasRelate( | |
| 395 | b.into(), | |
| 396 | a.into(), | |
| 397 | ty::AliasRelationDirection::Subtype, | |
| 398 | ), | |
| 399 | ty::Invariant => ty::PredicateKind::AliasRelate( | |
| 400 | a.into(), | |
| 401 | b.into(), | |
| 402 | ty::AliasRelationDirection::Equate, | |
| 403 | ), | |
| 404 | ty::Bivariant => { | |
| 405 | unreachable!("Expected bivariance to be handled in relate_with_variance") | |
| 406 | } | |
| 407 | })]); | |
| 386 | fn ambient_variance(&self) -> ty::Variance { | |
| 387 | self.ambient_variance | |
| 408 | 388 | } |
| 409 | 389 | } |
library/core/src/attribute_docs.rs+47-33| ... | ... | @@ -8,10 +8,10 @@ |
| 8 | 8 | /// |
| 9 | 9 | /// This is most common on types that represent an important state or outcome. For example, |
| 10 | 10 | /// [`Result`] is marked `#[must_use]` because ignoring an error value can hide a failed operation. |
| 11 | /// In the following example, the returned `Result` is the only sign that writing the message | |
| 11 | /// In the following example, the returned [`Result`] is the only sign that writing the message | |
| 12 | 12 | /// might have failed: |
| 13 | 13 | /// |
| 14 | /// ```rust | |
| 14 | /// ``` | |
| 15 | 15 | /// # #![allow(unused_must_use)] |
| 16 | 16 | /// fn write_message() -> std::io::Result<()> { |
| 17 | 17 | /// // Write the message... |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /// write_message(); |
| 22 | 22 | /// ``` |
| 23 | 23 | /// |
| 24 | /// Ignoring that `Result` triggers this warning: | |
| 24 | /// Ignoring that [`Result`] triggers this warning: | |
| 25 | 25 | /// |
| 26 | 26 | /// ```text |
| 27 | 27 | /// warning: unused `Result` that must be used |
| ... | ... | @@ -36,7 +36,7 @@ |
| 36 | 36 | /// You can also place `#[must_use]` on a function, method, or trait declaration. On a function or |
| 37 | 37 | /// method, the warning is tied to ignoring that call's return value: |
| 38 | 38 | /// |
| 39 | /// ```rust | |
| 39 | /// ``` | |
| 40 | 40 | /// # #![allow(unused_must_use)] |
| 41 | 41 | /// #[must_use] |
| 42 | 42 | /// fn make_token() -> String { |
| ... | ... | @@ -53,7 +53,7 @@ |
| 53 | 53 | /// |
| 54 | 54 | /// The attribute can include a message explaining what the caller should do with the value: |
| 55 | 55 | /// |
| 56 | /// ```rust | |
| 56 | /// ``` | |
| 57 | 57 | /// # #![allow(dead_code)] |
| 58 | 58 | /// #[must_use = "call `.finish()` to complete the operation"] |
| 59 | 59 | /// fn start_operation() -> Operation { |
| ... | ... | @@ -65,7 +65,7 @@ |
| 65 | 65 | /// |
| 66 | 66 | /// If intentionally ignoring the value is correct, bind it to `_` or call [`drop`]: |
| 67 | 67 | /// |
| 68 | /// ```rust | |
| 68 | /// ``` | |
| 69 | 69 | /// # #[must_use] |
| 70 | 70 | /// # fn make_token() -> String { |
| 71 | 71 | /// # String::from("token") |
| ... | ... | @@ -80,8 +80,6 @@ |
| 80 | 80 | /// |
| 81 | 81 | /// For more information, see the Reference on [the `must_use` attribute]. |
| 82 | 82 | /// |
| 83 | /// [`Result`]: result::Result | |
| 84 | /// [`Future`]: future::Future | |
| 85 | 83 | /// [`unused_must_use`]: ../rustc/lints/listing/warn-by-default.html#unused-must-use |
| 86 | 84 | /// [the `must_use` attribute]: ../reference/attributes/diagnostics.html#the-must_use-attribute |
| 87 | 85 | mod must_use_attribute {} |
| ... | ... | @@ -90,9 +88,9 @@ mod must_use_attribute {} |
| 90 | 88 | // |
| 91 | 89 | /// The `allow` attribute suppresses lint diagnostics that would otherwise produce |
| 92 | 90 | /// warnings or errors. It can be used on any lint or lint group (except those |
| 93 | /// set to `forbid`). | |
| 91 | /// set to [`forbid`]). | |
| 94 | 92 | /// |
| 95 | /// ```rust | |
| 93 | /// ``` | |
| 96 | 94 | /// #[allow(dead_code)] |
| 97 | 95 | /// fn unused_function() { |
| 98 | 96 | /// // ... |
| ... | ... | @@ -119,7 +117,7 @@ mod must_use_attribute {} |
| 119 | 117 | /// |
| 120 | 118 | /// Multiple lints can be set to `allow` at once with commas: |
| 121 | 119 | /// |
| 122 | /// ```rust | |
| 120 | /// ``` | |
| 123 | 121 | /// #[allow(unused_variables, unused_mut)] |
| 124 | 122 | /// fn main() { |
| 125 | 123 | /// let mut x: u32 = 42; |
| ... | ... | @@ -128,12 +126,12 @@ mod must_use_attribute {} |
| 128 | 126 | /// |
| 129 | 127 | /// This is mostly used to prevent lint warnings or errors while still under development. |
| 130 | 128 | /// |
| 131 | /// It cannot override a lint that has been set to `forbid`. | |
| 129 | /// It cannot override a lint that has been set to [`forbid`]. | |
| 132 | 130 | /// |
| 133 | 131 | /// It's also important to consider that overusing `allow` could make code harder to maintain |
| 134 | 132 | /// and possibly hide issues. To mitigate this issue, using the `expect` attribute is preferred. |
| 135 | 133 | /// |
| 136 | /// `allow` can be overridden by `warn`, `deny`, and `forbid`. | |
| 134 | /// `allow` can be overridden by [`warn`], [`deny`], and [`forbid`]. | |
| 137 | 135 | /// |
| 138 | 136 | /// The lint checks supported by rustc can be found via `rustc -W help`, |
| 139 | 137 | /// along with their default settings and are documented in [the `rustc` book]. |
| ... | ... | @@ -143,6 +141,9 @@ mod must_use_attribute {} |
| 143 | 141 | /// For more information, see the Reference on [the `allow` attribute]. |
| 144 | 142 | /// |
| 145 | 143 | /// [the `allow` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes |
| 144 | /// [`forbid`]: ./attribute.forbid.html | |
| 145 | /// [`warn`]: ./attribute.warn.html | |
| 146 | /// [`deny`]: ./attribute.deny.html | |
| 146 | 147 | mod allow_attribute {} |
| 147 | 148 | |
| 148 | 149 | #[doc(attribute = "cfg")] |
| ... | ... | @@ -152,7 +153,7 @@ mod allow_attribute {} |
| 152 | 153 | /// The `cfg` attribute allows compiling an item under specific conditions, otherwise it |
| 153 | 154 | /// will be ignored. |
| 154 | 155 | /// |
| 155 | /// ```rust | |
| 156 | /// ``` | |
| 156 | 157 | /// // Only compiles this function for Linux. |
| 157 | 158 | /// #[cfg(target_os = "linux")] |
| 158 | 159 | /// fn platform_specific() { |
| ... | ... | @@ -169,19 +170,20 @@ mod allow_attribute {} |
| 169 | 170 | /// Depending on the platform you're targeting, only one of these two functions will be considered |
| 170 | 171 | /// during the compilation. |
| 171 | 172 | /// |
| 172 | /// Conditions can also be combined with `all(...)`, `any(...)`, and `not(...)`. | |
| 173 | /// Conditions can also be combined with `all(...)`, `any(...)`, and `not(...)`: | |
| 173 | 174 | /// |
| 174 | 175 | /// * `all`: True if all given predicates are true. |
| 175 | 176 | /// * `any`: True if at least one of the given predicates is true. |
| 176 | 177 | /// * `not`: True if the predicate is false and false if the predicate is true. |
| 177 | 178 | /// |
| 178 | /// ```rust | |
| 179 | /// ``` | |
| 179 | 180 | /// #[cfg(all(unix, target_pointer_width = "64"))] |
| 180 | 181 | /// fn unix_64bit() { |
| 182 | /// // ... | |
| 181 | 183 | /// } |
| 182 | 184 | /// ``` |
| 183 | 185 | /// |
| 184 | /// If you want to use this mechanism in an `if` condition in your code, you | |
| 186 | /// If you want to use this mechanism in an [`if`] condition in your code, you | |
| 185 | 187 | /// can use the [`cfg!`] macro. To conditionally apply an attribute, |
| 186 | 188 | /// see [`cfg_attr`]. |
| 187 | 189 | /// |
| ... | ... | @@ -189,6 +191,7 @@ mod allow_attribute {} |
| 189 | 191 | /// |
| 190 | 192 | /// [`cfg_attr`]: ../reference/conditional-compilation.html#the-cfg_attr-attribute |
| 191 | 193 | /// [the `cfg` attribute]: ../reference/conditional-compilation.html#the-cfg-attribute |
| 194 | /// [`if`]: ./keyword.if.html | |
| 192 | 195 | mod cfg_attribute {} |
| 193 | 196 | |
| 194 | 197 | #[doc(attribute = "deny")] |
| ... | ... | @@ -196,16 +199,16 @@ mod cfg_attribute {} |
| 196 | 199 | /// Emits an error, preventing the compilation from finishing, when a lint check has failed. |
| 197 | 200 | /// This is useful for enforcing rules or preventing certain patterns: |
| 198 | 201 | /// |
| 199 | /// ```rust,compile_fail | |
| 202 | /// ```compile_fail | |
| 200 | 203 | /// #[deny(unused)] |
| 201 | 204 | /// fn foo() { |
| 202 | 205 | /// let x = 42; // Emits an error because x is unused. |
| 203 | 206 | /// } |
| 204 | 207 | /// ``` |
| 205 | 208 | /// |
| 206 | /// `deny` can be overridden by `allow`, `warn`, and `forbid`: | |
| 209 | /// `deny` can be overridden by [`allow`], [`warn`], and [`forbid`]: | |
| 207 | 210 | /// |
| 208 | /// ```rust | |
| 211 | /// ``` | |
| 209 | 212 | /// #![deny(unused)] |
| 210 | 213 | /// |
| 211 | 214 | /// #[allow(unused)] // We override the `deny` for this function. |
| ... | ... | @@ -216,7 +219,7 @@ mod cfg_attribute {} |
| 216 | 219 | /// |
| 217 | 220 | /// Multiple lints can also be set to `deny` at once: |
| 218 | 221 | /// |
| 219 | /// ```rust,compile_fail | |
| 222 | /// ```compile_fail | |
| 220 | 223 | /// #![deny(unused_imports, unused_variables)] |
| 221 | 224 | /// use std::collections::*; |
| 222 | 225 | /// |
| ... | ... | @@ -233,20 +236,24 @@ mod cfg_attribute {} |
| 233 | 236 | /// For more information, see the Reference on [the `deny` attribute]. |
| 234 | 237 | /// |
| 235 | 238 | /// [the `deny` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes |
| 239 | /// [`forbid`]: ./attribute.forbid.html | |
| 240 | /// [`allow`]: ./attribute.allow.html | |
| 241 | /// [`warn`]: ./attribute.warn.html | |
| 242 | /// [`deny`]: ./attribute.deny.html | |
| 236 | 243 | mod deny_attribute {} |
| 237 | 244 | |
| 238 | 245 | #[doc(attribute = "forbid")] |
| 239 | 246 | // |
| 240 | 247 | /// Emits an error, preventing the compilation from finishing, when a lint check has failed. |
| 241 | 248 | /// |
| 242 | /// A lint set to `forbid` cannot be overridden by `allow` or `warn`. | |
| 249 | /// A lint set to `forbid` cannot be overridden by [`allow`] or [`warn`]. | |
| 243 | 250 | /// Attempting either will result in a compilation error. Writing `#[deny(...)]` on the same lint inside a |
| 244 | 251 | /// `forbid` scope is permitted, but has no effect; the lint remains at the `forbid` level. |
| 245 | 252 | /// |
| 246 | 253 | /// This is useful for enforcing strict policies that should not be relaxed |
| 247 | 254 | /// anywhere in the codebase. Example: |
| 248 | 255 | /// |
| 249 | /// ```rust | |
| 256 | /// ``` | |
| 250 | 257 | /// #![forbid(unsafe_code)] |
| 251 | 258 | /// |
| 252 | 259 | /// // This would cause a compilation error if uncommented: |
| ... | ... | @@ -255,7 +262,7 @@ mod deny_attribute {} |
| 255 | 262 | /// |
| 256 | 263 | /// Multiple lints can be set to `forbid` at once: |
| 257 | 264 | /// |
| 258 | /// ```rust | |
| 265 | /// ``` | |
| 259 | 266 | /// #![forbid(unsafe_code, unused)] |
| 260 | 267 | /// ``` |
| 261 | 268 | /// |
| ... | ... | @@ -267,6 +274,8 @@ mod deny_attribute {} |
| 267 | 274 | /// For more information, see the Reference on [the `forbid` attribute]. |
| 268 | 275 | /// |
| 269 | 276 | /// [the `forbid` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes |
| 277 | /// [`allow`]: ./attribute.allow.html | |
| 278 | /// [`warn`]: ./attribute.warn.html | |
| 270 | 279 | mod forbid_attribute {} |
| 271 | 280 | |
| 272 | 281 | #[doc(attribute = "deprecated")] |
| ... | ... | @@ -279,15 +288,16 @@ mod forbid_attribute {} |
| 279 | 288 | /// |
| 280 | 289 | /// Example: |
| 281 | 290 | /// |
| 282 | /// ```rust | |
| 291 | /// ``` | |
| 283 | 292 | /// #[deprecated(since = "1.0.0", note = "Use bar instead")] |
| 284 | 293 | /// struct Foo; |
| 285 | 294 | /// struct Bar; |
| 286 | 295 | /// ``` |
| 287 | 296 | /// |
| 288 | /// `deprecated` attribute helps developers transition away from old code by providing warnings when | |
| 289 | /// deprecated items are used. Note that during `Cargo` builds, warnings on dependencies get silenced | |
| 290 | /// by default, so you may not see a deprecation warning unless you build that dependency directly. | |
| 297 | /// The `deprecated` attribute helps developers transition away from old code by providing warnings | |
| 298 | /// when deprecated items are used. Note that during `Cargo` builds, warnings on dependencies get | |
| 299 | /// silenced by default, so you may not see a deprecation warning unless you build that dependency | |
| 300 | /// directly. | |
| 291 | 301 | /// |
| 292 | 302 | /// For more information, see the Reference on [the `deprecated` attribute]. |
| 293 | 303 | /// |
| ... | ... | @@ -298,12 +308,13 @@ mod deprecated_attribute {} |
| 298 | 308 | // |
| 299 | 309 | /// Emits a warning during compilation when a lint check failed. |
| 300 | 310 | /// |
| 301 | /// Unlike `deny` or `forbid`, `warn` does not produce a hard error: the compilation continues, but | |
| 302 | /// the compiler emits a warning message. `warn` can be overridden by `allow`, `deny`, and `forbid`. | |
| 311 | /// Unlike [`deny`] or [`forbid`], `warn` does not produce a hard error: the compilation | |
| 312 | /// continues, but the compiler emits a warning message. `warn` can be overridden by [`allow`], | |
| 313 | /// [`deny`], and [`forbid`]. | |
| 303 | 314 | /// |
| 304 | 315 | /// Example: |
| 305 | 316 | /// |
| 306 | /// ```rust,compile_fail | |
| 317 | /// ```compile_fail | |
| 307 | 318 | /// #![allow(unused)] |
| 308 | 319 | /// |
| 309 | 320 | /// #[warn(unused)] // We override the allowed `unused` lint. |
| ... | ... | @@ -315,11 +326,11 @@ mod deprecated_attribute {} |
| 315 | 326 | /// |
| 316 | 327 | /// |
| 317 | 328 | /// Many lints, including `unused`, are already set to `warn` by default so this attribute is |
| 318 | /// mainly useful for lints that are normally `allow` by default. | |
| 329 | /// mainly useful for lints that are normally [`allow`] by default. | |
| 319 | 330 | /// |
| 320 | 331 | /// Multiple lints can be set to `warn` at once: |
| 321 | 332 | /// |
| 322 | /// ```rust,compile_fail | |
| 333 | /// ```compile_fail | |
| 323 | 334 | /// #[warn(unused_mut, unused_variables)] |
| 324 | 335 | /// fn main() { |
| 325 | 336 | /// let mut x = 42; |
| ... | ... | @@ -334,4 +345,7 @@ mod deprecated_attribute {} |
| 334 | 345 | /// For more information, see the Reference on [the `warn` attribute]. |
| 335 | 346 | /// |
| 336 | 347 | /// [the `warn` attribute]: ../reference/attributes/diagnostics.html#lint-check-attributes |
| 348 | /// [`allow`]: ./attribute.allow.html | |
| 349 | /// [`deny`]: ./attribute.deny.html | |
| 350 | /// [`forbid`]: ./attribute.forbid.html | |
| 337 | 351 | mod warn_attribute {} |
library/core/src/intrinsics/mod.rs+10-10| ... | ... | @@ -818,19 +818,19 @@ pub const fn forget<T: ?Sized>(_: T); |
| 818 | 818 | /// |
| 819 | 819 | /// // This is how the standard library does it. This is the best method, if |
| 820 | 820 | /// // you need to do something like this |
| 821 | /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize) | |
| 821 | /// fn split_at_stdlib<T>(to_split: &mut [T], mid: usize) | |
| 822 | 822 | /// -> (&mut [T], &mut [T]) { |
| 823 | /// let len = slice.len(); | |
| 823 | /// let len = to_split.len(); | |
| 824 | 824 | /// assert!(mid <= len); |
| 825 | 825 | /// unsafe { |
| 826 | /// let ptr = slice.as_mut_ptr(); | |
| 827 | /// // This now has three mutable references pointing at the same | |
| 828 | /// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1. | |
| 829 | /// // `slice` is never used after `let ptr = ...`, and so one can | |
| 830 | /// // treat it as "dead", and therefore, you only have two real | |
| 831 | /// // mutable slices. | |
| 832 | /// (slice::from_raw_parts_mut(ptr, mid), | |
| 833 | /// slice::from_raw_parts_mut(ptr.add(mid), len - mid)) | |
| 826 | /// let ptr = to_split.as_mut_ptr(); | |
| 827 | /// let fst = slice::from_raw_parts_mut(ptr, mid); | |
| 828 | /// let snd = slice::from_raw_parts_mut(ptr.add(mid), len - mid); | |
| 829 | /// // The function now has three mutable references to overlapping memory: | |
| 830 | /// // `to_split`, `fst`, and `snd`. | |
| 831 | /// // `to_split` is never used after `let ptr = ...` so it can be treated as "dead". | |
| 832 | /// // This leaves two "live" mutable slice references, `fst` and `snd`, with no overlap. | |
| 833 | /// (fst, snd) | |
| 834 | 834 | /// } |
| 835 | 835 | /// } |
| 836 | 836 | /// ``` |
library/core/src/ptr/mod.rs+19-21| ... | ... | @@ -300,27 +300,25 @@ |
| 300 | 300 | //! represent the tagged pointer as an actual pointer and not a `usize`*. For instance: |
| 301 | 301 | //! |
| 302 | 302 | //! ``` |
| 303 | //! unsafe { | |
| 304 | //! // A flag we want to pack into our pointer | |
| 305 | //! static HAS_DATA: usize = 0x1; | |
| 306 | //! static FLAG_MASK: usize = !HAS_DATA; | |
| 307 | //! | |
| 308 | //! // Our value, which must have enough alignment to have spare least-significant-bits. | |
| 309 | //! let my_precious_data: u32 = 17; | |
| 310 | //! assert!(align_of::<u32>() > 1); | |
| 311 | //! | |
| 312 | //! // Create a tagged pointer | |
| 313 | //! let ptr = &my_precious_data as *const u32; | |
| 314 | //! let tagged = ptr.map_addr(|addr| addr | HAS_DATA); | |
| 315 | //! | |
| 316 | //! // Check the flag: | |
| 317 | //! if tagged.addr() & HAS_DATA != 0 { | |
| 318 | //! // Untag and read the pointer | |
| 319 | //! let data = *tagged.map_addr(|addr| addr & FLAG_MASK); | |
| 320 | //! assert_eq!(data, 17); | |
| 321 | //! } else { | |
| 322 | //! unreachable!() | |
| 323 | //! } | |
| 303 | //! // A flag we want to pack into our pointer | |
| 304 | //! static HAS_DATA: usize = 0x1; | |
| 305 | //! static FLAG_MASK: usize = !HAS_DATA; | |
| 306 | //! | |
| 307 | //! // Our value, which must have enough alignment to have spare least-significant-bits. | |
| 308 | //! let my_precious_data: u32 = 17; | |
| 309 | //! assert!(align_of::<u32>() > 1); | |
| 310 | //! | |
| 311 | //! // Create a tagged pointer | |
| 312 | //! let ptr = &my_precious_data as *const u32; | |
| 313 | //! let tagged = ptr.map_addr(|addr| addr | HAS_DATA); | |
| 314 | //! | |
| 315 | //! // Check the flag: | |
| 316 | //! if tagged.addr() & HAS_DATA != 0 { | |
| 317 | //! // Untag and read the pointer | |
| 318 | //! let data = unsafe { *tagged.map_addr(|addr| addr & FLAG_MASK) }; | |
| 319 | //! assert_eq!(data, 17); | |
| 320 | //! } else { | |
| 321 | //! unreachable!() | |
| 324 | 322 | //! } |
| 325 | 323 | //! ``` |
| 326 | 324 | //! |
library/std/src/sys/process/unix/vxworks.rs+11-1| ... | ... | @@ -124,7 +124,17 @@ impl Command { |
| 124 | 124 | Ok(t) => unsafe { |
| 125 | 125 | let mut status = 0 as c_int; |
| 126 | 126 | libc::waitpid(t.0.pid, &mut status, 0); |
| 127 | libc::exit(0); | |
| 127 | // If the task was killed by a signal, terminate the same way by | |
| 128 | // restoring the default disposition and resending it to ourselves. | |
| 129 | if libc::WIFSIGNALED(status) { | |
| 130 | let signal = libc::WTERMSIG(status); | |
| 131 | libc::signal(signal, libc::SIG_DFL); | |
| 132 | libc::kill(libc::getpid(), signal); | |
| 133 | // The signal should have already terminated us; abort if it | |
| 134 | // was blocked or ignored. | |
| 135 | libc::abort(); | |
| 136 | } | |
| 137 | libc::exit(libc::WEXITSTATUS(status)); | |
| 128 | 138 | }, |
| 129 | 139 | Err(e) => e, |
| 130 | 140 | } |
src/ci/run.sh-8| ... | ... | @@ -79,14 +79,6 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1" |
| 79 | 79 | # of our CPU resources. |
| 80 | 80 | RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set dist.compression-profile=balanced" |
| 81 | 81 | |
| 82 | # When building for mingw, limit the number of parallel linker jobs during | |
| 83 | # the LLVM build, as not to run out of memory. | |
| 84 | # This is an attempt to fix the spurious build error tracked by | |
| 85 | # https://github.com/rust-lang/rust/issues/108227. | |
| 86 | if isKnownToBeMingwBuild; then | |
| 87 | RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.link-jobs=1" | |
| 88 | fi | |
| 89 | ||
| 90 | 82 | # Only produce xz tarballs on CI. gz tarballs will be generated by the release |
| 91 | 83 | # process by recompressing the existing xz ones. This decreases the storage |
| 92 | 84 | # space required for CI artifacts. |
src/doc/rustc/src/platform-support.md+1| ... | ... | @@ -401,6 +401,7 @@ target | std | host | notes |
| 401 | 401 | `riscv32gc-unknown-linux-musl` | ? | | RISC-V Linux (kernel 5.4, musl 1.2.5) |
| 402 | 402 | [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA) |
| 403 | 403 | [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA) |
| 404 | [`riscv32imfc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics) | |
| 404 | 405 | [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF |
| 405 | 406 | [`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX |
| 406 | 407 | [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) |
src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md+15-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | # `riscv32{i,im,ima,imc,imac,imafc}-unknown-none-elf` | |
| 1 | # `riscv32{i,im,ima,imc,imfc,imac,imafc}-unknown-none-elf` | |
| 2 | 2 | |
| 3 | 3 | **Tier: 2** |
| 4 | 4 | |
| ... | ... | @@ -6,12 +6,25 @@ Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and |
| 6 | 6 | |
| 7 | 7 | **Tier: 3** |
| 8 | 8 | |
| 9 | Bare-metal target for RISC-V CPUs with the RV32IMA ISA. | |
| 9 | Bare-metal target for RISC-V CPUs with the RV32IMA and RV32IMFC ISAs. | |
| 10 | ||
| 11 | The `riscv32imfc-unknown-none-elf` target covers RV32IMFC cores that have | |
| 12 | hardware single-precision floating point (the `F` extension, using the `ilp32f` | |
| 13 | ABI) but *no* atomic (`A`) extension. Like `riscv32imc-unknown-none-elf`, it is | |
| 14 | built with `+forced-atomics`: atomic loads/stores lower to plain loads/stores | |
| 15 | (sound on a single hart) and `lr`/`sc`/`amo*` instructions are never emitted, so | |
| 16 | it does not trap on a core without the `A` extension. Compare-and-swap and other | |
| 17 | read-modify-write atomics are disabled (`atomic_cas = false`); downstream crates | |
| 18 | that need them use a critical-section polyfill (e.g. `portable-atomic`). | |
| 10 | 19 | |
| 11 | 20 | ## Target maintainers |
| 12 | 21 | |
| 13 | 22 | * Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) |
| 14 | 23 | |
| 24 | The `riscv32imfc-unknown-none-elf` target is additionally maintained by: | |
| 25 | ||
| 26 | * [@sanchuanhehe](https://github.com/sanchuanhehe) | |
| 27 | ||
| 15 | 28 | ## Requirements |
| 16 | 29 | |
| 17 | 30 | The target is cross-compiled, and uses static linking. No external toolchain |
src/llvm-project+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | Subproject commit 3c3f13025bf9f99bb2a757eb37dad4f09e7d6c36 | |
| 1 | Subproject commit a04c1eced55f2f3ea8dbd3d17db0b6df271c0809 |
src/tools/test-float-parse/Cargo.lock deleted-75| ... | ... | @@ -1,75 +0,0 @@ |
| 1 | # This file is automatically @generated by Cargo. | |
| 2 | # It is not intended for manual editing. | |
| 3 | version = 3 | |
| 4 | ||
| 5 | [[package]] | |
| 6 | name = "cfg-if" | |
| 7 | version = "1.0.0" | |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |
| 10 | ||
| 11 | [[package]] | |
| 12 | name = "getrandom" | |
| 13 | version = "0.2.10" | |
| 14 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 15 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" | |
| 16 | dependencies = [ | |
| 17 | "cfg-if", | |
| 18 | "libc", | |
| 19 | "wasi", | |
| 20 | ] | |
| 21 | ||
| 22 | [[package]] | |
| 23 | name = "libc" | |
| 24 | version = "0.2.147" | |
| 25 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 26 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" | |
| 27 | ||
| 28 | [[package]] | |
| 29 | name = "ppv-lite86" | |
| 30 | version = "0.2.17" | |
| 31 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 32 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | |
| 33 | ||
| 34 | [[package]] | |
| 35 | name = "rand" | |
| 36 | version = "0.8.5" | |
| 37 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 38 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" | |
| 39 | dependencies = [ | |
| 40 | "libc", | |
| 41 | "rand_chacha", | |
| 42 | "rand_core", | |
| 43 | ] | |
| 44 | ||
| 45 | [[package]] | |
| 46 | name = "rand_chacha" | |
| 47 | version = "0.3.1" | |
| 48 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 49 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" | |
| 50 | dependencies = [ | |
| 51 | "ppv-lite86", | |
| 52 | "rand_core", | |
| 53 | ] | |
| 54 | ||
| 55 | [[package]] | |
| 56 | name = "rand_core" | |
| 57 | version = "0.6.4" | |
| 58 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 59 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" | |
| 60 | dependencies = [ | |
| 61 | "getrandom", | |
| 62 | ] | |
| 63 | ||
| 64 | [[package]] | |
| 65 | name = "test-float-parse" | |
| 66 | version = "0.1.0" | |
| 67 | dependencies = [ | |
| 68 | "rand", | |
| 69 | ] | |
| 70 | ||
| 71 | [[package]] | |
| 72 | name = "wasi" | |
| 73 | version = "0.11.0+wasi-snapshot-preview1" | |
| 74 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 75 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" |
tests/assembly-llvm/targets/targets-elf.rs+3| ... | ... | @@ -508,6 +508,9 @@ |
| 508 | 508 | //@ revisions: riscv32imc_unknown_none_elf |
| 509 | 509 | //@ [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf |
| 510 | 510 | //@ [riscv32imc_unknown_none_elf] needs-llvm-components: riscv |
| 511 | //@ revisions: riscv32imfc_unknown_none_elf | |
| 512 | //@ [riscv32imfc_unknown_none_elf] compile-flags: --target riscv32imfc-unknown-none-elf | |
| 513 | //@ [riscv32imfc_unknown_none_elf] needs-llvm-components: riscv | |
| 511 | 514 | //@ revisions: riscv64_linux_android |
| 512 | 515 | //@ [riscv64_linux_android] compile-flags: --target riscv64-linux-android |
| 513 | 516 | //@ [riscv64_linux_android] needs-llvm-components: riscv |
tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | //@ compile-flags: -Znext-solver=globally | |
| 2 | ||
| 3 | #![feature(inherent_associated_types)] | |
| 4 | #![feature(type_alias_impl_trait)] | |
| 5 | #![allow(incomplete_features)] | |
| 6 | ||
| 7 | struct Foo<T>(T); | |
| 8 | ||
| 9 | impl Foo<Vec<[u32]>> { | |
| 10 | //~^ ERROR the size for values of type `[u32]` cannot be known at compilation time | |
| 11 | type Assoc = u32; | |
| 12 | } | |
| 13 | ||
| 14 | type Tait = impl Sized; | |
| 15 | ||
| 16 | #[define_opaque(Tait)] | |
| 17 | fn bar() { | |
| 18 | let _: Foo<Tait>::Assoc = 42; | |
| 19 | //~^ ERROR the associated type `Assoc` exists for `Foo<Tait>`, but its trait bounds were not satisfied | |
| 20 | } | |
| 21 | ||
| 22 | fn main() {} |
tests/ui/associated-inherent-types/next-solver-unsatisfied-bounds-inherent-tait.stderr created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | error[E0277]: the size for values of type `[u32]` cannot be known at compilation time | |
| 2 | --> $DIR/next-solver-unsatisfied-bounds-inherent-tait.rs:9:10 | |
| 3 | | | |
| 4 | LL | impl Foo<Vec<[u32]>> { | |
| 5 | | ^^^^^^^^^^ doesn't have a size known at compile-time | |
| 6 | | | |
| 7 | = help: the trait `Sized` is not implemented for `[u32]` | |
| 8 | note: required by an implicit `Sized` bound in `Vec` | |
| 9 | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | |
| 10 | ||
| 11 | error: the associated type `Assoc` exists for `Foo<Tait>`, but its trait bounds were not satisfied | |
| 12 | --> $DIR/next-solver-unsatisfied-bounds-inherent-tait.rs:18:23 | |
| 13 | | | |
| 14 | LL | struct Foo<T>(T); | |
| 15 | | ------------- associated type `Assoc` not found for this struct | |
| 16 | ... | |
| 17 | LL | let _: Foo<Tait>::Assoc = 42; | |
| 18 | | ^^^^^ associated type cannot be referenced on `Foo<Tait>` due to unsatisfied trait bounds | |
| 19 | ||
| 20 | error: aborting due to 2 previous errors | |
| 21 | ||
| 22 | For more information about this error, try `rustc --explain E0277`. |
tests/ui/derives/redundant-derive-note-on-unimplemented.stderr+3-1| ... | ... | @@ -7,11 +7,13 @@ LL | println!("{:?}", S(X)); |
| 7 | 7 | | required by this formatting parameter |
| 8 | 8 | | |
| 9 | 9 | = help: the trait `Debug` is not implemented for `X` |
| 10 | help: the trait `Debug` is implemented for `S<T>` | |
| 10 | help: the trait `Debug` is conditionally implemented for `S<T>` | |
| 11 | 11 | --> $DIR/redundant-derive-note-on-unimplemented.rs:8:10 |
| 12 | 12 | | |
| 13 | 13 | LL | #[derive(Debug)] |
| 14 | 14 | | ^^^^^ |
| 15 | LL | struct S<T>(T); | |
| 16 | | - unsatisfied requirement introduced here: `X: Debug` | |
| 15 | 17 | note: required for `S<X>` to implement `Debug` |
| 16 | 18 | --> $DIR/redundant-derive-note-on-unimplemented.rs:9:8 |
| 17 | 19 | | |
tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr+4-2| ... | ... | @@ -39,11 +39,13 @@ LL | want(Some(())); |
| 39 | 39 | | required by a bound introduced by this call |
| 40 | 40 | | |
| 41 | 41 | = help: the trait `Iterator` is not implemented for `()` |
| 42 | help: the trait `T1` is implemented for `Option<It>` | |
| 42 | help: the trait `T1` is conditionally implemented for `Option<It>` | |
| 43 | 43 | --> $DIR/blame-trait-error.rs:21:1 |
| 44 | 44 | | |
| 45 | 45 | LL | impl<It: Iterator> T1 for Option<It> {} |
| 46 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 46 | | ^^^^^^^^^--------^^^^^^^^^^^^^^^^^^^ | |
| 47 | | | | |
| 48 | | unsatisfied requirement introduced here: `(): Iterator` | |
| 47 | 49 | note: required for `Option<()>` to implement `T1` |
| 48 | 50 | --> $DIR/blame-trait-error.rs:21:20 |
| 49 | 51 | | |
tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.rs created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | //@ check-pass | |
| 2 | ||
| 3 | // Regression test for https://github.com/rust-lang/rust/issues/158628. | |
| 4 | ||
| 5 | #[diagnostic::on_type_error(unknown = "")] | |
| 6 | //~^ WARN unknown diagnostic attribute | |
| 7 | pub struct Foo {} | |
| 8 | ||
| 9 | fn main() {} |
tests/ui/feature-gates/feature-gate-diagnostic-on-type-error-malformed-args.stderr created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | warning: unknown diagnostic attribute | |
| 2 | --> $DIR/feature-gate-diagnostic-on-type-error-malformed-args.rs:5:15 | |
| 3 | | | |
| 4 | LL | #[diagnostic::on_type_error(unknown = "")] | |
| 5 | | ^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | = help: add `#![feature(diagnostic_on_type_error)]` to the crate attributes to enable | |
| 8 | = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default | |
| 9 | ||
| 10 | warning: 1 warning emitted | |
| 11 |
tests/ui/impl-restriction/restriction_resolution_errors.rs+2-2| ... | ... | @@ -23,7 +23,7 @@ pub mod a { |
| 23 | 23 | |
| 24 | 24 | pub impl(in super::E) trait T6 {} //~ ERROR expected module, found enum `super::E` [E0577] |
| 25 | 25 | |
| 26 | pub impl(in super::super::super) trait T7 {} //~ ERROR too many leading `super` keywords [E0433] | |
| 26 | pub impl(in super::super::super) trait T7 {} //~ ERROR too many leading `super` keywords within `crate::a::b` [E0433] | |
| 27 | 27 | |
| 28 | 28 | // OK paths |
| 29 | 29 | pub impl(crate) trait T8 {} |
| ... | ... | @@ -53,7 +53,7 @@ pub impl(in crate::a::E) trait T14 {} //~ ERROR expected module, found enum `cra |
| 53 | 53 | pub impl(crate) trait T15 {} |
| 54 | 54 | pub impl(self) trait T16 {} |
| 55 | 55 | |
| 56 | pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords [E0433] | |
| 56 | pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords within `crate` [E0433] | |
| 57 | 57 | |
| 58 | 58 | pub impl(in external) trait T18 {} //~ ERROR trait implementation can only be restricted to ancestor modules |
| 59 | 59 |
tests/ui/impl-restriction/restriction_resolution_errors.stderr+4-4| ... | ... | @@ -16,11 +16,11 @@ error: trait implementation can only be restricted to ancestor modules |
| 16 | 16 | LL | pub impl(in super::d) trait T4 {} |
| 17 | 17 | | ^^^^^^^^ |
| 18 | 18 | |
| 19 | error[E0433]: too many leading `super` keywords | |
| 19 | error[E0433]: too many leading `super` keywords within `crate::a::b` | |
| 20 | 20 | --> $DIR/restriction_resolution_errors.rs:26:35 |
| 21 | 21 | | |
| 22 | 22 | LL | pub impl(in super::super::super) trait T7 {} |
| 23 | | ^^^^^ there are too many leading `super` keywords | |
| 23 | | ^^^^^ this `super` would go above the crate root | |
| 24 | 24 | |
| 25 | 25 | error: trait implementation can only be restricted to ancestor modules |
| 26 | 26 | --> $DIR/restriction_resolution_errors.rs:36:21 |
| ... | ... | @@ -40,11 +40,11 @@ error: trait implementation can only be restricted to ancestor modules |
| 40 | 40 | LL | pub impl(in crate::a) trait T13 {} |
| 41 | 41 | | ^^^^^^^^ |
| 42 | 42 | |
| 43 | error[E0433]: too many leading `super` keywords | |
| 43 | error[E0433]: too many leading `super` keywords within `crate` | |
| 44 | 44 | --> $DIR/restriction_resolution_errors.rs:56:10 |
| 45 | 45 | | |
| 46 | 46 | LL | pub impl(super) trait T17 {} |
| 47 | | ^^^^^ there are too many leading `super` keywords | |
| 47 | | ^^^^^ this `super` would go above the crate root | |
| 48 | 48 | |
| 49 | 49 | error: trait implementation can only be restricted to ancestor modules |
| 50 | 50 | --> $DIR/restriction_resolution_errors.rs:58:13 |
tests/ui/impl-trait/nested_impl_trait.stderr+8-2| ... | ... | @@ -50,8 +50,11 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } |
| 50 | 50 | | | |
| 51 | 51 | | the trait `From<impl Into<u32>>` is not implemented for `impl Debug` |
| 52 | 52 | | |
| 53 | help: the trait `Into<U>` is implemented for `T` | |
| 53 | help: the trait `Into<U>` is conditionally implemented for `T` | |
| 54 | 54 | --> $SRC_DIR/core/src/convert/mod.rs:LL:COL |
| 55 | ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL | |
| 56 | | | |
| 57 | = note: unsatisfied requirement introduced here: `impl Debug: From<impl Into<u32>>` | |
| 55 | 58 | = note: required for `impl Into<u32>` to implement `Into<impl Debug>` |
| 56 | 59 | |
| 57 | 60 | error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied |
| ... | ... | @@ -62,8 +65,11 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x } |
| 62 | 65 | | | |
| 63 | 66 | | the trait `From<impl Into<u32>>` is not implemented for `impl Debug` |
| 64 | 67 | | |
| 65 | help: the trait `Into<U>` is implemented for `T` | |
| 68 | help: the trait `Into<U>` is conditionally implemented for `T` | |
| 66 | 69 | --> $SRC_DIR/core/src/convert/mod.rs:LL:COL |
| 70 | ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL | |
| 71 | | | |
| 72 | = note: unsatisfied requirement introduced here: `impl Debug: From<impl Into<u32>>` | |
| 67 | 73 | = note: required for `impl Into<u32>` to implement `Into<impl Debug>` |
| 68 | 74 | |
| 69 | 75 | error: aborting due to 7 previous errors |
tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/158656>. | |
| 2 | ||
| 3 | //@ revisions: current next | |
| 4 | //@[next] compile-flags: -Znext-solver | |
| 5 | //@ check-pass | |
| 6 | ||
| 7 | trait Trait {} | |
| 8 | ||
| 9 | trait WithAssoc { | |
| 10 | type Assoc: ?Sized; | |
| 11 | } | |
| 12 | struct Thing; | |
| 13 | impl WithAssoc for Thing { | |
| 14 | type Assoc = dyn Trait; | |
| 15 | } | |
| 16 | ||
| 17 | fn foo() -> impl WithAssoc<Assoc = impl Trait + ?Sized> { | |
| 18 | Thing | |
| 19 | } | |
| 20 | ||
| 21 | fn main() {} |
tests/ui/keyword/keyword-super-as-identifier.rs+1-1| ... | ... | @@ -1,3 +1,3 @@ |
| 1 | 1 | fn main() { |
| 2 | let super = 22; //~ ERROR too many leading `super` keywords | |
| 2 | let super = 22; //~ ERROR too many leading `super` keywords within `crate` | |
| 3 | 3 | } |
tests/ui/keyword/keyword-super-as-identifier.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/keyword-super-as-identifier.rs:2:9 |
| 3 | 3 | | |
| 4 | 4 | LL | let super = 22; |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/keyword/keyword-super.rs+1-1| ... | ... | @@ -1,3 +1,3 @@ |
| 1 | 1 | fn main() { |
| 2 | let super: isize; //~ ERROR: too many leading `super` keywords | |
| 2 | let super: isize; //~ ERROR: too many leading `super` keywords within `crate` | |
| 3 | 3 | } |
tests/ui/keyword/keyword-super.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/keyword-super.rs:2:9 |
| 3 | 3 | | |
| 4 | 4 | LL | let super: isize; |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/lint/improper-ctypes/nonzero-char.rs created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | // Regression test for https://github.com/rust-lang/rust/issues/158511. | |
| 2 | ||
| 3 | #![allow(dead_code)] | |
| 4 | #![deny(improper_ctypes)] | |
| 5 | ||
| 6 | use std::num; | |
| 7 | ||
| 8 | extern "C" { | |
| 9 | fn result_nonzero_u32_t(x: Result<num::NonZero<char>, ()>); | |
| 10 | //~^ ERROR `extern` block uses type `char`, which is not FFI-safe | |
| 11 | } | |
| 12 | ||
| 13 | fn main() {} |
tests/ui/lint/improper-ctypes/nonzero-char.stderr created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | error: `extern` block uses type `char`, which is not FFI-safe | |
| 2 | --> $DIR/nonzero-char.rs:9:32 | |
| 3 | | | |
| 4 | LL | fn result_nonzero_u32_t(x: Result<num::NonZero<char>, ()>); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | |
| 6 | | | |
| 7 | = help: consider using `u32` or `libc::wchar_t` instead | |
| 8 | = note: the `char` type has no C equivalent | |
| 9 | note: the lint level is defined here | |
| 10 | --> $DIR/nonzero-char.rs:4:9 | |
| 11 | | | |
| 12 | LL | #![deny(improper_ctypes)] | |
| 13 | | ^^^^^^^^^^^^^^^ | |
| 14 | ||
| 15 | error: aborting due to 1 previous error | |
| 16 |
tests/ui/modules/super-at-crate-root.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //! Check that `super` keyword used at the crate root (top-level) results in a compilation error |
| 2 | 2 | //! as there is no parent module to resolve. |
| 3 | 3 | |
| 4 | use super::f; //~ ERROR too many leading `super` keywords | |
| 4 | use super::f; //~ ERROR too many leading `super` keywords within `crate` | |
| 5 | 5 | |
| 6 | 6 | fn main() {} |
tests/ui/modules/super-at-crate-root.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/super-at-crate-root.rs:4:5 |
| 3 | 3 | | |
| 4 | 4 | LL | use super::f; |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/resolve/impl-items-vis-unresolved.rs+1-1| ... | ... | @@ -19,7 +19,7 @@ pub struct RawFloatState; |
| 19 | 19 | impl RawFloatState { |
| 20 | 20 | perftools_inline! { |
| 21 | 21 | pub(super) fn new() {} |
| 22 | //~^ ERROR: too many leading `super` keywords | |
| 22 | //~^ ERROR: too many leading `super` keywords within `crate` | |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 |
tests/ui/resolve/impl-items-vis-unresolved.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/impl-items-vis-unresolved.rs:21:13 |
| 3 | 3 | | |
| 4 | 4 | LL | pub(super) fn new() {} |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/resolve/issue-117920.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #![crate_type = "lib"] |
| 2 | 2 | |
| 3 | use super::A; //~ ERROR too many leading `super` keywords | |
| 3 | use super::A; //~ ERROR too many leading `super` keywords within `crate` | |
| 4 | 4 | |
| 5 | 5 | mod b { |
| 6 | 6 | pub trait A {} |
tests/ui/resolve/issue-117920.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/issue-117920.rs:3:5 |
| 3 | 3 | | |
| 4 | 4 | LL | use super::A; |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/resolve/issue-82156.rs+1-1| ... | ... | @@ -1,3 +1,3 @@ |
| 1 | 1 | fn main() { |
| 2 | super(); //~ ERROR: too many leading `super` keywords | |
| 2 | super(); //~ ERROR: too many leading `super` keywords within `crate` | |
| 3 | 3 | } |
tests/ui/resolve/issue-82156.stderr+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | error[E0433]: too many leading `super` keywords | |
| 1 | error[E0433]: too many leading `super` keywords within `crate` | |
| 2 | 2 | --> $DIR/issue-82156.rs:2:5 |
| 3 | 3 | | |
| 4 | 4 | LL | super(); |
| 5 | | ^^^^^ there are too many leading `super` keywords | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | 6 | |
| 7 | 7 | error: aborting due to 1 previous error |
| 8 | 8 |
tests/ui/resolve/too-many-super-issue-158275.rs created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | #![crate_type = "lib"] | |
| 2 | ||
| 3 | mod outer { | |
| 4 | mod inner { | |
| 5 | struct Example(super::super::super::Impl); | |
| 6 | //~^ ERROR too many leading `super` keywords within `crate::outer::inner` | |
| 7 | } | |
| 8 | } | |
| 9 | ||
| 10 | struct Impl; |
tests/ui/resolve/too-many-super-issue-158275.stderr created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | error[E0433]: too many leading `super` keywords within `crate::outer::inner` | |
| 2 | --> $DIR/too-many-super-issue-158275.rs:5:38 | |
| 3 | | | |
| 4 | LL | struct Example(super::super::super::Impl); | |
| 5 | | ^^^^^ this `super` would go above the crate root | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 | ||
| 9 | For more information about this error, try `rustc --explain E0433`. |
tests/ui/splat/run-splat.rs created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //! Check that splat codegen works for simple cases. | |
| 2 | //@ run-pass | |
| 3 | //@ check-run-results | |
| 4 | #![feature(splat, tuple_trait)] | |
| 5 | #![expect(incomplete_features)] | |
| 6 | ||
| 7 | use std::marker::Tuple; | |
| 8 | ||
| 9 | struct Foo; | |
| 10 | ||
| 11 | trait MethodArgs: Tuple { | |
| 12 | fn call_method(self, this: &Foo); | |
| 13 | } | |
| 14 | ||
| 15 | impl Foo { | |
| 16 | fn method(&self, #[splat] args: impl MethodArgs) { | |
| 17 | args.call_method(self) | |
| 18 | } | |
| 19 | } | |
| 20 | ||
| 21 | impl MethodArgs for (i32, String) { | |
| 22 | fn call_method(self, _this: &Foo) { | |
| 23 | dbg!(self.1, self.0); | |
| 24 | } | |
| 25 | } | |
| 26 | ||
| 27 | impl MethodArgs for (f64,) { | |
| 28 | fn call_method(self, _this: &Foo) { | |
| 29 | dbg!(self.0); | |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 33 | fn main() { | |
| 34 | let foo = Foo; | |
| 35 | foo.method(42, "hello splat".to_string()); | |
| 36 | foo.method(3.141); | |
| 37 | } |
tests/ui/splat/run-splat.run.stderr created+3| ... | ... | @@ -0,0 +1,3 @@ |
| 1 | [$DIR/run-splat.rs:23:9] self.1 = "hello splat" | |
| 2 | [$DIR/run-splat.rs:23:9] self.0 = 42 | |
| 3 | [$DIR/run-splat.rs:29:9] self.0 = 3.141 |
tests/ui/splat/splat-dyn-asref-tuple-fail.rs+27-2| ... | ... | @@ -4,11 +4,36 @@ |
| 4 | 4 | #![feature(splat)] |
| 5 | 5 | #![feature(tuple_trait)] |
| 6 | 6 | |
| 7 | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {} | |
| 8 | //~^ ERROR cannot use splat attribute | |
| 7 | // Strip binders and their lifetime numbers from error messages | |
| 8 | //@ normalize-stderr: "&.*value: (.*), bound_vars: .*" -> "$1" | |
| 9 | ||
| 10 | // FIXME(splat): Some errors are reported on the callee, but they would be more ergonomic on the | |
| 11 | // caller as well | |
| 12 | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 13 | //~^ ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a | |
| 14 | //~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a | |
| 15 | //~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a | |
| 16 | //~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a | |
| 17 | where | |
| 18 | T: std::marker::Tuple, | |
| 19 | { | |
| 20 | } | |
| 9 | 21 | |
| 10 | 22 | fn main() { |
| 23 | // These error patterns are reported on the function definition, but we can't check for two | |
| 24 | // strings in the same error message | |
| 11 | 25 | let s: String = "hello".to_owned(); |
| 12 | 26 | dyn_asref_splat::<String>(&s); |
| 13 | 27 | //~^ ERROR `String` is not a tuple |
| 28 | //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<.*String>\) | |
| 29 | ||
| 30 | dyn_asref_splat(&s); | |
| 31 | //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\) | |
| 32 | ||
| 33 | let t = (1u8, 2f32); | |
| 34 | dyn_asref_splat::<(u8, f32)>(&t); | |
| 35 | //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<\(u8, f32\)>\) | |
| 36 | ||
| 37 | dyn_asref_splat(&t); | |
| 38 | //@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\) | |
| 14 | 39 | } |
tests/ui/splat/splat-dyn-asref-tuple-fail.stderr+38-8| ... | ... | @@ -1,24 +1,54 @@ |
| 1 | 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<std::string::String>), bound_vars: [] }] + '?3 (&'?3 dyn [Binder { value: Trait(std::convert::AsRef<std::string::String>), bound_vars: [] }] + '?3) | |
| 2 | --> $DIR/splat-dyn-asref-tuple-fail.rs:7:36 | |
| 1 | error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<std::string::String>) | |
| 2 | --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 | |
| 3 | 3 | | |
| 4 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {} | |
| 4 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | ... |
| 7 | 7 | LL | dyn_asref_splat::<String>(&s); |
| 8 | 8 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 9 | 9 | |
| 10 | 10 | error[E0277]: `String` is not a tuple |
| 11 | --> $DIR/splat-dyn-asref-tuple-fail.rs:12:23 | |
| 11 | --> $DIR/splat-dyn-asref-tuple-fail.rs:26:23 | |
| 12 | 12 | | |
| 13 | 13 | LL | dyn_asref_splat::<String>(&s); |
| 14 | 14 | | ^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `String` |
| 15 | 15 | | |
| 16 | 16 | note: required by a bound in `dyn_asref_splat` |
| 17 | --> $DIR/splat-dyn-asref-tuple-fail.rs:7:60 | |
| 17 | --> $DIR/splat-dyn-asref-tuple-fail.rs:18:8 | |
| 18 | 18 | | |
| 19 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {} | |
| 20 | | ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat` | |
| 19 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 20 | | --------------- required by a bound in this function | |
| 21 | ... | |
| 22 | LL | T: std::marker::Tuple, | |
| 23 | | ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat` | |
| 24 | ||
| 25 | error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>) | |
| 26 | --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 | |
| 27 | | | |
| 28 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 29 | | ^^^^^^^^^^^^^ | |
| 30 | ... | |
| 31 | LL | dyn_asref_splat(&s); | |
| 32 | | ^^^^^^^^^^^^^^^^^^^ | |
| 33 | ||
| 34 | error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<(u8, f32)>) | |
| 35 | --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 | |
| 36 | | | |
| 37 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 38 | | ^^^^^^^^^^^^^ | |
| 39 | ... | |
| 40 | LL | dyn_asref_splat::<(u8, f32)>(&t); | |
| 41 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 42 | ||
| 43 | error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>) | |
| 44 | --> $DIR/splat-dyn-asref-tuple-fail.rs:12:36 | |
| 45 | | | |
| 46 | LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) | |
| 47 | | ^^^^^^^^^^^^^ | |
| 48 | ... | |
| 49 | LL | dyn_asref_splat(&t); | |
| 50 | | ^^^^^^^^^^^^^^^^^^^ | |
| 21 | 51 | |
| 22 | error: aborting due to 2 previous errors | |
| 52 | error: aborting due to 5 previous errors | |
| 23 | 53 | |
| 24 | 54 | For more information about this error, try `rustc --explain E0277`. |
tests/ui/splat/splat-fn-ptr-cast-fail.rs created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | //! Test casting splatted functions to non-splatted function pointers fails. | |
| 2 | ||
| 3 | #![allow(incomplete_features)] | |
| 4 | #![feature(splat, tuple_trait)] | |
| 5 | ||
| 6 | use std::marker::Tuple; | |
| 7 | ||
| 8 | fn tuple_args(#[splat] (_a, _b): (u32, i8)) {} | |
| 9 | ||
| 10 | fn splat_non_terminal_arg(#[splat] (_a, _b): (u32, i8), _c: f64) {} | |
| 11 | ||
| 12 | fn f<Args: Tuple>(#[splat] args: Args) {} | |
| 13 | ||
| 14 | fn main() { | |
| 15 | // Function pointers | |
| 16 | let _fn_ptr: fn((u32, i8)) = tuple_args; //~ ERROR mismatched types | |
| 17 | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg; //~ ERROR mismatched types | |
| 18 | ||
| 19 | let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8)); //~ ERROR non-primitive cast | |
| 20 | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64); //~ ERROR non-primitive cast | |
| 21 | ||
| 22 | // Bug #158603 regression test variants | |
| 23 | const _F2: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types | |
| 24 | const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>; //~ ERROR mismatched types | |
| 25 | } |
tests/ui/splat/splat-fn-ptr-cast-fail.stderr created+60| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | error[E0308]: mismatched types | |
| 2 | --> $DIR/splat-fn-ptr-cast-fail.rs:16:34 | |
| 3 | | | |
| 4 | LL | let _fn_ptr: fn((u32, i8)) = tuple_args; | |
| 5 | | ------------- ^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted | |
| 6 | | | | |
| 7 | | expected due to this | |
| 8 | | | |
| 9 | = note: expected fn pointer `fn((_, _))` | |
| 10 | found fn item `fn(#[splat] (_, _)) {tuple_args}` | |
| 11 | ||
| 12 | error[E0308]: mismatched types | |
| 13 | --> $DIR/splat-fn-ptr-cast-fail.rs:17:39 | |
| 14 | | | |
| 15 | LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg; | |
| 16 | | ------------------ ^^^^^^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted | |
| 17 | | | | |
| 18 | | expected due to this | |
| 19 | | | |
| 20 | = note: expected fn pointer `fn((_, _), _)` | |
| 21 | found fn item `fn(#[splat] (_, _), _) {splat_non_terminal_arg}` | |
| 22 | ||
| 23 | error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8)) {tuple_args}` as `fn((u32, i8))` | |
| 24 | --> $DIR/splat-fn-ptr-cast-fail.rs:19:34 | |
| 25 | | | |
| 26 | LL | let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8)); | |
| 27 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast | |
| 28 | ||
| 29 | error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8), f64) {splat_non_terminal_arg}` as `fn((u32, i8), f64)` | |
| 30 | --> $DIR/splat-fn-ptr-cast-fail.rs:20:39 | |
| 31 | | | |
| 32 | LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64); | |
| 33 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast | |
| 34 | ||
| 35 | error[E0308]: mismatched types | |
| 36 | --> $DIR/splat-fn-ptr-cast-fail.rs:23:32 | |
| 37 | | | |
| 38 | LL | const _F2: fn((u8, u32)) = f::<(u8, u32)>; | |
| 39 | | ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted | |
| 40 | | | | |
| 41 | | expected because of the type of the constant | |
| 42 | | | |
| 43 | = note: expected fn pointer `fn((_, _))` | |
| 44 | found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}` | |
| 45 | ||
| 46 | error[E0308]: mismatched types | |
| 47 | --> $DIR/splat-fn-ptr-cast-fail.rs:24:35 | |
| 48 | | | |
| 49 | LL | const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>; | |
| 50 | | ---------------- ^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted | |
| 51 | | | | |
| 52 | | expected because of the type of the constant | |
| 53 | | | |
| 54 | = note: expected fn pointer `fn(((_, _),))` | |
| 55 | found fn item `fn(#[splat] ((_, _),)) {f::<((u8, u32),)>}` | |
| 56 | ||
| 57 | error: aborting due to 6 previous errors | |
| 58 | ||
| 59 | Some errors have detailed explanations: E0308, E0605. | |
| 60 | For more information about an error, try `rustc --explain E0308`. |
tests/ui/splat/splat-fn-tuple-generic-fail.rs+7-1| ... | ... | @@ -4,7 +4,11 @@ |
| 4 | 4 | #![feature(splat)] |
| 5 | 5 | #![feature(tuple_trait)] |
| 6 | 6 | |
| 7 | fn splat_generic_tuple<T: std::marker::Tuple>(#[splat] _t: T) {} | |
| 7 | use std::marker::Tuple; | |
| 8 | ||
| 9 | fn splat_generic_tuple<T: Tuple>(#[splat] _t: T) {} | |
| 10 | ||
| 11 | fn f<Args: Tuple>(#[splat] args: Args) {} | |
| 8 | 12 | |
| 9 | 13 | fn main() { |
| 10 | 14 | // FIXME(splat): should splatted functions be callable with tupled and un-tupled arguments? |
| ... | ... | @@ -24,4 +28,6 @@ fn main() { |
| 24 | 28 | |
| 25 | 29 | splat_generic_tuple::<(u32, i8)>((1, 2)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided |
| 26 | 30 | splat_generic_tuple::<(u32, i8)>((1u32, 2i8)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided |
| 31 | ||
| 32 | const F1: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types | |
| 27 | 33 | } |
tests/ui/splat/splat-fn-tuple-generic-fail.stderr+20-8| ... | ... | @@ -1,39 +1,51 @@ |
| 1 | 1 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 2 | --> $DIR/splat-fn-tuple-generic-fail.rs:19:5 | |
| 2 | --> $DIR/splat-fn-tuple-generic-fail.rs:23:5 | |
| 3 | 3 | | |
| 4 | 4 | LL | splat_generic_tuple::<(((u32, i8)))>((1, 2)); |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 8 | --> $DIR/splat-fn-tuple-generic-fail.rs:20:5 | |
| 8 | --> $DIR/splat-fn-tuple-generic-fail.rs:24:5 | |
| 9 | 9 | | |
| 10 | 10 | LL | splat_generic_tuple::<(((u32, i8)))>((1u32, 2i8)); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | |
| 13 | 13 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 14 | --> $DIR/splat-fn-tuple-generic-fail.rs:22:5 | |
| 14 | --> $DIR/splat-fn-tuple-generic-fail.rs:26:5 | |
| 15 | 15 | | |
| 16 | 16 | LL | splat_generic_tuple::<((u32, i8))>((1, 2)); |
| 17 | 17 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 18 | 18 | |
| 19 | 19 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 20 | --> $DIR/splat-fn-tuple-generic-fail.rs:23:5 | |
| 20 | --> $DIR/splat-fn-tuple-generic-fail.rs:27:5 | |
| 21 | 21 | | |
| 22 | 22 | LL | splat_generic_tuple::<((u32, i8))>((1u32, 2i8)); |
| 23 | 23 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 24 | 24 | |
| 25 | 25 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 26 | --> $DIR/splat-fn-tuple-generic-fail.rs:25:5 | |
| 26 | --> $DIR/splat-fn-tuple-generic-fail.rs:29:5 | |
| 27 | 27 | | |
| 28 | 28 | LL | splat_generic_tuple::<(u32, i8)>((1, 2)); |
| 29 | 29 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 30 | 30 | |
| 31 | 31 | error[E0057]: this splatted function takes 2 arguments, but 1 was provided |
| 32 | --> $DIR/splat-fn-tuple-generic-fail.rs:26:5 | |
| 32 | --> $DIR/splat-fn-tuple-generic-fail.rs:30:5 | |
| 33 | 33 | | |
| 34 | 34 | LL | splat_generic_tuple::<(u32, i8)>((1u32, 2i8)); |
| 35 | 35 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 36 | 36 | |
| 37 | error: aborting due to 6 previous errors | |
| 37 | error[E0308]: mismatched types | |
| 38 | --> $DIR/splat-fn-tuple-generic-fail.rs:32:31 | |
| 39 | | | |
| 40 | LL | const F1: fn((u8, u32)) = f::<(u8, u32)>; | |
| 41 | | ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted | |
| 42 | | | | |
| 43 | | expected because of the type of the constant | |
| 44 | | | |
| 45 | = note: expected fn pointer `fn((_, _))` | |
| 46 | found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}` | |
| 47 | ||
| 48 | error: aborting due to 7 previous errors | |
| 38 | 49 | |
| 39 | For more information about this error, try `rustc --explain E0057`. | |
| 50 | Some errors have detailed explanations: E0057, E0308. | |
| 51 | For more information about an error, try `rustc --explain E0057`. |
tests/ui/splat/splat-generics-everywhere.rs+20-7| ... | ... | @@ -3,11 +3,10 @@ |
| 3 | 3 | |
| 4 | 4 | #![allow(incomplete_features)] |
| 5 | 5 | #![feature(splat)] |
| 6 | #![feature(tuple_trait)] | |
| 6 | 7 | |
| 7 | 8 | struct Foo<T>(T); |
| 8 | 9 | |
| 9 | // FIXME(splat): also add assoc/method with splatted generic tuple traits | |
| 10 | // also add generics inside the splatted tuple | |
| 11 | 10 | impl<T> Foo<T> { |
| 12 | 11 | fn new(t: T) -> Self { |
| 13 | 12 | Self(t) |
| ... | ... | @@ -20,12 +19,13 @@ impl<T> Foo<T> { |
| 20 | 19 | fn lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} |
| 21 | 20 | |
| 22 | 21 | fn const_generic<const N: usize>(&self, #[splat] _s: (u32, f64, [u8; N])) {} |
| 22 | ||
| 23 | fn generic_in_tuple<U>(&self, #[splat] _s: (U, u32)) {} | |
| 24 | ||
| 25 | fn generic_tuple_assoc<U: std::marker::Tuple>(_u: U, #[splat] _s: ()) {} | |
| 23 | 26 | } |
| 24 | 27 | |
| 25 | // FIXME(splat): also add generics to the trait | |
| 26 | // also add assoc/method with splatted generic tuple traits | |
| 27 | // also add generics inside the splatted tuple | |
| 28 | trait BarTrait { | |
| 28 | trait BarTrait<T> { | |
| 29 | 29 | fn trait_assoc<W>(w: W, #[splat] _s: ()); |
| 30 | 30 | |
| 31 | 31 | fn trait_method<X>(&self, x: X, #[splat] _s: (u32, f64)); |
| ... | ... | @@ -33,9 +33,13 @@ trait BarTrait { |
| 33 | 33 | fn trait_lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} |
| 34 | 34 | |
| 35 | 35 | fn trait_const_generic<const N: usize>(&self, #[splat] _s: (u32, f64, [u8; N])) {} |
| 36 | ||
| 37 | fn trait_generic_in_tuple<U>(&self, #[splat] _s: (T, U)) {} | |
| 38 | ||
| 39 | fn trait_generic_tuple<U: std::marker::Tuple>(&self, #[splat] _s: U) {} | |
| 36 | 40 | } |
| 37 | 41 | |
| 38 | impl<T> BarTrait for Foo<T> { | |
| 42 | impl<T> BarTrait<T> for Foo<T> { | |
| 39 | 43 | fn trait_assoc<W>(_w: W, #[splat] _s: ()) {} |
| 40 | 44 | |
| 41 | 45 | fn trait_method<X>(&self, _x: X, #[splat] _s: (u32, f64)) {} |
| ... | ... | @@ -43,6 +47,10 @@ impl<T> BarTrait for Foo<T> { |
| 43 | 47 | fn trait_lifetime<'a>(&self, #[splat] _s: (u32, f64, &'a str)) {} |
| 44 | 48 | |
| 45 | 49 | fn trait_const_generic<const N: usize>(&self, #[splat] _s: (u32, f64, [u8; N])) {} |
| 50 | ||
| 51 | fn trait_generic_in_tuple<U>(&self, #[splat] _s: (T, U)) {} | |
| 52 | ||
| 53 | fn trait_generic_tuple<U: std::marker::Tuple>(&self, #[splat] _s: U) {} | |
| 46 | 54 | } |
| 47 | 55 | |
| 48 | 56 | fn main() { |
| ... | ... | @@ -57,8 +65,13 @@ fn main() { |
| 57 | 65 | foo.method("v", 1u32, 2.3); |
| 58 | 66 | foo.lifetime(1u32, 2.3, "asdf"); |
| 59 | 67 | foo.const_generic(1u32, 2.3, [1, 2, 3]); |
| 68 | foo.generic_in_tuple(42i32, 1u32); | |
| 69 | Foo::<f32>::generic_tuple_assoc(()); | |
| 60 | 70 | |
| 71 | Foo::<u32>::trait_assoc("w"); | |
| 61 | 72 | foo.trait_method("x", 42u32, 9.8); |
| 62 | 73 | foo.trait_lifetime(1u32, 2.3, "asdf"); |
| 63 | 74 | foo.trait_const_generic(1u32, 2.3, [1, 2, 3]); |
| 75 | foo.trait_generic_in_tuple("hello", 42i32); | |
| 76 | foo.trait_generic_tuple(); | |
| 64 | 77 | } |
tests/ui/splat/splat-self.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ run-pass | |
| 2 | //@ check-run-results | |
| 3 | //! Test using `#[splat]` on self arguments of trait methods. | |
| 4 | ||
| 5 | #![feature(splat)] | |
| 6 | #![expect(incomplete_features)] | |
| 7 | ||
| 8 | trait Trait { | |
| 9 | fn method(#[splat] self: Self); | |
| 10 | } | |
| 11 | ||
| 12 | impl Trait for (i32, i64) { | |
| 13 | fn method(#[splat] self: Self) { | |
| 14 | println!("{self:?}"); | |
| 15 | } | |
| 16 | } | |
| 17 | ||
| 18 | fn main() { | |
| 19 | (1_i32, 2_i64).method(); | |
| 20 | Trait::method(3_i32, 4_i64); | |
| 21 | } |
tests/ui/splat/splat-self.run.stdout created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | (1, 2) | |
| 2 | (3, 4) |
tests/ui/traits/copy-bounds-impl-type-params.stderr+8-4| ... | ... | @@ -80,11 +80,13 @@ error[E0277]: the trait bound `String: Copy` is not satisfied |
| 80 | 80 | LL | let a = t as Box<dyn Gettable<String>>; |
| 81 | 81 | | ^ the trait `Copy` is not implemented for `String` |
| 82 | 82 | | |
| 83 | help: the trait `Gettable<T>` is implemented for `S<T>` | |
| 83 | help: the trait `Gettable<T>` is conditionally implemented for `S<T>` | |
| 84 | 84 | --> $DIR/copy-bounds-impl-type-params.rs:14:1 |
| 85 | 85 | | |
| 86 | 86 | LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} |
| 87 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 87 | | ^^^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 88 | | | | |
| 89 | | unsatisfied requirement introduced here: `String: Copy` | |
| 88 | 90 | note: required for `S<String>` to implement `Gettable<String>` |
| 89 | 91 | --> $DIR/copy-bounds-impl-type-params.rs:14:32 |
| 90 | 92 | | |
| ... | ... | @@ -100,11 +102,13 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied |
| 100 | 102 | LL | let a: Box<dyn Gettable<Foo>> = t; |
| 101 | 103 | | ^ the trait `Copy` is not implemented for `Foo` |
| 102 | 104 | | |
| 103 | help: the trait `Gettable<T>` is implemented for `S<T>` | |
| 105 | help: the trait `Gettable<T>` is conditionally implemented for `S<T>` | |
| 104 | 106 | --> $DIR/copy-bounds-impl-type-params.rs:14:1 |
| 105 | 107 | | |
| 106 | 108 | LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} |
| 107 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 109 | | ^^^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 110 | | | | |
| 111 | | unsatisfied requirement introduced here: `Foo: Copy` | |
| 108 | 112 | note: required for `S<Foo>` to implement `Gettable<Foo>` |
| 109 | 113 | --> $DIR/copy-bounds-impl-type-params.rs:14:32 |
| 110 | 114 | | |
tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.rs created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | struct Test(i32, i64); | |
| 2 | trait Foo<'a> { | |
| 3 | type Assoc; | |
| 4 | } | |
| 5 | ||
| 6 | trait SimpleFoo { | |
| 7 | type SimpleAssoc; | |
| 8 | } | |
| 9 | impl<'a, T> Foo<'a> for T where T: SimpleFoo { | |
| 10 | type Assoc = T::SimpleAssoc; | |
| 11 | } | |
| 12 | ||
| 13 | impl SimpleFoo for i32 { | |
| 14 | type SimpleAssoc = i32; | |
| 15 | } | |
| 16 | impl SimpleFoo for i64 { | |
| 17 | type SimpleAssoc = i32; | |
| 18 | } | |
| 19 | ||
| 20 | impl<'a> Foo<'a> for Test where i32: Foo<'a, Assoc = i32>, i64: Foo<'a, Assoc = i64> { | |
| 21 | type Assoc = Test; | |
| 22 | } | |
| 23 | ||
| 24 | fn process<'a, T: Foo<'a>>(_input: T) {} | |
| 25 | fn test() { process(Test(0, 1)) } | |
| 26 | //~^ ERROR the trait bound `Test: Foo<'_>` is not satisfied | |
| 27 | ||
| 28 | fn main() {} |
tests/ui/traits/error_reporting/conditionally-implemented-trait-158423.stderr created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | error[E0277]: the trait bound `Test: Foo<'_>` is not satisfied | |
| 2 | --> $DIR/conditionally-implemented-trait-158423.rs:25:21 | |
| 3 | | | |
| 4 | LL | fn test() { process(Test(0, 1)) } | |
| 5 | | ------- ^^^^^^^^^^ unsatisfied trait bound | |
| 6 | | | | |
| 7 | | required by a bound introduced by this call | |
| 8 | | | |
| 9 | help: the trait `Foo<'_>` is not implemented for `Test` | |
| 10 | --> $DIR/conditionally-implemented-trait-158423.rs:1:1 | |
| 11 | | | |
| 12 | LL | struct Test(i32, i64); | |
| 13 | | ^^^^^^^^^^^ | |
| 14 | help: the trait `Foo<'_>` is conditionally implemented for `Test` | |
| 15 | --> $DIR/conditionally-implemented-trait-158423.rs:20:1 | |
| 16 | | | |
| 17 | LL | impl<'a> Foo<'a> for Test where i32: Foo<'a, Assoc = i32>, i64: Foo<'a, Assoc = i64> { | |
| 18 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^ | |
| 19 | | | | |
| 20 | | unsatisfied requirement introduced here: `<i64 as Foo<'_>>::Assoc == i64` | |
| 21 | note: required by a bound in `process` | |
| 22 | --> $DIR/conditionally-implemented-trait-158423.rs:24:19 | |
| 23 | | | |
| 24 | LL | fn process<'a, T: Foo<'a>>(_input: T) {} | |
| 25 | | ^^^^^^^ required by this bound in `process` | |
| 26 | ||
| 27 | error: aborting due to 1 previous error | |
| 28 | ||
| 29 | For more information about this error, try `rustc --explain E0277`. |
tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr+1-1| ... | ... | @@ -7,7 +7,7 @@ LL | struct LocalTy; |
| 7 | 7 | LL | impl Trait for <LocalTy as Overflow>::Assoc {} |
| 8 | 8 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation |
| 9 | 9 | | |
| 10 | = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc` | |
| 10 | = note: overflow evaluating the requirement `<LocalTy as Overflow>::Assoc == _` | |
| 11 | 11 | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) |
| 12 | 12 | |
| 13 | 13 | error: aborting due to 1 previous error |
tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | //@ compile-flags: -Znext-solver | |
| 2 | ||
| 3 | //! This test is extremely similar to `nested-rerun-not-erased-in-normalizes-to.rs`, however, | |
| 4 | //! instead of the eager normalization failing due to an anon const when in ErasedNotCoherence, this | |
| 5 | //! just straight up fails normalization because u32 is not Iterator | |
| 6 | ||
| 7 | #![feature(ptr_metadata)] | |
| 8 | ||
| 9 | struct ThisStructAintValid(<u32 as Iterator>::Item); | |
| 10 | //~^ ERROR `u32` is not an iterator | |
| 11 | ||
| 12 | fn main() { | |
| 13 | let y: <ThisStructAintValid as std::ptr::Pointee>::Metadata; | |
| 14 | //~^ ERROR type mismatch resolving `<ThisStructAintValid as Pointee>::Metadata == _` | |
| 15 | } |
tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | error[E0277]: `u32` is not an iterator | |
| 2 | --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:9:28 | |
| 3 | | | |
| 4 | LL | struct ThisStructAintValid(<u32 as Iterator>::Item); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not an iterator | |
| 6 | | | |
| 7 | = help: the trait `Iterator` is not implemented for `u32` | |
| 8 | ||
| 9 | error[E0271]: type mismatch resolving `<ThisStructAintValid as Pointee>::Metadata == _` | |
| 10 | --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:13:12 | |
| 11 | | | |
| 12 | LL | let y: <ThisStructAintValid as std::ptr::Pointee>::Metadata; | |
| 13 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | |
| 14 | ||
| 15 | error: aborting due to 2 previous errors | |
| 16 | ||
| 17 | Some errors have detailed explanations: E0271, E0277. | |
| 18 | For more information about an error, try `rustc --explain E0271`. |
tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr+2-1| ... | ... | @@ -9,13 +9,14 @@ help: the trait `Trait<_, _, _>` is not implemented for `A<X>` |
| 9 | 9 | | |
| 10 | 10 | LL | struct A<T>(*const T); |
| 11 | 11 | | ^^^^^^^^^^^ |
| 12 | help: the trait `Trait<U, V, D>` is implemented for `A<T>` | |
| 12 | help: the trait `Trait<U, V, D>` is conditionally implemented for `A<T>` | |
| 13 | 13 | --> $DIR/incompleteness-unstable-result.rs:34:1 |
| 14 | 14 | | |
| 15 | 15 | LL | / impl<T, U, V, D> Trait<U, V, D> for A<T> |
| 16 | 16 | LL | | where |
| 17 | 17 | LL | | T: IncompleteGuidance<U, V>, |
| 18 | 18 | LL | | A<T>: Trait<U, D, V>, |
| 19 | | | -------------- unsatisfied requirement introduced here: `A<_>: Trait<_, _, _>` | |
| 19 | 20 | LL | | B<T>: Trait<U, V, D>, |
| 20 | 21 | LL | | (): ToU8<D>, |
| 21 | 22 | | |________________^ |
tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr+2-1| ... | ... | @@ -9,13 +9,14 @@ help: the trait `Trait<_, _, _>` is not implemented for `A<X>` |
| 9 | 9 | | |
| 10 | 10 | LL | struct A<T>(*const T); |
| 11 | 11 | | ^^^^^^^^^^^ |
| 12 | help: the trait `Trait<U, V, D>` is implemented for `A<T>` | |
| 12 | help: the trait `Trait<U, V, D>` is conditionally implemented for `A<T>` | |
| 13 | 13 | --> $DIR/incompleteness-unstable-result.rs:34:1 |
| 14 | 14 | | |
| 15 | 15 | LL | / impl<T, U, V, D> Trait<U, V, D> for A<T> |
| 16 | 16 | LL | | where |
| 17 | 17 | LL | | T: IncompleteGuidance<U, V>, |
| 18 | 18 | LL | | A<T>: Trait<U, D, V>, |
| 19 | | | -------------- unsatisfied requirement introduced here: `A<_>: Trait<_, _, _>` | |
| 19 | 20 | LL | | B<T>: Trait<U, V, D>, |
| 20 | 21 | LL | | (): ToU8<D>, |
| 21 | 22 | | |________________^ |
tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | //@ build-pass | |
| 2 | //@ compile-flags: -Znext-solver | |
| 3 | ||
| 4 | //! Consider: | |
| 5 | //! | |
| 6 | //! goal is <StructTailHasAnonConst as Pointee>::Metadata == ?0, in a typing context of | |
| 7 | //! ErasedNotCoherence | |
| 8 | //! | |
| 9 | //! `consider_builtin_pointee_candidate` looks at StructTailHasAnonConst, realizes it's an ADT, | |
| 10 | //! fetches the struct tail (which is `S<{ 2 + 2 }>`), and calls `instantiate_normalizes_to_term` | |
| 11 | //! with the result of `<Struct<{ 2 + 2 }> as Pointee>::Metadata` | |
| 12 | //! | |
| 13 | //! `instantiate_normalizes_to_term` `.eq()`s `<Struct<{ 2 + 2 }> as Pointee>::Metadata` and `?0` | |
| 14 | //! | |
| 15 | //! this eagerly normalizes, which normalizes the anon const, which fails due to ErasedNotCoherence | |
| 16 | //! | |
| 17 | //! this causes the `.eq()` in `instantiate_normalizes_to_term` to fail, which used to have an | |
| 18 | //! unwrap, which ICEd | |
| 19 | ||
| 20 | #![feature(ptr_metadata)] | |
| 21 | ||
| 22 | struct S<const N: usize>; | |
| 23 | ||
| 24 | struct StructTailHasAnonConst(S<{ 2 + 2 }>); | |
| 25 | ||
| 26 | fn main() { | |
| 27 | let y: <StructTailHasAnonConst as std::ptr::Pointee>::Metadata; | |
| 28 | } |
tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs+1| ... | ... | @@ -14,6 +14,7 @@ fn needs_bar<S: Bar>() {} |
| 14 | 14 | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() { |
| 15 | 15 | needs_bar::<T::Assoc1>(); |
| 16 | 16 | //~^ ERROR: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied |
| 17 | //~| ERROR: the size for values of type `<T as Foo2>::Assoc2` cannot be known at compilation time | |
| 17 | 18 | } |
| 18 | 19 | |
| 19 | 20 | fn main() {} |
tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr+22-1| ... | ... | @@ -14,6 +14,27 @@ help: consider further restricting the associated type |
| 14 | 14 | LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar { |
| 15 | 15 | | ++++++++++++++++++++++++++++++ |
| 16 | 16 | |
| 17 | error: aborting due to 1 previous error | |
| 17 | error[E0277]: the size for values of type `<T as Foo2>::Assoc2` cannot be known at compilation time | |
| 18 | --> $DIR/recursive-self-normalization-2.rs:15:17 | |
| 19 | | | |
| 20 | LL | needs_bar::<T::Assoc1>(); | |
| 21 | | ^^^^^^^^^ doesn't have a size known at compile-time | |
| 22 | | | |
| 23 | = help: the trait `Sized` is not implemented for `<T as Foo2>::Assoc2` | |
| 24 | note: required by an implicit `Sized` bound in `needs_bar` | |
| 25 | --> $DIR/recursive-self-normalization-2.rs:12:14 | |
| 26 | | | |
| 27 | LL | fn needs_bar<S: Bar>() {} | |
| 28 | | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` | |
| 29 | help: consider further restricting the associated type | |
| 30 | | | |
| 31 | LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Sized { | |
| 32 | | ++++++++++++++++++++++++++++++++ | |
| 33 | help: consider relaxing the implicit `Sized` restriction | |
| 34 | | | |
| 35 | LL | fn needs_bar<S: Bar + ?Sized>() {} | |
| 36 | | ++++++++ | |
| 37 | ||
| 38 | error: aborting due to 2 previous errors | |
| 18 | 39 | |
| 19 | 40 | For more information about this error, try `rustc --explain E0277`. |