diff --git a/.mailmap b/.mailmap index 2a53cbf9effc4..90533e81b39ff 100644 --- a/.mailmap +++ b/.mailmap @@ -690,6 +690,7 @@ Xinye Tao Xuefeng Wu Xuefeng Wu Xuefeng Wu XuefengWu York Xiang +Yotam Ofek Youngsoo Son Youngsuk Kim Yuki Okushi diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7680f8e107439..a81f4a7aa7189 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use rustc_abi::ExternAbi; +use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_attr_data_structures::{ @@ -402,6 +402,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); + // On trait methods, inherit the `#[align]` of the trait's method prototype. + codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did)); + let inline_span; (codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) = find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span)) @@ -556,17 +559,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs } +/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype. +fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let impl_item = tcx.opt_associated_item(def_id)?; + match impl_item.container { + ty::AssocItemContainer::Impl => impl_item.trait_item_def_id, + _ => None, + } +} + /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - if let Some(impl_item) = tcx.opt_associated_item(def_id) - && let ty::AssocItemContainer::Impl = impl_item.container - && let Some(trait_item) = impl_item.trait_item_def_id - { - return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER); - } + let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false }; + tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER) +} - false +/// If the provided DefId is a method in a trait impl, return the value of the `#[align]` +/// attribute on the method prototype (if any). +fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { + tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment } fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option { @@ -734,5 +746,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; + *providers = + Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..*providers }; } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index db5ac6a514fb4..e1d8b7546cf42 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1123,7 +1123,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // While optimizations will remove no-op transmutes, they might still be // there in debug or things that aren't no-op in MIR because they change // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar { + if from_scalar == to_scalar && from_backend_ty == to_backend_ty { return imm; } @@ -1142,13 +1142,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | Float(_), Int(..) | Float(_)) => { - if from_backend_ty == to_backend_ty { - imm - } else { - bx.bitcast(imm, to_backend_ty) - } - } + (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 26a31cb055ebe..f138c5ca039ec 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -266,6 +266,7 @@ trivial! { Option, Option, Option, + Option, Result<(), rustc_errors::ErrorGuaranteed>, Result<(), rustc_middle::traits::query::NoSolution>, Result, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8a3d26e1b0314..09295157b5428 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -67,6 +67,7 @@ use std::mem; use std::path::PathBuf; use std::sync::Arc; +use rustc_abi::Align; use rustc_arena::TypedArena; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::expand::allocator::AllocatorKind; @@ -1481,6 +1482,10 @@ rustc_queries! { desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } } + query inherited_align(def_id: DefId) -> Option { + desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) } + } + query lookup_deprecation_entry(def_id: DefId) -> Option { desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index a300558c0c9ce..c281ef216c788 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -383,10 +383,10 @@ where let mut candidates = vec![]; - if let TypingMode::Coherence = self.typing_mode() { - if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { - return vec![candidate]; - } + if let TypingMode::Coherence = self.typing_mode() + && let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) + { + return vec![candidate]; } self.assemble_alias_bound_candidates(goal, &mut candidates); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 5b6f978527285..73bb1508de97a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -997,12 +997,12 @@ where } fn try_fold_ty(&mut self, ty: I::Ty) -> Result { - if let ty::Alias(ty::Projection, alias_ty) = ty.kind() { - if let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { - return Ok(term.expect_ty()); - } + if let ty::Alias(ty::Projection, alias_ty) = ty.kind() + && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? + { + Ok(term.expect_ty()) + } else { + ty.try_super_fold_with(self) } - - ty.try_super_fold_with(self) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 0547eb77f8d83..42264f58bcd19 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -42,20 +42,18 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(host_clause) = assumption.as_host_effect_clause() { - if host_clause.def_id() == goal.predicate.def_id() - && host_clause.constness().satisfies(goal.predicate.constness) - { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.trait_ref.args, - host_clause.skip_binder().trait_ref.args, - ) { - return Ok(()); - } - } + if let Some(host_clause) = assumption.as_host_effect_clause() + && host_clause.def_id() == goal.predicate.def_id() + && host_clause.constness().satisfies(goal.predicate.constness) + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + host_clause.skip_binder().trait_ref.args, + ) + { + Ok(()) + } else { + Err(NoSolution) } - - Err(NoSolution) } fn match_assumption( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index dd9ccadf6cf64..b42587618b57b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -429,22 +429,21 @@ where // If we have run this goal before, and it was stalled, check that any of the goal's // args have changed. Otherwise, we don't need to re-run the goal because it'll remain // stalled, since it'll canonicalize the same way and evaluation is pure. - if let Some(stalled_on) = stalled_on { - if !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) - && !self - .delegate - .opaque_types_storage_num_entries() - .needs_reevaluation(stalled_on.num_opaques) - { - return Ok(( - NestedNormalizationGoals::empty(), - GoalEvaluation { - certainty: Certainty::Maybe(stalled_on.stalled_cause), - has_changed: HasChanged::No, - stalled_on: Some(stalled_on), - }, - )); - } + if let Some(stalled_on) = stalled_on + && !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) + && !self + .delegate + .opaque_types_storage_num_entries() + .needs_reevaluation(stalled_on.num_opaques) + { + return Ok(( + NestedNormalizationGoals::empty(), + GoalEvaluation { + certainty: Certainty::Maybe(stalled_on.stalled_cause), + has_changed: HasChanged::No, + stalled_on: Some(stalled_on), + }, + )); } let (orig_values, canonical_goal) = self.canonicalize_goal(goal); @@ -833,14 +832,11 @@ where match t.kind() { ty::Infer(ty::TyVar(vid)) => { - if let ty::TermKind::Ty(term) = self.term.kind() { - if let ty::Infer(ty::TyVar(term_vid)) = term.kind() { - if self.delegate.root_ty_var(vid) - == self.delegate.root_ty_var(term_vid) - { - return ControlFlow::Break(()); - } - } + if let ty::TermKind::Ty(term) = self.term.kind() + && let ty::Infer(ty::TyVar(term_vid)) = term.kind() + && self.delegate.root_ty_var(vid) == self.delegate.root_ty_var(term_vid) + { + return ControlFlow::Break(()); } self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?; @@ -860,15 +856,12 @@ where fn visit_const(&mut self, c: I::Const) -> Self::Result { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - if let ty::TermKind::Const(term) = self.term.kind() { - if let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() - { - if self.delegate.root_const_var(vid) - == self.delegate.root_const_var(term_vid) - { - return ControlFlow::Break(()); - } - } + if let ty::TermKind::Const(term) = self.term.kind() + && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() + && self.delegate.root_const_var(vid) + == self.delegate.root_const_var(term_vid) + { + return ControlFlow::Break(()); } self.check_nameable(self.delegate.universe_of_ct(vid).unwrap()) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index d51c87fe68e60..edb354b4a8454 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -112,18 +112,17 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(projection_pred) = assumption.as_projection_clause() { - if projection_pred.item_def_id() == goal.predicate.def_id() { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.alias.args, - projection_pred.skip_binder().projection_term.args, - ) { - return Ok(()); - } - } + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.item_def_id() == goal.predicate.def_id() + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.alias.args, + projection_pred.skip_binder().projection_term.args, + ) + { + Ok(()) + } else { + Err(NoSolution) } - - Err(NoSolution) } fn match_assumption( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 8aaa8e9ca87ea..6c9fb63b579ad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -127,33 +127,32 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(trait_clause) = assumption.as_trait_clause() { - if trait_clause.polarity() != goal.predicate.polarity { - return Err(NoSolution); - } - - if trait_clause.def_id() == goal.predicate.def_id() { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.trait_ref.args, - trait_clause.skip_binder().trait_ref.args, - ) { - return Ok(()); - } - } - + fn trait_def_id_matches( + cx: I, + clause_def_id: I::DefId, + goal_def_id: I::DefId, + ) -> bool { + clause_def_id == goal_def_id // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so - // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds - // are syntactic sugar for a lack of bounds so don't need this. - if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized) - && ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized) - { - let meta_sized_clause = - trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id()); - return Self::fast_reject_assumption(ecx, goal, meta_sized_clause); - } + // check for a `MetaSized` supertrait being matched against a `Sized` assumption. + // + // `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this. + || (cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized) + && cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized)) } - Err(NoSolution) + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.polarity() == goal.predicate.polarity + && trait_def_id_matches(ecx.cx(), trait_clause.def_id(), goal.predicate.def_id()) + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + trait_clause.skip_binder().trait_ref.args, + ) + { + return Ok(()); + } else { + Err(NoSolution) + } } fn match_assumption( diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 177bad96595e0..7ffcf7b5d9654 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -320,10 +320,10 @@ pub fn supertrait_def_ids( let trait_def_id = stack.pop()?; for (predicate, _) in cx.explicit_super_predicates_of(trait_def_id).iter_identity() { - if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { - if set.insert(data.def_id()) { - stack.push(data.def_id()); - } + if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() + && set.insert(data.def_id()) + { + stack.push(data.def_id()); } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index e42639c68075a..79f6bc5dabb40 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -284,12 +284,12 @@ where } // If they have no bound vars, relate normally. - if let Some(a_inner) = a.no_bound_vars() { - if let Some(b_inner) = b.no_bound_vars() { - self.relate(a_inner, b_inner)?; - return Ok(a); - } - }; + if let Some(a_inner) = a.no_bound_vars() + && let Some(b_inner) = b.no_bound_vars() + { + self.relate(a_inner, b_inner)?; + return Ok(a); + } match self.ambient_variance { // Checks whether `for<..> sub <: for<..> sup` holds. diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index 1b99cc820f1ab..eb56c1af408bb 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -80,31 +80,29 @@ impl GlobalCache { mut candidate_is_applicable: impl FnMut(&NestedGoals) -> bool, ) -> Option> { let entry = self.map.get(&input)?; - if let Some(Success { required_depth, ref nested_goals, ref result }) = entry.success { - if available_depth.cache_entry_is_applicable(required_depth) - && candidate_is_applicable(nested_goals) - { - return Some(CacheData { - result: cx.get_tracked(&result), - required_depth, - encountered_overflow: false, - nested_goals, - }); - } + if let Some(Success { required_depth, ref nested_goals, ref result }) = entry.success + && available_depth.cache_entry_is_applicable(required_depth) + && candidate_is_applicable(nested_goals) + { + return Some(CacheData { + result: cx.get_tracked(&result), + required_depth, + encountered_overflow: false, + nested_goals, + }); } let additional_depth = available_depth.0; if let Some(WithOverflow { nested_goals, result }) = entry.with_overflow.get(&additional_depth) + && candidate_is_applicable(nested_goals) { - if candidate_is_applicable(nested_goals) { - return Some(CacheData { - result: cx.get_tracked(result), - required_depth: additional_depth, - encountered_overflow: true, - nested_goals, - }); - } + return Some(CacheData { + result: cx.get_tracked(result), + required_depth: additional_depth, + encountered_overflow: true, + nested_goals, + }); } None diff --git a/library/stdarch/crates/intrinsic-test/README.md b/library/stdarch/crates/intrinsic-test/README.md index 260d59fca80f7..bea95f91e9e1c 100644 --- a/library/stdarch/crates/intrinsic-test/README.md +++ b/library/stdarch/crates/intrinsic-test/README.md @@ -7,7 +7,7 @@ USAGE: intrinsic-test [FLAGS] [OPTIONS] FLAGS: - --a32 Run tests for A32 instrinsics instead of A64 + --a32 Run tests for A32 intrinsics instead of A64 --generate-only Regenerate test programs, but don't build or run them -h, --help Prints help information -V, --version Prints version information diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 09dc476d68eea..f7e62e1eccf67 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -499,7 +499,7 @@ This directive takes comma-separated issue numbers as arguments, or `"unknown"`: - `//@ known-bug: rust-lang/chalk#123456` (allows arbitrary text before the `#`, which is useful when the issue is on another repo) - `//@ known-bug: unknown` - (when there is no known issue yet; preferrably open one if it does not already exist) + (when there is no known issue yet; preferably open one if it does not already exist) Do not include [error annotations](#error-annotations) in a test with `known-bug`. The test should still include other normal directives and diff --git a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md index a6fb25a55be2b..10464e500ec2a 100644 --- a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md +++ b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md @@ -64,7 +64,7 @@ struct HaveAlias { In this example, the concrete type referred to by `Alias` is guaranteed to be the same wherever `Alias` occurs. -> Orginally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. +> Originally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. ### `type_alias_impl_trait` in argument position. diff --git a/src/tools/rust-installer/README.md b/src/tools/rust-installer/README.md index 99d8e5ca4cf1c..505ffe4093fcd 100644 --- a/src/tools/rust-installer/README.md +++ b/src/tools/rust-installer/README.md @@ -51,7 +51,7 @@ To combine installers. * Make install.sh not have to be customized, pull it's data from a config file. -* Be more resiliant to installation failures, particularly if the disk +* Be more resilient to installation failures, particularly if the disk is full. * Pre-install and post-uninstall scripts. * Allow components to depend on or contradict other components. diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 7e27e0258c2f5..4f9af6d53dd3b 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1368,7 +1368,6 @@ ui/infinite/issue-41731-infinite-macro-println.rs ui/intrinsics/issue-28575.rs ui/intrinsics/issue-84297-reifying-copy.rs ui/invalid/issue-114435-layout-type-err.rs -ui/issue-11881.rs ui/issue-15924.rs ui/issue-16822.rs ui/issues-71798.rs diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index 267da0602406e..90073ff308143 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -1,10 +1,10 @@ -//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 +//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code #![crate_type = "lib"] #![feature(fn_align)] // CHECK: align 16 -#[no_mangle] +#[unsafe(no_mangle)] #[align(16)] pub fn fn_align() {} @@ -12,12 +12,12 @@ pub struct A; impl A { // CHECK: align 16 - #[no_mangle] + #[unsafe(no_mangle)] #[align(16)] pub fn method_align(self) {} // CHECK: align 16 - #[no_mangle] + #[unsafe(no_mangle)] #[align(16)] pub fn associated_fn() {} } @@ -25,46 +25,94 @@ impl A { trait T: Sized { fn trait_fn() {} - // CHECK: align 32 - #[align(32)] fn trait_method(self) {} + + #[align(8)] + fn trait_method_inherit_low(self); + + #[align(32)] + fn trait_method_inherit_high(self); + + #[align(32)] + fn trait_method_inherit_default(self) {} + + #[align(4)] + #[align(128)] + #[align(8)] + fn inherit_highest(self) {} } impl T for A { - // CHECK: align 16 - #[no_mangle] + // CHECK-LABEL: trait_fn + // CHECK-SAME: align 16 + #[unsafe(no_mangle)] #[align(16)] fn trait_fn() {} - // CHECK: align 16 - #[no_mangle] + // CHECK-LABEL: trait_method + // CHECK-SAME: align 16 + #[unsafe(no_mangle)] #[align(16)] fn trait_method(self) {} -} -impl T for () {} + // The prototype's align is ignored because the align here is higher. + // CHECK-LABEL: trait_method_inherit_low + // CHECK-SAME: align 16 + #[unsafe(no_mangle)] + #[align(16)] + fn trait_method_inherit_low(self) {} + + // The prototype's align is used because it is higher. + // CHECK-LABEL: trait_method_inherit_high + // CHECK-SAME: align 32 + #[unsafe(no_mangle)] + #[align(16)] + fn trait_method_inherit_high(self) {} + + // The prototype's align inherited. + // CHECK-LABEL: trait_method_inherit_default + // CHECK-SAME: align 32 + #[unsafe(no_mangle)] + fn trait_method_inherit_default(self) {} + + // The prototype's highest align inherited. + // CHECK-LABEL: inherit_highest + // CHECK-SAME: align 128 + #[unsafe(no_mangle)] + #[align(32)] + #[align(64)] + fn inherit_highest(self) {} +} -pub fn foo() { - ().trait_method(); +trait HasDefaultImpl: Sized { + // CHECK-LABEL: inherit_from_default_method + // CHECK-LABEL: inherit_from_default_method + // CHECK-SAME: align 32 + #[align(32)] + fn inherit_from_default_method(self) {} } +pub struct InstantiateDefaultMethods; + +impl HasDefaultImpl for InstantiateDefaultMethods {} + // CHECK-LABEL: align_specified_twice_1 // CHECK-SAME: align 64 -#[no_mangle] +#[unsafe(no_mangle)] #[align(32)] #[align(64)] pub fn align_specified_twice_1() {} // CHECK-LABEL: align_specified_twice_2 // CHECK-SAME: align 128 -#[no_mangle] +#[unsafe(no_mangle)] #[align(128)] #[align(32)] pub fn align_specified_twice_2() {} // CHECK-LABEL: align_specified_twice_3 // CHECK-SAME: align 256 -#[no_mangle] +#[unsafe(no_mangle)] #[align(32)] #[align(256)] pub fn align_specified_twice_3() {} diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index c57ade58c30e4..0732e11f3e095 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -1,5 +1,6 @@ //@ compile-flags: -C opt-level=0 -C no-prepopulate-passes +#![feature(repr_simd)] #![crate_type = "lib"] // With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type, @@ -100,3 +101,23 @@ pub fn bool_to_fake_bool_unsigned(b: bool) -> FakeBoolUnsigned { pub fn fake_bool_unsigned_to_bool(b: FakeBoolUnsigned) -> bool { unsafe { std::mem::transmute(b) } } + +#[repr(simd)] +#[derive(Clone, Copy)] +struct S([i64; 1]); + +// CHECK-LABEL: define i64 @single_element_simd_to_scalar(<1 x i64> %b) +// CHECK: bitcast <1 x i64> %b to i64 +// CHECK: ret i64 +#[no_mangle] +pub extern "C" fn single_element_simd_to_scalar(b: S) -> i64 { + unsafe { std::mem::transmute(b) } +} + +// CHECK-LABEL: define <1 x i64> @scalar_to_single_element_simd(i64 %b) +// CHECK: bitcast i64 %b to <1 x i64> +// CHECK: ret <1 x i64> +#[no_mangle] +pub extern "C" fn scalar_to_single_element_simd(b: i64) -> S { + unsafe { std::mem::transmute(b) } +} diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs index 483def62fc79b..dbe0f692aefb0 100644 --- a/tests/run-make/short-ice/rmake.rs +++ b/tests/run-make/short-ice/rmake.rs @@ -5,9 +5,12 @@ // See https://github.com/rust-lang/rust/issues/107910 //@ needs-target-std -//@ ignore-i686-pc-windows-msvc -// Reason: the assert_eq! on line 37 fails, almost seems like it missing debug info? -// Haven't been able to reproduce locally, but it happens on CI. +//@ ignore-windows-msvc +// +// - FIXME(#143198): On `i686-pc-windows-msvc`: the assert_eq! on line 37 fails, almost seems like +// it missing debug info? Haven't been able to reproduce locally, but it happens on CI. +// - FIXME(#143198): On `x86_64-pc-windows-msvc`: full backtrace sometimes do not contain matching +// count of short backtrace markers (e.g. 5x end marker, but 3x start marker). use run_make_support::rustc; diff --git a/tests/ui/attributes/inner-attrs-impl-cfg.rs b/tests/ui/attributes/inner-attrs-impl-cfg.rs new file mode 100644 index 0000000000000..e7a5cfa9e2f53 --- /dev/null +++ b/tests/ui/attributes/inner-attrs-impl-cfg.rs @@ -0,0 +1,36 @@ +//! Test inner attributes (#![...]) behavior in impl blocks with cfg conditions. +//! +//! This test verifies that: +//! - Inner attributes can conditionally exclude entire impl blocks +//! - Regular attributes within impl blocks work independently +//! - Attribute parsing doesn't consume too eagerly + +//@ run-pass + +struct Foo; + +impl Foo { + #![cfg(false)] + + fn method(&self) -> bool { + false + } +} + +impl Foo { + #![cfg(not(FALSE))] + + // Check that we don't eat attributes too eagerly. + #[cfg(false)] + fn method(&self) -> bool { + false + } + + fn method(&self) -> bool { + true + } +} + +pub fn main() { + assert!(Foo.method()); +} diff --git a/tests/ui/integral-indexing.rs b/tests/ui/indexing/indexing-integral-types.rs similarity index 54% rename from tests/ui/integral-indexing.rs rename to tests/ui/indexing/indexing-integral-types.rs index e20553af8a26f..a91696a6fd513 100644 --- a/tests/ui/integral-indexing.rs +++ b/tests/ui/indexing/indexing-integral-types.rs @@ -1,16 +1,20 @@ +//! Test that only usize can be used for indexing arrays and slices. + pub fn main() { let v: Vec = vec![0, 1, 2, 3, 4, 5]; let s: String = "abcdef".to_string(); + + // Valid indexing with usize v[3_usize]; v[3]; - v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8` - v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8` + v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8` + v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8` v[3u32]; //~ ERROR the type `[isize]` cannot be indexed by `u32` v[3i32]; //~ ERROR the type `[isize]` cannot be indexed by `i32` s.as_bytes()[3_usize]; s.as_bytes()[3]; - s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8` - s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8` + s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8` + s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8` s.as_bytes()[3u32]; //~ ERROR the type `[u8]` cannot be indexed by `u32` s.as_bytes()[3i32]; //~ ERROR the type `[u8]` cannot be indexed by `i32` } diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/indexing/indexing-integral-types.stderr similarity index 91% rename from tests/ui/integral-indexing.stderr rename to tests/ui/indexing/indexing-integral-types.stderr index 26253e078cb40..b63991ec2c4af 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/indexing/indexing-integral-types.stderr @@ -1,5 +1,5 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:6:7 + --> $DIR/indexing-integral-types.rs:10:7 | LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -11,7 +11,7 @@ LL | v[3u8]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:7:7 + --> $DIR/indexing-integral-types.rs:11:7 | LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -23,7 +23,7 @@ LL | v[3i8]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:8:7 + --> $DIR/indexing-integral-types.rs:12:7 | LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -35,7 +35,7 @@ LL | v[3u32]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:9:7 + --> $DIR/indexing-integral-types.rs:13:7 | LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -47,7 +47,7 @@ LL | v[3i32]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:12:18 + --> $DIR/indexing-integral-types.rs:16:18 | LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -59,7 +59,7 @@ LL | s.as_bytes()[3u8]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:13:18 + --> $DIR/indexing-integral-types.rs:17:18 | LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -71,7 +71,7 @@ LL | s.as_bytes()[3i8]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:14:18 + --> $DIR/indexing-integral-types.rs:18:18 | LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -83,7 +83,7 @@ LL | s.as_bytes()[3u32]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:15:18 + --> $DIR/indexing-integral-types.rs:19:18 | LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` diff --git a/tests/ui/inner-attrs-on-impl.rs b/tests/ui/inner-attrs-on-impl.rs deleted file mode 100644 index 1dce1cdd261af..0000000000000 --- a/tests/ui/inner-attrs-on-impl.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass - -struct Foo; - -impl Foo { - #![cfg(false)] - - fn method(&self) -> bool { false } -} - -impl Foo { - #![cfg(not(FALSE))] - - // check that we don't eat attributes too eagerly. - #[cfg(false)] - fn method(&self) -> bool { false } - - fn method(&self) -> bool { true } -} - - -pub fn main() { - assert!(Foo.method()); -} diff --git a/tests/ui/inner-module.rs b/tests/ui/inner-module.rs deleted file mode 100644 index 111f2cab857f2..0000000000000 --- a/tests/ui/inner-module.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -mod inner { - pub mod inner2 { - pub fn hello() { println!("hello, modular world"); } - } - pub fn hello() { inner2::hello(); } -} - -pub fn main() { inner::hello(); inner::inner2::hello(); } diff --git a/tests/ui/inner-static-type-parameter.rs b/tests/ui/inner-static-type-parameter.rs deleted file mode 100644 index a1994e7529cb7..0000000000000 --- a/tests/ui/inner-static-type-parameter.rs +++ /dev/null @@ -1,11 +0,0 @@ -// see #9186 - -enum Bar { What } //~ ERROR parameter `T` is never used - -fn foo() { - static a: Bar = Bar::What; -//~^ ERROR can't use generic parameters from outer item -} - -fn main() { -} diff --git a/tests/ui/integral-variable-unification-error.rs b/tests/ui/mismatched_types/int-float-type-mismatch.rs similarity index 65% rename from tests/ui/integral-variable-unification-error.rs rename to tests/ui/mismatched_types/int-float-type-mismatch.rs index 8d1621321e8e6..b45d02730d986 100644 --- a/tests/ui/integral-variable-unification-error.rs +++ b/tests/ui/mismatched_types/int-float-type-mismatch.rs @@ -1,3 +1,6 @@ +//! Check that a type mismatch error is reported when trying +//! to unify a {float} value assignment to an {integer} variable. + fn main() { let mut x //~ NOTE expected due to the type of this binding = diff --git a/tests/ui/integral-variable-unification-error.stderr b/tests/ui/mismatched_types/int-float-type-mismatch.stderr similarity index 87% rename from tests/ui/integral-variable-unification-error.stderr rename to tests/ui/mismatched_types/int-float-type-mismatch.stderr index 1caa6042fd206..43b8609a49d7c 100644 --- a/tests/ui/integral-variable-unification-error.stderr +++ b/tests/ui/mismatched_types/int-float-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:5:9 + --> $DIR/int-float-type-mismatch.rs:8:9 | LL | let mut x | ----- expected due to the type of this binding diff --git a/tests/ui/modules/nested-modules-basic.rs b/tests/ui/modules/nested-modules-basic.rs new file mode 100644 index 0000000000000..12eccec280863 --- /dev/null +++ b/tests/ui/modules/nested-modules-basic.rs @@ -0,0 +1,19 @@ +//! Basic test for nested module functionality and path resolution + +//@ run-pass + +mod inner { + pub mod inner2 { + pub fn hello() { + println!("hello, modular world"); + } + } + pub fn hello() { + inner2::hello(); + } +} + +pub fn main() { + inner::hello(); + inner::inner2::hello(); +} diff --git a/tests/ui/statics/static-generic-param-soundness.rs b/tests/ui/statics/static-generic-param-soundness.rs new file mode 100644 index 0000000000000..aabcca514d317 --- /dev/null +++ b/tests/ui/statics/static-generic-param-soundness.rs @@ -0,0 +1,20 @@ +//! Originally, inner statics in generic functions were generated only once, causing the same +//! static to be shared across all generic instantiations. This created a soundness hole where +//! different types could be coerced through thread-local storage in safe code. +//! +//! This test checks that generic parameters from outer scopes cannot be used in inner statics, +//! preventing this soundness issue. +//! +//! See https://github.com/rust-lang/rust/issues/9186 + +enum Bar { + //~^ ERROR parameter `T` is never used + What, +} + +fn foo() { + static a: Bar = Bar::What; + //~^ ERROR can't use generic parameters from outer item +} + +fn main() {} diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/statics/static-generic-param-soundness.stderr similarity index 86% rename from tests/ui/inner-static-type-parameter.stderr rename to tests/ui/statics/static-generic-param-soundness.stderr index 88d33b44c5931..47554c7fcb0f0 100644 --- a/tests/ui/inner-static-type-parameter.stderr +++ b/tests/ui/statics/static-generic-param-soundness.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/inner-static-type-parameter.rs:6:19 + --> $DIR/static-generic-param-soundness.rs:16:19 | LL | fn foo() { | - type parameter from outer item @@ -9,9 +9,9 @@ LL | static a: Bar = Bar::What; = note: a `static` is a separate item from the item that contains it error[E0392]: type parameter `T` is never used - --> $DIR/inner-static-type-parameter.rs:3:10 + --> $DIR/static-generic-param-soundness.rs:10:10 | -LL | enum Bar { What } +LL | enum Bar { | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.rs b/tests/ui/traits/dispatch-from-dyn-invalid-impls.rs similarity index 52% rename from tests/ui/invalid_dispatch_from_dyn_impls.rs rename to tests/ui/traits/dispatch-from-dyn-invalid-impls.rs index b1d4b261babee..f5f66ca69cfc1 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.rs +++ b/tests/ui/traits/dispatch-from-dyn-invalid-impls.rs @@ -1,20 +1,30 @@ +//! Test various invalid implementations of DispatchFromDyn trait. +//! +//! DispatchFromDyn is a special trait used by the compiler for dyn-compatible dynamic dispatch. +//! This checks that the compiler correctly rejects invalid implementations: +//! - Structs with extra non-coercible fields +//! - Structs with multiple pointer fields +//! - Structs with no coercible fields +//! - Structs with repr(C) or other incompatible representations +//! - Structs with over-aligned fields + #![feature(unsize, dispatch_from_dyn)] -use std::{ - ops::DispatchFromDyn, - marker::{Unsize, PhantomData}, -}; +use std::marker::{PhantomData, Unsize}; +use std::ops::DispatchFromDyn; +// Extra field prevents DispatchFromDyn struct WrapperWithExtraField(T, i32); impl DispatchFromDyn> for WrapperWithExtraField //~^ ERROR [E0378] where - T: DispatchFromDyn, -{} - + T: DispatchFromDyn +{ +} -struct MultiplePointers{ +// Multiple pointer fields create ambiguous coercion +struct MultiplePointers { ptr1: *const T, ptr2: *const T, } @@ -22,10 +32,11 @@ struct MultiplePointers{ impl DispatchFromDyn> for MultiplePointers //~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced where - T: Unsize, -{} - + T: Unsize +{ +} +// No coercible fields (only PhantomData) struct NothingToCoerce { data: PhantomData, } @@ -33,23 +44,28 @@ struct NothingToCoerce { impl DispatchFromDyn> for NothingToCoerce {} //~^ ERROR implementing `DispatchFromDyn` requires a field to be coerced +// repr(C) is incompatible with DispatchFromDyn #[repr(C)] struct HasReprC(Box); impl DispatchFromDyn> for HasReprC //~^ ERROR [E0378] where - T: Unsize, -{} + T: Unsize +{ +} +// Over-aligned fields are incompatible #[repr(align(64))] struct OverAlignedZst; + struct OverAligned(Box, OverAlignedZst); impl DispatchFromDyn> for OverAligned //~^ ERROR [E0378] - where - T: Unsize, -{} +where + T: Unsize +{ +} fn main() {} diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.stderr b/tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr similarity index 77% rename from tests/ui/invalid_dispatch_from_dyn_impls.stderr rename to tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr index 93ec6bbe0896f..676da0ce81fb1 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr @@ -1,25 +1,25 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else - --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:19:1 | LL | / impl DispatchFromDyn> for WrapperWithExtraField LL | | LL | | where -LL | | T: DispatchFromDyn, - | |__________________________^ +LL | | T: DispatchFromDyn + | |_________________________^ | = note: extra field `1` of type `i32` is not allowed error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:22:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:32:1 | LL | / impl DispatchFromDyn> for MultiplePointers LL | | LL | | where -LL | | T: Unsize, - | |_________________^ +LL | | T: Unsize + | |________________^ | note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:18:5 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:28:5 | LL | ptr1: *const T, | ^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | ptr2: *const T, | ^^^^^^^^^^^^^^ error[E0374]: implementing `DispatchFromDyn` requires a field to be coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:33:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:44:1 | LL | impl DispatchFromDyn> for NothingToCoerce {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,22 +35,22 @@ LL | impl DispatchFromDyn> for NothingT = note: expected a single field to be coerced, none found error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` - --> $DIR/invalid_dispatch_from_dyn_impls.rs:39:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:51:1 | LL | / impl DispatchFromDyn> for HasReprC LL | | LL | | where -LL | | T: Unsize, - | |_________________^ +LL | | T: Unsize + | |________________^ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else - --> $DIR/invalid_dispatch_from_dyn_impls.rs:49:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:64:1 | LL | / impl DispatchFromDyn> for OverAligned LL | | -LL | | where -LL | | T: Unsize, - | |_____________________^ +LL | | where +LL | | T: Unsize + | |________________^ | = note: extra field `1` of type `OverAlignedZst` is not allowed diff --git a/tests/ui/issue-11881.rs b/tests/ui/traits/encoder-trait-bounds-regression.rs similarity index 76% rename from tests/ui/issue-11881.rs rename to tests/ui/traits/encoder-trait-bounds-regression.rs index 1abe079720337..292b921cdf761 100644 --- a/tests/ui/issue-11881.rs +++ b/tests/ui/traits/encoder-trait-bounds-regression.rs @@ -1,14 +1,23 @@ +//! Regression test for issue #11881 +//! +//! Originally, the compiler would ICE when trying to parameterize on certain encoder types +//! due to issues with higher-ranked trait bounds and lifetime inference. This test checks +//! that various encoder patterns work correctly: +//! - Generic encoders with associated error types +//! - Higher-ranked trait bounds (for<'r> Encodable>) +//! - Multiple encoder implementations for the same type +//! - Polymorphic encoding functions + //@ run-pass #![allow(unused_must_use)] #![allow(dead_code)] #![allow(unused_imports)] -use std::fmt; -use std::io::prelude::*; use std::io::Cursor; -use std::slice; +use std::io::prelude::*; use std::marker::PhantomData; +use std::{fmt, slice}; trait Encoder { type Error; @@ -45,7 +54,6 @@ impl Encoder for OpaqueEncoder { type Error = (); } - struct Foo { baz: bool, } @@ -69,7 +77,6 @@ impl Encodable for Bar { enum WireProtocol { JSON, Opaque, - // ... } fn encode_json Encodable>>(val: &T, wr: &mut Cursor>) {