From 47293c1234e615045b5bd6fbbf867ff6b757fd1f Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Wed, 7 Aug 2024 15:48:16 +0200 Subject: Check ABI target compatibility for function pointers This check was previously only performed on functions not function pointers. Co-authored-by: Folkert --- compiler/rustc_hir_analysis/src/check/check.rs | 24 +++++++++++++--------- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 19 +++++++++++++---- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 7 +++++++ 4 files changed, 37 insertions(+), 15 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d725772a5b3..4c53414226b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,9 @@ use rustc_hir::Node; use rustc_hir::def::{CtorKind, DefKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; -use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; +use rustc_lint_defs::builtin::{ + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, +}; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -52,16 +54,18 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { }); } } +} - // This ABI is only allowed on function pointers - if abi == Abi::CCmseNonSecureCall { - struct_span_code_err!( - tcx.dcx(), - span, - E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" - ) - .emit(); +pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { + match tcx.sess.target.is_abi_supported(abi) { + Some(true) => (), + Some(false) | None => { + tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { + lint.primary_message( + "use of calling convention not supported on this target on function pointer", + ); + }); + } } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d3d88919d87..004540b2643 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -73,7 +73,7 @@ pub mod wfcheck; use std::num::NonZero; -pub use check::check_abi; +pub use check::{check_abi, check_abi_fn_ptr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 5150db7f51b..a562759da11 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,6 +1,5 @@ -use rustc_errors::DiagCtxtHandle; -use rustc_hir as hir; -use rustc_hir::HirId; +use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; +use rustc_hir::{self as hir, HirId}; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; use rustc_span::Span; @@ -26,7 +25,19 @@ pub(crate) fn validate_cmse_abi<'tcx>( .. }) = hir_node else { - // might happen when this ABI is used incorrectly. That will be handled elsewhere + let span = match tcx.parent_hir_node(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ForeignMod { .. }, span, .. + }) => *span, + _ => tcx.hir().span(hir_id), + }; + struct_span_code_err!( + tcx.dcx(), + span, + E0781, + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + ) + .emit(); return; }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e95b5142559..b6562c97247 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,6 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, debug_span, instrument}; use crate::bounds::Bounds; +use crate::check::check_abi_fn_ptr; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -2324,6 +2325,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); + if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) = + tcx.hir_node(hir_id) + { + check_abi_fn_ptr(tcx, hir_id, *span, bare_fn_ty.abi); + } + // reject function types that violate cmse ABI requirements cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); -- cgit 1.4.1-3-g733a5 From e3a0da18633a8cfb5263bb975747352690b01fcf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 22:10:16 -0400 Subject: Remove unnamed field feature --- compiler/rustc_ast_passes/messages.ftl | 8 - compiler/rustc_ast_passes/src/ast_validation.rs | 26 - compiler/rustc_ast_passes/src/errors.rs | 18 - compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_feature/src/removed.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir_analysis/messages.ftl | 15 - compiler/rustc_hir_analysis/src/check/check.rs | 56 - compiler/rustc_hir_analysis/src/collect.rs | 104 +- compiler/rustc_hir_analysis/src/errors.rs | 42 - compiler/rustc_hir_typeck/src/expr.rs | 63 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 10 +- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_hir_typeck/src/writeback.rs | 5 - compiler/rustc_metadata/src/rmeta/decoder.rs | 3 - compiler/rustc_middle/src/ty/adt.rs | 9 +- compiler/rustc_middle/src/ty/context.rs | 10 +- compiler/rustc_middle/src/ty/mod.rs | 22 +- compiler/rustc_middle/src/ty/typeck_results.rs | 19 - compiler/rustc_mir_build/src/thir/cx/expr.rs | 20 +- compiler/rustc_parse/src/parser/item.rs | 4 +- .../feature-gates/feature-gate-unnamed_fields.rs | 29 - .../feature-gate-unnamed_fields.stderr | 63 - .../anon-struct-in-enum-issue-121446.rs | 11 - .../anon-struct-in-enum-issue-121446.stderr | 16 - tests/ui/union/unnamed-fields/auxiliary/dep.rs | 18 - .../union/unnamed-fields/field_uniqueness_check.rs | 337 ---- .../unnamed-fields/field_uniqueness_check.stderr | 1734 -------------------- tests/ui/union/unnamed-fields/repr_check.rs | 69 - tests/ui/union/unnamed-fields/repr_check.stderr | 152 -- .../unnamed-fields/restrict_anonymous_structs.rs | 32 - .../restrict_anonymous_structs.stderr | 48 - .../unnamed-fields/restrict_anonymous_unions.rs | 32 - .../restrict_anonymous_unions.stderr | 48 - tests/ui/union/unnamed-fields/restrict_type_hir.rs | 44 - .../union/unnamed-fields/restrict_type_hir.stderr | 62 - .../unnamed-enum-field-issue-121757.rs | 25 - .../unnamed-enum-field-issue-121757.stderr | 45 - tests/ui/unpretty/expanded-exhaustive.rs | 14 - tests/ui/unpretty/expanded-exhaustive.stdout | 18 - 40 files changed, 30 insertions(+), 3209 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.rs delete mode 100644 tests/ui/feature-gates/feature-gate-unnamed_fields.stderr delete mode 100644 tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs delete mode 100644 tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr delete mode 100644 tests/ui/union/unnamed-fields/auxiliary/dep.rs delete mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.rs delete mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.stderr delete mode 100644 tests/ui/union/unnamed-fields/repr_check.rs delete mode 100644 tests/ui/union/unnamed-fields/repr_check.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr delete mode 100644 tests/ui/union/unnamed-fields/restrict_type_hir.rs delete mode 100644 tests/ui/union/unnamed-fields/restrict_type_hir.stderr delete mode 100644 tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs delete mode 100644 tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index c361c35b723..0146a8d9082 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -160,14 +160,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} .type = inherent impl for this type .only_trait = only trait implementations may be annotated with {$annotation} -ast_passes_invalid_unnamed_field = - unnamed fields are not allowed outside of structs or unions - .label = unnamed field declared here - -ast_passes_invalid_unnamed_field_ty = - unnamed fields can only have struct or union types - .label = not a struct or union - ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier .suggestion = remove safe from this item diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 229d04f8de2..b3d91d881c4 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -255,7 +255,6 @@ impl<'a> AstValidator<'a> { if let Some(ident) = field.ident && ident.name == kw::Underscore { - self.check_unnamed_field_ty(&field.ty, ident.span); self.visit_vis(&field.vis); self.visit_ident(ident); self.visit_ty_common(&field.ty); @@ -294,21 +293,6 @@ impl<'a> AstValidator<'a> { } } - fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) { - if matches!( - &ty.kind, - // We already checked for `kw::Underscore` before calling this function, - // so skip the check - TyKind::AnonStruct(..) | TyKind::AnonUnion(..) - // If the anonymous field contains a Path as type, we can't determine - // if the path is a valid struct or union, so skip the check - | TyKind::Path(..) - ) { - return; - } - self.dcx().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span }); - } - fn deny_anon_struct_or_union(&self, ty: &Ty) { let struct_or_union = match &ty.kind { TyKind::AnonStruct(..) => "struct", @@ -318,15 +302,6 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); } - fn deny_unnamed_field(&self, field: &FieldDef) { - if let Some(ident) = field.ident - && ident.name == kw::Underscore - { - self.dcx() - .emit_err(errors::InvalidUnnamedField { span: field.span, ident_span: ident.span }); - } - } - fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) { let Const::Yes(span) = constness else { return; @@ -895,7 +870,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_field_def(&mut self, field: &'a FieldDef) { - self.deny_unnamed_field(field); visit::walk_field_def(self, field) } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5cce47ce7bd..07515897c69 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -814,24 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_passes_invalid_unnamed_field_ty)] -pub(crate) struct InvalidUnnamedFieldTy { - #[primary_span] - pub span: Span, - #[label] - pub ty_span: Span, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_invalid_unnamed_field)] -pub(crate) struct InvalidUnnamedField { - #[primary_span] - pub span: Span, - #[label] - pub ident_span: Span, -} - #[derive(Diagnostic)] #[diag(ast_passes_anon_struct_or_union_not_allowed)] pub(crate) struct AnonStructOrUnionNotAllowed { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 83931a8c1a9..e47f5d43128 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -541,7 +541,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); - gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e3..276814dd0d9 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -216,6 +216,8 @@ declare_features! ( (removed, test_removed_feature, "1.0.0", None, None), /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), + /// Allows unnamed fields of struct and union type + (removed, unnamed_fields, "1.74.0", Some(49804)), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e96..843610a18a1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -618,8 +618,6 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), - /// Allows unnamed fields of struct and union type - (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "1.82.0", Some(95174)), diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c73826c489f..b64a400f75e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -248,8 +248,6 @@ hir_analysis_invalid_union_field = hir_analysis_invalid_union_field_sugg = wrap the field type in `ManuallyDrop<...>` -hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types - hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl .label = const parameter declared here @@ -535,19 +533,6 @@ hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_na hir_analysis_unconstrained_opaque_type = unconstrained opaque type .note = `{$name}` must be used in combination with a concrete type within the same {$what} -hir_analysis_unnamed_fields_repr_field_defined = unnamed field defined here - -hir_analysis_unnamed_fields_repr_field_missing_repr_c = - named type of unnamed field must have `#[repr(C)]` representation - .label = unnamed field defined here - .field_ty_label = `{$field_ty}` defined here - .suggestion = add `#[repr(C)]` to this {$field_adt_kind} - -hir_analysis_unnamed_fields_repr_missing_repr_c = - {$adt_kind} with unnamed fields must have `#[repr(C)]` representation - .label = {$adt_kind} `{$adt_name}` defined here - .suggestion = add `#[repr(C)]` to this {$adt_kind} - hir_analysis_unrecognized_atomic_operation = unrecognized atomic operation function: `{$op}` .label = unrecognized atomic operation diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d725772a5b3..b9111a5cd39 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -76,7 +76,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); - check_unnamed_fields(tcx, def); } fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { @@ -86,61 +85,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); - check_unnamed_fields(tcx, def); -} - -/// Check the representation of adts with unnamed fields. -fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { - if def.is_enum() { - return; - } - let variant = def.non_enum_variant(); - if !variant.has_unnamed_fields() { - return; - } - if !def.is_anonymous() { - let adt_kind = def.descr(); - let span = tcx.def_span(def.did()); - let unnamed_fields = variant - .fields - .iter() - .filter(|f| f.is_unnamed()) - .map(|f| { - let span = tcx.def_span(f.did); - errors::UnnamedFieldsReprFieldDefined { span } - }) - .collect::>(); - debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt"); - let adt_name = tcx.item_name(def.did()); - if !def.repr().c() { - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC { - span, - adt_kind, - adt_name, - unnamed_fields, - sugg_span: span.shrink_to_lo(), - }); - } - } - for field in variant.fields.iter().filter(|f| f.is_unnamed()) { - let field_ty = tcx.type_of(field.did).instantiate_identity(); - if let Some(adt) = field_ty.ty_adt_def() - && !adt.is_enum() - { - if !adt.is_anonymous() && !adt.repr().c() { - let field_ty_span = tcx.def_span(adt.did()); - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { - span: tcx.def_span(field.did), - field_ty_span, - field_ty, - field_adt_kind: adt.descr(), - sugg_span: field_ty_span.shrink_to_lo(), - }); - } - } else { - tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) }); - } - } } /// Check that the fields of the `union` do not need dropping. diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 93b021be245..cfa148d925d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1007,79 +1007,6 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { } } } - - /// Check the uniqueness of fields across adt where there are - /// nested fields imported from an unnamed field. - fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) { - for field in adt_def.all_fields() { - if field.is_unnamed() { - // Here we don't care about the generic parameters, so `instantiate_identity` is enough. - match self.tcx.type_of(field.did).instantiate_identity().kind() { - ty::Adt(adt_def, _) => { - self.check_field_in_nested_adt(*adt_def, unnamed_field_span); - } - ty_kind => span_bug!( - self.tcx.def_span(field.did), - "Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}" - ), - } - } else { - self.check_field_decl( - field.ident(self.tcx), - NestedSpan { - span: unnamed_field_span, - nested_field_span: self.tcx.def_span(field.did), - } - .into(), - ); - } - } - } - - /// Check the uniqueness of fields in a struct variant, and recursively - /// check the nested fields if it is an unnamed field with type of an - /// anonymous adt. - fn check_field(&mut self, field: &hir::FieldDef<'_>) { - if field.ident.name != kw::Underscore { - self.check_field_decl(field.ident, field.span.into()); - return; - } - match &field.ty.kind { - hir::TyKind::AnonAdt(item_id) => { - match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind { - hir::ItemKind::Struct(variant_data, ..) - | hir::ItemKind::Union(variant_data, ..) => { - variant_data.fields().iter().for_each(|f| self.check_field(f)); - } - item_kind => span_bug!( - field.ty.span, - "Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}" - ), - } - } - hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { - // If this is a direct path to an ADT, we can check it - // If this is a type alias or non-ADT, `check_unnamed_fields` should verify it - if let Some(def_id) = res.opt_def_id() - && let Some(local) = def_id.as_local() - && let Node::Item(item) = self.tcx.hir_node_by_def_id(local) - && item.is_adt() - { - self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span); - } - } - // Abort due to errors (there must be an error if an unnamed field - // has any type kind other than an anonymous adt or a named adt) - ty_kind => { - self.tcx.dcx().span_delayed_bug( - field.ty.span, - format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"), - ); - // FIXME: errors during AST validation should abort the compilation before reaching here. - self.tcx.dcx().abort_if_errors(); - } - } - } } fn lower_variant( @@ -1090,20 +1017,13 @@ fn lower_variant( def: &hir::VariantData<'_>, adt_kind: ty::AdtKind, parent_did: LocalDefId, - is_anonymous: bool, ) -> ty::VariantDef { - let mut has_unnamed_fields = false; let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx); let fields = def .fields() .iter() - .inspect(|f| { - has_unnamed_fields |= f.ident.name == kw::Underscore; - // We only check named ADT here because anonymous ADTs are checked inside - // the named ADT in which they are defined. - if !is_anonymous { - field_uniqueness_check_ctx.check_field(f); - } + .inspect(|field| { + field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into()); }) .map(|f| ty::FieldDef { did: f.def_id.to_def_id(), @@ -1127,7 +1047,6 @@ fn lower_variant( adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) || variant_did .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), - has_unnamed_fields, ) } @@ -1138,20 +1057,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { bug!("expected ADT to be an item"); }; - let is_anonymous = item.ident.name == kw::Empty; - let repr = if is_anonymous { - let parent = tcx.local_parent(def_id); - if let Node::Item(item) = tcx.hir_node_by_def_id(parent) - && item.is_struct_or_union() - { - tcx.adt_def(parent).repr() - } else { - tcx.dcx().span_delayed_bug(item.span, "anonymous field inside non struct/union"); - ty::ReprOptions::default() - } - } else { - tcx.repr_options_of_def(def_id) - }; + let repr = tcx.repr_options_of_def(def_id); let (kind, variants) = match &item.kind { ItemKind::Enum(def, _) => { let mut distance_from_explicit = 0; @@ -1175,7 +1081,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { &v.data, AdtKind::Enum, def_id, - is_anonymous, ) }) .collect(); @@ -1195,7 +1100,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { def, adt_kind, def_id, - is_anonymous, )) .collect(); @@ -1203,7 +1107,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { } _ => bug!("{:?} is not an ADT", item.owner_id.def_id), }; - tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous) + tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) } fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4edb68e6199..9099703e812 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -734,13 +734,6 @@ pub(crate) struct InvalidUnionField { pub note: (), } -#[derive(Diagnostic)] -#[diag(hir_analysis_invalid_unnamed_field_ty)] -pub(crate) struct InvalidUnnamedFieldTy { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_return_type_notation_on_non_rpitit)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { @@ -1598,41 +1591,6 @@ pub(crate) struct UnconstrainedGenericParameter { pub const_param_note2: bool, } -#[derive(Diagnostic)] -pub(crate) enum UnnamedFieldsRepr<'a> { - #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] - MissingReprC { - #[primary_span] - #[label] - span: Span, - adt_kind: &'static str, - adt_name: Symbol, - #[subdiagnostic] - unnamed_fields: Vec, - #[suggestion(code = "#[repr(C)]\n")] - sugg_span: Span, - }, - #[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)] - FieldMissingReprC { - #[primary_span] - #[label] - span: Span, - #[label(hir_analysis_field_ty_label)] - field_ty_span: Span, - field_ty: Ty<'a>, - field_adt_kind: &'static str, - #[suggestion(code = "#[repr(C)]\n")] - sugg_span: Span, - }, -} - -#[derive(Subdiagnostic)] -#[note(hir_analysis_unnamed_fields_repr_field_defined)] -pub(crate) struct UnnamedFieldsReprFieldDefined { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] pub(crate) struct OpaqueCapturesHigherRankedLifetime { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b34ed4640db..ed7be72551b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -33,7 +33,6 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; -use smallvec::SmallVec; use tracing::{debug, instrument, trace}; use {rustc_ast as ast, rustc_hir as hir}; @@ -1722,8 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); - // FIXME: handle nested fields - self.write_field_index(field.hir_id, i, Vec::new()); + self.write_field_index(field.hir_id, i); // We don't look at stability attributes on // struct-like enums (yet...), but it's definitely not @@ -2367,35 +2365,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, base_def: ty::AdtDef<'tcx>, ident: Ident, - nested_fields: &mut SmallVec<[(FieldIdx, &'tcx ty::FieldDef); 1]>, - ) -> bool { + ) -> Option<(FieldIdx, &'tcx ty::FieldDef)> { // No way to find a field in an enum. if base_def.is_enum() { - return false; + return None; } for (field_idx, field) in base_def.non_enum_variant().fields.iter_enumerated() { - if field.is_unnamed() { - // We have an unnamed field, recurse into the nested ADT to find `ident`. - // If we find it there, return immediately, and `nested_fields` will contain the - // correct path. - nested_fields.push((field_idx, field)); - - let field_ty = self.tcx.type_of(field.did).instantiate_identity(); - let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); - if self.find_adt_field(adt_def, ident, &mut *nested_fields) { - return true; - } - - nested_fields.pop(); - } else if field.ident(self.tcx).normalize_to_macros_2_0() == ident { + if field.ident(self.tcx).normalize_to_macros_2_0() == ident { // We found the field we wanted. - nested_fields.push((field_idx, field)); - return true; + return Some((field_idx, field)); } } - false + None } // Check field access expressions @@ -2425,34 +2408,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let mut field_path = SmallVec::new(); - if self.find_adt_field(*base_def, ident, &mut field_path) { - let (first_idx, _) = field_path[0]; - let (_, last_field) = field_path.last().unwrap(); - - // Save the index of all fields regardless of their visibility in case - // of error recovery. - let nested_fields = field_path[..] - .array_windows() - .map(|[(_, outer), (inner_idx, _)]| { - let outer_ty = self.field_ty(expr.span, outer, args); - (outer_ty, *inner_idx) - }) - .collect(); - self.write_field_index(expr.hir_id, first_idx, nested_fields); + if let Some((idx, field)) = self.find_adt_field(*base_def, ident) { + self.write_field_index(expr.hir_id, idx); let adjustments = self.adjust_steps(&autoderef); - if last_field.vis.is_accessible_from(def_scope, self.tcx) { + if field.vis.is_accessible_from(def_scope, self.tcx) { self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.tcx.check_stability( - last_field.did, - Some(expr.hir_id), - expr.span, - None, - ); - return self.field_ty(expr.span, last_field, args); + self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); + return self.field_ty(expr.span, field, args); } // The field is not accessible, fall through to error reporting. @@ -2467,11 +2432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.write_field_index( - expr.hir_id, - FieldIdx::from_usize(index), - Vec::new(), - ); + self.write_field_index(expr.hir_id, FieldIdx::from_usize(index)); return field_ty; } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 62107877283..cd4c5de2a66 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -165,16 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn write_field_index( - &self, - hir_id: HirId, - index: FieldIdx, - nested_fields: Vec<(Ty<'tcx>, FieldIdx)>, - ) { + pub(crate) fn write_field_index(&self, hir_id: HirId, index: FieldIdx) { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); - if !nested_fields.is_empty() { - self.typeck_results.borrow_mut().nested_fields_mut().insert(hir_id, nested_fields); - } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 49c5a7d8a65..fb78da0a86c 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1513,8 +1513,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_map .get(&ident) .map(|(i, f)| { - // FIXME: handle nested fields - self.write_field_index(field.hir_id, *i, Vec::new()); + self.write_field_index(field.hir_id, *i); self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); self.field_ty(span, f, args) }) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3254dddaee9..b193b81f6de 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -588,11 +588,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { { self.typeck_results.field_indices_mut().insert(hir_id, index); } - if let Some(nested_fields) = - self.fcx.typeck_results.borrow_mut().nested_fields_mut().remove(hir_id) - { - self.typeck_results.nested_fields_mut().insert(hir_id, nested_fields); - } } #[instrument(skip(self, span), level = "debug")] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2157324d5cc..600a9b75097 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1107,8 +1107,6 @@ impl<'a> CrateMetadataRef<'a> { parent_did, None, data.is_non_exhaustive, - // FIXME: unnamed fields in crate metadata is unimplemented yet. - false, ), ) } @@ -1151,7 +1149,6 @@ impl<'a> CrateMetadataRef<'a> { adt_kind, variants.into_iter().map(|(_, variant)| variant).collect(), repr, - false, ) } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 8f89f5c25af..3322a2643d7 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -259,12 +259,8 @@ impl AdtDefData { kind: AdtKind, variants: IndexVec, repr: ReprOptions, - is_anonymous: bool, ) -> Self { - debug!( - "AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})", - did, kind, variants, repr, is_anonymous - ); + debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { @@ -297,9 +293,6 @@ impl AdtDefData { if tcx.is_lang_item(did, LangItem::UnsafeCell) { flags |= AdtFlags::IS_UNSAFE_CELL; } - if is_anonymous { - flags |= AdtFlags::IS_ANONYMOUS; - } AdtDefData { did, variants, flags, repr } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2ffb273cb6f..4eaba540e33 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1419,16 +1419,8 @@ impl<'tcx> TyCtxt<'tcx> { kind: AdtKind, variants: IndexVec, repr: ReprOptions, - is_anonymous: bool, ) -> ty::AdtDef<'tcx> { - self.mk_adt_def_from_data(ty::AdtDefData::new( - self, - did, - kind, - variants, - repr, - is_anonymous, - )) + self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr)) } /// Allocates a read-only byte or string literal for `mir::interpret`. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b1212a5eb5..33bb5fa5739 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1155,8 +1155,6 @@ bitflags::bitflags! { const NO_VARIANT_FLAGS = 0; /// Indicates whether the field list of this variant is `#[non_exhaustive]`. const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; - /// Indicates whether this variant has unnamed fields. - const HAS_UNNAMED_FIELDS = 1 << 1; } } rustc_data_structures::external_bitflags_debug! { VariantFlags } @@ -1209,12 +1207,11 @@ impl VariantDef { parent_did: DefId, recover_tainted: Option, is_field_list_non_exhaustive: bool, - has_unnamed_fields: bool, ) -> Self { debug!( "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, - fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})", - name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields, + fields = {:?}, adt_kind = {:?}, parent_did = {:?})", + name, variant_did, ctor, discr, fields, adt_kind, parent_did, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1222,10 +1219,6 @@ impl VariantDef { flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } - if has_unnamed_fields { - flags |= VariantFlags::HAS_UNNAMED_FIELDS; - } - VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, @@ -1243,12 +1236,6 @@ impl VariantDef { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } - /// Does this variant contains unnamed fields - #[inline] - pub fn has_unnamed_fields(&self) -> bool { - self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS) - } - /// Computes the `Ident` of this variant by looking up the `Span` pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) @@ -1434,11 +1421,6 @@ impl<'tcx> FieldDef { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) } - - /// Returns whether the field is unnamed - pub fn is_unnamed(&self) -> bool { - self.name == rustc_span::symbol::kw::Underscore - } } #[derive(Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 17280c3d047..c01d2120111 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -42,12 +42,6 @@ pub struct TypeckResults<'tcx> { /// belongs, but it may not exist if it's a tuple field (`tuple.0`). field_indices: ItemLocalMap, - /// Resolved types and indices for the nested fields' accesses of `obj.field` (expanded - /// to `obj._(1)._(2).field` in THIR). This map only stores the intermediate type - /// of `obj._(1)` and index of `_(1)._(2)`, and the type of `_(1)._(2)`, and the index of - /// `_(2).field`. - nested_fields: ItemLocalMap, FieldIdx)>>, - /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated outside inference. See /// typeck::check::fn_ctxt for details. @@ -225,7 +219,6 @@ impl<'tcx> TypeckResults<'tcx> { hir_owner, type_dependent_defs: Default::default(), field_indices: Default::default(), - nested_fields: Default::default(), user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), @@ -299,18 +292,6 @@ impl<'tcx> TypeckResults<'tcx> { self.field_indices().get(id).cloned() } - pub fn nested_fields(&self) -> LocalTableInContext<'_, Vec<(Ty<'tcx>, FieldIdx)>> { - LocalTableInContext { hir_owner: self.hir_owner, data: &self.nested_fields } - } - - pub fn nested_fields_mut(&mut self) -> LocalTableInContextMut<'_, Vec<(Ty<'tcx>, FieldIdx)>> { - LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.nested_fields } - } - - pub fn nested_field_tys_and_indices(&self, id: HirId) -> &[(Ty<'tcx>, FieldIdx)] { - self.nested_fields().get(id).map_or(&[], Vec::as_slice) - } - pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2ffad0b4834..044d8045a27 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -807,21 +807,11 @@ impl<'tcx> Cx<'tcx> { }); ExprKind::Loop { body } } - hir::ExprKind::Field(source, ..) => { - let mut kind = ExprKind::Field { - lhs: self.mirror_expr(source), - variant_index: FIRST_VARIANT, - name: self.typeck_results.field_index(expr.hir_id), - }; - let nested_field_tys_and_indices = - self.typeck_results.nested_field_tys_and_indices(expr.hir_id); - for &(ty, idx) in nested_field_tys_and_indices { - let expr = Expr { temp_lifetime, ty, span: source.span, kind }; - let lhs = self.thir.exprs.push(expr); - kind = ExprKind::Field { lhs, variant_index: FIRST_VARIANT, name: idx }; - } - kind - } + hir::ExprKind::Field(source, ..) => ExprKind::Field { + lhs: self.mirror_expr(source), + variant_index: FIRST_VARIANT, + name: self.typeck_results.field_index(expr.hir_id), + }, hir::ExprKind::Cast(source, cast_ty) => { // Check for a user-given type annotation on this `cast` let user_provided_types = self.typeck_results.user_provided_types(); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9fc82d84225..13681c00f8e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2009,9 +2009,7 @@ impl<'a> Parser<'a> { /// for better diagnostics and suggestions. fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err(true)?; - if ident.name == kw::Underscore { - self.psess.gated_spans.gate(sym::unnamed_fields, lo); - } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { + if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() { let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false, Case::Sensitive) { let inherited_vis = diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs deleted file mode 100644 index 302a9bbeb45..00000000000 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs +++ /dev/null @@ -1,29 +0,0 @@ -#[repr(C)] -struct Foo { - foo: u8, - _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - bar: u8, - baz: u16 - } -} - -#[repr(C)] -union Bar { - foobar: u8, - _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] - //~^ ERROR unnamed fields are not yet fully implemented [E0658] - foobaz: u8, - barbaz: u16 - } -} - -#[repr(C)] -struct S; - -#[repr(C)] -struct Baz { - _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] -} - -fn main(){} diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr deleted file mode 100644 index bc9e95bab98..00000000000 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:4:5 - | -LL | _: union { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:4:8 - | -LL | _: union { - | ________^ -LL | | -LL | | bar: u8, -LL | | baz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:14:5 - | -LL | _: struct { - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:14:8 - | -LL | _: struct { - | ________^ -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:26:5 - | -LL | _: S - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs deleted file mode 100644 index 00f9bfd5cdf..00000000000 --- a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![crate_type = "lib"] -#![feature(unnamed_fields)] -#![allow(unused, incomplete_features)] - -enum K { - M { - _ : struct { field: u8 }, - //~^ error: unnamed fields are not allowed outside of structs or unions - //~| error: anonymous structs are not allowed outside of unnamed struct or union fields - } -} diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr deleted file mode 100644 index 43843141e2e..00000000000 --- a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/anon-struct-in-enum-issue-121446.rs:7:9 - | -LL | _ : struct { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/anon-struct-in-enum-issue-121446.rs:7:13 - | -LL | _ : struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: aborting due to 2 previous errors - diff --git a/tests/ui/union/unnamed-fields/auxiliary/dep.rs b/tests/ui/union/unnamed-fields/auxiliary/dep.rs deleted file mode 100644 index a11f3e18f52..00000000000 --- a/tests/ui/union/unnamed-fields/auxiliary/dep.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[repr(C)] -pub struct GoodStruct(()); - -pub struct BadStruct(()); - -pub enum BadEnum { - A, - B, -} - -#[repr(C)] -pub enum BadEnum2 { - A, - B, -} - -pub type GoodAlias = GoodStruct; -pub type BadAlias = i32; diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs deleted file mode 100644 index ddb951aa06c..00000000000 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs +++ /dev/null @@ -1,337 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -#[derive(Clone, Copy)] -#[repr(C)] -struct Foo { - a: u8, -} - -#[derive(Clone, Copy)] -#[repr(C)] -struct Bar { - _: union { - a: u8, - }, -} - - -// duplicated with a normal field -#[derive(Clone, Copy)] -#[repr(C)] -union A { - // referent field - a: u8, - - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field -#[derive(Clone, Copy)] -#[repr(C)] -struct B { - _: union { - // referent field - a: u8, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a more nested field -#[derive(Clone, Copy)] -#[repr(C)] -union C { - _: struct { - _: union { - // referent field - a: u8, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field (within the direct outer anonymous adt) - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field (within the direct outer anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field (within the direct outer anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt (within the direct outer anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the direct outer anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - // normal field - a: u8, //~ ERROR field `a` is already declared [E0124] - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared [E0124] - }, - }, - // nested field in a named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt -#[derive(Clone, Copy)] -#[repr(C)] -struct D { - // referent field `a` - _: Foo, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a nested field of a named adt -#[derive(Clone, Copy)] -#[repr(C)] -union D2 { - // referent field `a` - _: Bar, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt in an anonymous adt -#[derive(Clone, Copy)] -#[repr(C)] -struct E { - _: struct { - // referent field `a` - _: Foo, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -// duplicated with a nested field in a named adt in an anonymous adt -#[repr(C)] -#[derive(Clone, Copy)] -union E2 { - _: struct { - // referent field `a` - _: Bar, - - // normal field (within the same anonymous adt) - a: u8, //~ ERROR field `a` is already declared - // nested field (within the same anonymous adt) - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field (within the same anonymous adt) - _: union { - _: struct { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in a named adt (within the same anonymous adt) - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt (within the same anonymous adt) - _: struct { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, - }, - - // normal field - a: u8, //~ ERROR field `a` is already declared - // nested field - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - // more nested field - _: struct { - _: union { - a: u8, //~ ERROR field `a` is already declared - }, - }, - // nested field in another named adt - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - // nested field in a named adt in an anoymous adt - _: union { - _: Foo, //~ ERROR field `a` is already declared - _: Bar, //~ ERROR field `a` is already declared - }, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr deleted file mode 100644 index 11978386843..00000000000 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr +++ /dev/null @@ -1,1734 +0,0 @@ -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:27:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:30:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:31:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:36:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:40:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:40:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:41:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:41:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:44:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:44:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:45:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:45:9 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:58:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:61:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:66:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:70:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:70:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:71:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:71:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:74:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:74:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:75:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:75:13 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:80:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:83:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:88:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:92:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:92:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:93:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:93:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:96:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:96:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:97:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:97:9 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:111:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:114:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:119:21 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:123:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:123:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:124:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:124:13 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:127:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:127:17 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:128:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:128:17 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:133:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:136:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:141:17 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:145:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:145:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:146:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:146:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:149:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:149:13 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:150:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:150:13 - | -LL | _: Bar, - | ^^^^^^ - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:154:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:157:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:162:13 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | a: u8, - | ^^^^^ field already declared - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:166:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:166:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:167:5 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:167:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:170:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:170:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:171:9 - | -LL | a: u8, - | ----- `a` first declared here -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:171:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:183:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:186:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:191:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:195:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:195:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:196:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:196:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:199:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:199:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:200:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:200:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:180:5 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:212:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:215:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:220:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:224:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:224:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:225:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:225:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:228:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:228:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:229:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:229:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:209:5 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:242:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:245:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:250:17 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:254:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:254:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:255:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:255:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:258:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:258:13 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:259:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:259:13 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:264:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:267:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:272:13 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:276:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:276:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:277:5 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:277:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:280:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:280:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:281:9 - | -LL | _: Foo, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:281:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:239:9 - | -LL | _: Foo, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:294:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:297:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:302:17 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:306:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:306:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:307:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:307:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:310:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:310:13 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:311:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:311:13 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:316:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:319:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:324:13 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | a: u8, - | ^^^^^ field already declared - | -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:328:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:328:5 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:329:5 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:329:5 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:332:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Foo, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:7:5 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:332:9 - | -LL | _: Foo, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:333:9 - | -LL | _: Bar, - | ------ `a` first declared here in this unnamed field -... -LL | _: Bar, - | ^^^^^^ field `a` declared in this unnamed field - | -note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:333:9 - | -LL | _: Bar, - | ^^^^^^ -note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:14:9 - | -LL | a: u8, - | ^^^^^ -help: fields from the type of this unnamed field are considered fields of the outer type - --> $DIR/field_uniqueness_check.rs:291:9 - | -LL | _: Bar, - | ^^^^^^ - -error: aborting due to 85 previous errors - -For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/union/unnamed-fields/repr_check.rs b/tests/ui/union/unnamed-fields/repr_check.rs deleted file mode 100644 index b50b54b20af..00000000000 --- a/tests/ui/union/unnamed-fields/repr_check.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct A { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE struct `A` defined here - _: struct { //~ NOTE unnamed field defined here - a: i32, - }, - _: struct { //~ NOTE unnamed field defined here - _: struct { - b: i32, - }, - }, -} - -union B { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE union `B` defined here - _: union { //~ NOTE unnamed field defined here - a: i32, - }, - _: union { //~ NOTE unnamed field defined here - _: union { - b: i32, - }, - }, -} - -#[derive(Clone, Copy)] -#[repr(C)] -struct Foo {} - -#[derive(Clone, Copy)] -struct Bar {} -//~^ `Bar` defined here -//~| `Bar` defined here -//~| `Bar` defined here -//~| `Bar` defined here - -struct C { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE struct `C` defined here - _: Foo, //~ NOTE unnamed field defined here -} - -union D { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation - //~^ NOTE union `D` defined here - _: Foo, //~ NOTE unnamed field defined here -} - -#[repr(C)] -struct E { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - _: struct { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - }, -} - -#[repr(C)] -union F { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - _: union { - _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - //~^ NOTE unnamed field defined here - }, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/repr_check.stderr b/tests/ui/union/unnamed-fields/repr_check.stderr deleted file mode 100644 index 324968b1264..00000000000 --- a/tests/ui/union/unnamed-fields/repr_check.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:4:1 - | -LL | struct A { - | ^^^^^^^^ struct `A` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:6:5 - | -LL | / _: struct { -LL | | a: i32, -LL | | }, - | |_____^ -note: unnamed field defined here - --> $DIR/repr_check.rs:9:5 - | -LL | / _: struct { -LL | | _: struct { -LL | | b: i32, -LL | | }, -LL | | }, - | |_____^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct A { - | - -error: union with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:16:1 - | -LL | union B { - | ^^^^^^^ union `B` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:18:5 - | -LL | / _: union { -LL | | a: i32, -LL | | }, - | |_____^ -note: unnamed field defined here - --> $DIR/repr_check.rs:21:5 - | -LL | / _: union { -LL | | _: union { -LL | | b: i32, -LL | | }, -LL | | }, - | |_____^ -help: add `#[repr(C)]` to this union - | -LL + #[repr(C)] -LL | union B { - | - -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:39:1 - | -LL | struct C { - | ^^^^^^^^ struct `C` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:41:5 - | -LL | _: Foo, - | ^^^^^^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct C { - | - -error: union with unnamed fields must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:44:1 - | -LL | union D { - | ^^^^^^^ union `D` defined here - | -note: unnamed field defined here - --> $DIR/repr_check.rs:46:5 - | -LL | _: Foo, - | ^^^^^^ -help: add `#[repr(C)]` to this union - | -LL + #[repr(C)] -LL | union D { - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:51:5 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:54:9 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:61:5 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/repr_check.rs:64:9 - | -LL | struct Bar {} - | ---------- `Bar` defined here -... -LL | _: Bar, - | ^^^^^^ unnamed field defined here - | -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct Bar {} - | - -error: aborting due to 8 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs deleted file mode 100644 index 03545ed7b18..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct F { - field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field3: u8 }, -} - -struct G { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -union H { - field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field3: u8 }, -} - -union I { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -enum K { - M { - _ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR unnamed fields are not allowed outside of structs or unions - }, - N { - _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions - } -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr deleted file mode 100644 index 3b3890af771..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:5:13 - | -LL | field1: struct { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:10:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:14:13 - | -LL | field1: struct { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:19:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:24:9 - | -LL | _ : struct { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:24:13 - | -LL | _ : struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:28:9 - | -LL | _ : u8, - | -^^^^^ - | | - | unnamed field declared here - -error: aborting due to 7 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs deleted file mode 100644 index 9ffe71b28c2..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -struct F { - field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field3: u8 }, -} - -struct G { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -union H { - field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field3: u8 }, -} - -union I { - _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types -} - -enum K { - M { - _ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR unnamed fields are not allowed outside of structs or unions - }, - N { - _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions - } -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr deleted file mode 100644 index f8679aad2d7..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:5:13 - | -LL | field1: union { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:10:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:14:13 - | -LL | field1: union { field2: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:19:5 - | -LL | _: (u8, u8), - | ^ -------- not a struct or union - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:24:9 - | -LL | _ : union { field: u8 }, - | -^^^^^^^^^^^^^^^^^^^^^^ - | | - | unnamed field declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:24:13 - | -LL | _ : union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:28:9 - | -LL | _ : u8, - | -^^^^^ - | | - | unnamed field declared here - -error: aborting due to 7 previous errors - diff --git a/tests/ui/union/unnamed-fields/restrict_type_hir.rs b/tests/ui/union/unnamed-fields/restrict_type_hir.rs deleted file mode 100644 index 80e4608be82..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_type_hir.rs +++ /dev/null @@ -1,44 +0,0 @@ -//@ aux-build:dep.rs - -// test for #121151 - -#![allow(incomplete_features)] -#![feature(unnamed_fields)] - -extern crate dep; - -#[repr(C)] -struct A { - a: u8, -} - -enum BadEnum { - A, - B, -} - -#[repr(C)] -enum BadEnum2 { - A, - B, -} - -type MyStruct = A; -type MyI32 = i32; - -#[repr(C)] -struct L { - _: i32, //~ ERROR unnamed fields can only have struct or union types - _: MyI32, //~ ERROR unnamed fields can only have struct or union types - _: BadEnum, //~ ERROR unnamed fields can only have struct or union types - _: BadEnum2, //~ ERROR unnamed fields can only have struct or union types - _: MyStruct, - _: dep::BadStruct, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation - _: dep::BadEnum, //~ ERROR unnamed fields can only have struct or union types - _: dep::BadEnum2, //~ ERROR unnamed fields can only have struct or union types - _: dep::BadAlias, //~ ERROR unnamed fields can only have struct or union types - _: dep::GoodAlias, - _: dep::GoodStruct, -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_type_hir.stderr b/tests/ui/union/unnamed-fields/restrict_type_hir.stderr deleted file mode 100644 index 3e80d7fbf5c..00000000000 --- a/tests/ui/union/unnamed-fields/restrict_type_hir.stderr +++ /dev/null @@ -1,62 +0,0 @@ -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:31:5 - | -LL | _: i32, - | ^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:32:5 - | -LL | _: MyI32, - | ^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:33:5 - | -LL | _: BadEnum, - | ^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:34:5 - | -LL | _: BadEnum2, - | ^^^^^^^^^^^ - -error: named type of unnamed field must have `#[repr(C)]` representation - --> $DIR/restrict_type_hir.rs:36:5 - | -LL | _: dep::BadStruct, - | ^^^^^^^^^^^^^^^^^ unnamed field defined here - | - ::: $DIR/auxiliary/dep.rs:4:1 - | -LL | pub struct BadStruct(()); - | -------------------- `BadStruct` defined here - | -help: add `#[repr(C)]` to this struct - --> $DIR/auxiliary/dep.rs:4:1 - | -LL + #[repr(C)] -LL | pub struct BadStruct(()); - | - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:37:5 - | -LL | _: dep::BadEnum, - | ^^^^^^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:38:5 - | -LL | _: dep::BadEnum2, - | ^^^^^^^^^^^^^^^^ - -error: unnamed fields can only have struct or union types - --> $DIR/restrict_type_hir.rs:39:5 - | -LL | _: dep::BadAlias, - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors - diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs deleted file mode 100644 index 5d15ec4cffd..00000000000 --- a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs +++ /dev/null @@ -1,25 +0,0 @@ -type NodeId = u32; -struct Type<'a>(std::marker::PhantomData::<&'a ()>); - -type Ast<'ast> = &'ast AstStructure<'ast>; - -struct AstStructure<'ast> { -//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation - id: NodeId, - _: AstKind<'ast> -//~^ ERROR unnamed fields are not yet fully implemented [E0658] -//~^^ ERROR unnamed fields can only have struct or union types -} - -enum AstKind<'ast> { - ExprInt, - ExprLambda(Ast<'ast>), -} - -fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx> -{ - match ast.kind {} -//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609] -} - -fn main() {} diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr deleted file mode 100644 index 4ea910202de..00000000000 --- a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^ - | - = note: see issue #49804 for more information - = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: struct with unnamed fields must have `#[repr(C)]` representation - --> $DIR/unnamed-enum-field-issue-121757.rs:6:1 - | -LL | struct AstStructure<'ast> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here - | -note: unnamed field defined here - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^^^^^^^^^^^^^^^^ -help: add `#[repr(C)]` to this struct - | -LL + #[repr(C)] -LL | struct AstStructure<'ast> { - | - -error: unnamed fields can only have struct or union types - --> $DIR/unnamed-enum-field-issue-121757.rs:9:5 - | -LL | _: AstKind<'ast> - | ^^^^^^^^^^^^^^^^ - -error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>` - --> $DIR/unnamed-enum-field-issue-121757.rs:21:15 - | -LL | match ast.kind {} - | ^^^^ unknown field - | - = note: available fields are: `id`, `_` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0609, E0658. -For more information about an error, try `rustc --explain E0609`. diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 279d723a26c..b287e48e476 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -786,20 +786,6 @@ mod types { let _: (T, T); } - /// TyKind::AnonStruct - fn ty_anon_struct() { - struct Struct { - _: struct { t: T }, - } - } - - /// TyKind::AnonUnion - fn ty_anon_union() { - struct Struct { - _: union { t: T }, - } - } - /// TyKind::Path fn ty_path() { let _: T; diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 149659693ae..f8d09650d92 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -361,8 +361,6 @@ mod expressions { - - @@ -636,22 +634,6 @@ mod types { fn ty_never() { let _: !; } /// TyKind::Tup fn ty_tup() { let _: (); let _: (T,); let _: (T, T); } - /// TyKind::AnonStruct - fn ty_anon_struct() { - struct Struct { - _: struct { - t: T, - }, - } - } - /// TyKind::AnonUnion - fn ty_anon_union() { - struct Struct { - _: union { - t: T, - }, - } - } /// TyKind::Path fn ty_path() { let _: T; -- cgit 1.4.1-3-g733a5 From a0e687f0348af5d269c8ba0ac9bbb52308850c6a Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sun, 6 Oct 2024 15:57:23 +0300 Subject: Remove unnecessary sorts in `rustc_hir_analysis`. This is an attempt to gain the performance loss after the PR #131140. Here the related objects are `IndexSet` so do not require a sort to stay stable. --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 5 +---- compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3a9d2640eee..3079fd71b0c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -531,7 +531,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { debug!(?required_bounds); let param_env = tcx.param_env(gat_def_id); - let mut unsatisfied_bounds: Vec<_> = required_bounds + let unsatisfied_bounds: Vec<_> = required_bounds .into_iter() .filter(|clause| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { @@ -552,9 +552,6 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { .map(|clause| clause.to_string()) .collect(); - // We sort so that order is predictable - unsatisfied_bounds.sort(); - if !unsatisfied_bounds.is_empty() { let plural = pluralize!(unsatisfied_bounds.len()); let suggestion = format!( diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index d1c888a185e..5127e73d978 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -319,9 +319,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // List of connected regions is built. Now, run the overlap check // for each pair of impl blocks in the same connected region. for region in connected_regions.into_iter().flatten() { - let mut impl_blocks = - region.impl_blocks.into_iter().collect::>(); - impl_blocks.sort_unstable(); + let impl_blocks = region.impl_blocks.into_iter().collect::>(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); -- cgit 1.4.1-3-g733a5 From 2e7a52b22fe222316a48093547f6312252c20f0f Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Wed, 9 Oct 2024 18:37:30 +0200 Subject: Rename feature object_safe_for_dispatch to dyn_compatible_for_dispatch --- compiler/rustc_feature/src/removed.rs | 4 ++ compiler/rustc_feature/src/unstable.rs | 15 ++-- compiler/rustc_hir_analysis/src/coherence/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/dyn_compatibility.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- tests/crashes/120241-2.rs | 2 +- tests/crashes/120241.rs | 2 +- tests/crashes/120482.rs | 2 +- tests/crashes/125512.rs | 2 +- tests/crashes/128176.rs | 2 +- tests/crashes/130521.rs | 2 +- .../coherence-unsafe-trait-object-impl.rs | 2 +- .../feature-gate-dyn_compatible_for_dispatch.rs | 41 +++++++++++ ...feature-gate-dyn_compatible_for_dispatch.stderr | 83 ++++++++++++++++++++++ .../feature-gate-object_safe_for_dispatch.rs | 41 ----------- .../feature-gate-object_safe_for_dispatch.stderr | 83 ---------------------- ...d-copy-bound.dyn_compatible_for_dispatch.stderr | 40 +++++++++++ ...ited-copy-bound.object_safe_for_dispatch.stderr | 40 ----------- tests/ui/kindck/kindck-inherited-copy-bound.rs | 8 +-- ...iated-consts.dyn_compatible_for_dispatch.stderr | 19 +++++ ...sociated-consts.object_safe_for_dispatch.stderr | 19 ----- .../object-safety-associated-consts.rs | 4 +- ...ety-generics.dyn_compatible_for_dispatch.stderr | 35 +++++++++ ...safety-generics.object_safe_for_dispatch.stderr | 35 --------- tests/ui/object-safety/object-safety-generics.rs | 8 +-- ...entions-Self.dyn_compatible_for_dispatch.stderr | 35 +++++++++ ...y-mentions-Self.object_safe_for_dispatch.stderr | 35 --------- .../object-safety/object-safety-mentions-Self.rs | 4 +- ...ty-no-static.dyn_compatible_for_dispatch.stderr | 27 +++++++ ...afety-no-static.object_safe_for_dispatch.stderr | 27 ------- tests/ui/object-safety/object-safety-no-static.rs | 4 +- ...fety-sized-2.dyn_compatible_for_dispatch.stderr | 18 +++++ ...-safety-sized-2.object_safe_for_dispatch.stderr | 18 ----- tests/ui/object-safety/object-safety-sized-2.rs | 4 +- ...safety-sized.dyn_compatible_for_dispatch.stderr | 18 +++++ ...ct-safety-sized.object_safe_for_dispatch.stderr | 18 ----- tests/ui/object-safety/object-safety-sized.rs | 4 +- .../downcast-unsafe-trait-objects.rs | 23 ++++++ .../manual-self-impl-for-unsafe-obj.current.stderr | 15 ++++ .../manual-self-impl-for-unsafe-obj.next.stderr | 15 ++++ .../manual-self-impl-for-unsafe-obj.rs | 69 ++++++++++++++++++ .../static-dispatch-unsafe-object.rs | 37 ++++++++++ .../downcast-unsafe-trait-objects.rs | 23 ------ .../manual-self-impl-for-unsafe-obj.current.stderr | 15 ---- .../manual-self-impl-for-unsafe-obj.next.stderr | 15 ---- .../manual-self-impl-for-unsafe-obj.rs | 69 ------------------ .../static-dispatch-unsafe-object.rs | 37 ---------- ...-object-safe.dyn_compatible_for_dispatch.stderr | 22 ++++++ ...not-object-safe.object_safe_for_dispatch.stderr | 22 ------ .../self/arbitrary-self-types-not-object-safe.rs | 6 +- tests/ui/suggestions/issue-104328.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj.rs | 2 +- tests/ui/wf/wf-unsafe-trait-obj-match.rs | 2 +- 56 files changed, 548 insertions(+), 542 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr create mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs create mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e3..c275ad31b87 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -154,6 +154,10 @@ declare_features! ( /// then removed. But there was no utility storing it separately, so now /// it's in this list. (removed, no_stack_check, "1.0.0", None, None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). + /// Renamed to `dyn_compatible_for_dispatch`. + (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e96..110ffa75b05 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -259,6 +259,14 @@ declare_features! ( (unstable, doc_notable_trait, "1.52.0", Some(45040)), /// Allows using the `may_dangle` attribute (RFC 1327). (unstable, dropck_eyepatch, "1.10.0", Some(34761)), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + /// + /// Renamed from `object_safe_for_dispatch`. + /// + /// [^1]: Formerly known as "object safe". + (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -544,13 +552,6 @@ declare_features! ( (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)), /// Allows `for` binders in where-clauses (incomplete, non_lifetime_binders, "1.69.0", Some(108185)), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - /// - /// [^1]: Formerly known as "object safe". - // FIXME(dyn_compat_renaming): Rename feature. - (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 69d36426447..eea5a16ac6f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -199,7 +199,7 @@ fn check_object_overlap<'tcx>( for component_def_id in component_def_ids { if !tcx.is_dyn_compatible(component_def_id) { // FIXME(dyn_compat_renaming): Rename test and update comment. - // Without the 'object_safe_for_dispatch' feature this is an error + // Without the 'dyn_compatible_for_dispatch' feature this is an error // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. // With the feature enabled, the trait is not implemented automatically, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8aa129c6cd..9e2df848309 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -776,6 +776,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, dylib, + dyn_compatible_for_dispatch, dyn_metadata, dyn_star, dyn_trait, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 191eda4d347..45e7de942fb 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -639,8 +639,8 @@ fn object_ty_for_trait<'tcx>( /// contained by the trait object, because the object that needs to be coerced is behind /// a pointer. /// -/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch +/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in +/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -674,7 +674,7 @@ fn receiver_is_dispatchable<'tcx>( // the type `U` in the query // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can + // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 084b61115db..20adda6f0de 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -881,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { + if !self.infcx.tcx.features().dyn_compatible_for_dispatch { principal.with_self_ty(self.tcx(), self_ty) } else if self.tcx().is_dyn_compatible(principal.def_id()) { principal.with_self_ty(self.tcx(), self_ty) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7e140ecfee0..a849cdfe125 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let defer_to_coercion = tcx.features().object_safe_for_dispatch; + let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch; if !defer_to_coercion { if let Some(principal) = data.principal_def_id() { diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs index 9c4a3a50293..91ec3362090 100644 --- a/tests/crashes/120241-2.rs +++ b/tests/crashes/120241-2.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] #![feature(unsized_fn_params)] fn guard(_s: Copy) -> bool { diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs index f18347a006c..b4fcb903714 100644 --- a/tests/crashes/120241.rs +++ b/tests/crashes/120241.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs index 6cbc2009c5f..a395855d796 100644 --- a/tests/crashes/120482.rs +++ b/tests/crashes/120482.rs @@ -1,6 +1,6 @@ //@ known-bug: #120482 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn bar(&self, x: &Self); diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs index 1672b24a114..37dbdf2f32f 100644 --- a/tests/crashes/125512.rs +++ b/tests/crashes/125512.rs @@ -1,6 +1,6 @@ //@ known-bug: rust-lang/rust#125512 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; } diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs index 70fada4f0fe..970ad9ff2cd 100644 --- a/tests/crashes/128176.rs +++ b/tests/crashes/128176.rs @@ -1,7 +1,7 @@ //@ known-bug: rust-lang/rust#128176 #![feature(generic_const_exprs)] -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait X { type Y; } diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs index 2d30b658024..7c078ab5790 100644 --- a/tests/crashes/130521.rs +++ b/tests/crashes/130521.rs @@ -1,6 +1,6 @@ //@ known-bug: #130521 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] struct Vtable(dyn Cap); trait Cap<'a> {} diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs index 9859a226efd..16baf0958a6 100644 --- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -1,7 +1,7 @@ // Check that unsafe trait object do not implement themselves // automatically -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized { fn call(&self); diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs new file mode 100644 index 00000000000..2dbba370a51 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the dyn-incompatible trait objects +// are gated by the `dyn_compatible_for_dispatch` feature gate. + +trait DynIncompatible1: Sized {} + +trait DynIncompatible2 { + fn static_fn() {} +} + +trait DynIncompatible3 { + fn foo(&self); +} + +trait DynIncompatible4 { + fn foo(&self, s: &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn DynIncompatible1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..3cb73dfd52c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -0,0 +1,83 @@ +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 + | +LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 + | +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `DynIncompatible2` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 + | +LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 + | +LL | trait DynIncompatible2 { + | ---------------- this trait cannot be made into an object... +LL | fn static_fn() {} + | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter +help: consider turning `static_fn` into a method by giving it a `&self` argument + | +LL | fn static_fn(&self) {} + | +++++ +help: alternatively, consider constraining `static_fn` so it does not apply to trait objects + | +LL | fn static_fn() where Self: Sized {} + | +++++++++++++++++ + +error[E0038]: the trait `DynIncompatible3` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 + | +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 + | +LL | trait DynIncompatible3 { + | ---------------- this trait cannot be made into an object... +LL | fn foo(&self); + | ^^^ ...because method `foo` has generic type parameters + = help: consider moving `foo` to another trait + +error[E0038]: the trait `DynIncompatible4` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 + | +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 + | +LL | trait DynIncompatible4 { + | ---------------- this trait cannot be made into an object... +LL | fn foo(&self, s: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait + +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:38:16 + | +LL | impl Trait for dyn DynIncompatible1 {} + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 + | +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs deleted file mode 100644 index 37348e476d4..00000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the use of the non object-safe trait objects -// are gated by `object_safe_for_dispatch` feature gate. - -trait NonObjectSafe1: Sized {} - -trait NonObjectSafe2 { - fn static_fn() {} -} - -trait NonObjectSafe3 { - fn foo(&self); -} - -trait NonObjectSafe4 { - fn foo(&self, s: &Self); -} - -fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - //~^ ERROR E0038 - loop {} -} - -fn takes_non_object_safe_box(obj: Box) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_rc() -> std::rc::Rc { - //~^ ERROR E0038 - loop {} -} - -trait Trait {} - -impl Trait for dyn NonObjectSafe1 {} -//~^ ERROR E0038 - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr deleted file mode 100644 index fd5ed9c40f7..00000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ /dev/null @@ -1,83 +0,0 @@ -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 - | -LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 - | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - -error[E0038]: the trait `NonObjectSafe2` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:45 - | -LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe2` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:7:8 - | -LL | trait NonObjectSafe2 { - | -------------- this trait cannot be made into an object... -LL | fn static_fn() {} - | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter -help: consider turning `static_fn` into a method by giving it a `&self` argument - | -LL | fn static_fn(&self) {} - | +++++ -help: alternatively, consider constraining `static_fn` so it does not apply to trait objects - | -LL | fn static_fn() where Self: Sized {} - | +++++++++++++++++ - -error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 - | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 - | -LL | trait NonObjectSafe3 { - | -------------- this trait cannot be made into an object... -LL | fn foo(&self); - | ^^^ ...because method `foo` has generic type parameters - = help: consider moving `foo` to another trait - -error[E0038]: the trait `NonObjectSafe4` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:47 - | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 - | -LL | trait NonObjectSafe4 { - | -------------- this trait cannot be made into an object... -LL | fn foo(&self, s: &Self); - | ^^^^^ ...because method `foo` references the `Self` type in this parameter - = help: consider moving `foo` to another trait - -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 - | -LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 - | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..b4424f4750e --- /dev/null +++ b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied + --> $DIR/kindck-inherited-copy-bound.rs:21:16 + | +LL | take_param(&x); + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` + | | + | required by a bound introduced by this call + | +note: required for `Box<{integer}>` to implement `Foo` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl Foo for T { + | ---- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `take_param` + --> $DIR/kindck-inherited-copy-bound.rs:17:17 + | +LL | fn take_param(foo: &T) { } + | ^^^ required by this bound in `take_param` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:13 + | +LL | let z = &x as &dyn Foo; + | ^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/kindck-inherited-copy-bound.rs:10:13 + | +LL | trait Foo : Copy { + | --- ^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for the cast from `&Box` to `&dyn Foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr deleted file mode 100644 index b4424f4750e..00000000000 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:21:16 - | -LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` - | | - | required by a bound introduced by this call - | -note: required for `Box<{integer}>` to implement `Foo` - --> $DIR/kindck-inherited-copy-bound.rs:14:14 - | -LL | impl Foo for T { - | ---- ^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required by a bound in `take_param` - --> $DIR/kindck-inherited-copy-bound.rs:17:17 - | -LL | fn take_param(foo: &T) { } - | ^^^ required by this bound in `take_param` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 - | -LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/kindck-inherited-copy-bound.rs:10:13 - | -LL | trait Foo : Copy { - | --- ^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - = note: required for the cast from `&Box` to `&dyn Foo` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0277. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs index c785736f42e..dda95229ddf 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.rs +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,8 +1,8 @@ // Test that Copy bounds inherited by trait are checked. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::any::Any; @@ -19,7 +19,7 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = Box::new(3); take_param(&x); //[curr]~ ERROR E0277 - //[object_safe_for_dispatch]~^ ERROR E0277 + //[dyn_compatible_for_dispatch]~^ ERROR E0277 } fn b() { @@ -28,7 +28,7 @@ fn b() { let z = &x as &dyn Foo; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn main() { } diff --git a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..5b98cc35505 --- /dev/null +++ b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr deleted file mode 100644 index 5b98cc35505..00000000000 --- a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | const X: usize; - | ^ ...because it contains this associated `const` - = help: consider moving `X` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs index a090214bbb4..fc7b372b782 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.rs +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { const X: usize; diff --git a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..4686b994b33 --- /dev/null +++ b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:20:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:27:5 + | +LL | t as &dyn Bar + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr deleted file mode 100644 index 4686b994b33..00000000000 --- a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 - | -LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs index f005a689ac4..b51555aa500 100644 --- a/tests/ui/object-safety/object-safety-generics.rs +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { @@ -18,14 +18,14 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t as &dyn Bar - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 //[curr]~| ERROR E0038 } diff --git a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..d0efb9c587e --- /dev/null +++ b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:24:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:30:5 + | +LL | t + | ^ `Baz` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = note: required for the cast from `&T` to `&dyn Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr deleted file mode 100644 index d0efb9c587e..00000000000 --- a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, x: &Self); - | ^^^^^ ...because method `bar` references the `Self` type in this parameter - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 - | -LL | t - | ^ `Baz` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 - | -LL | trait Baz { - | --- this trait cannot be made into an object... -LL | fn baz(&self) -> Self; - | ^^^^ ...because method `baz` references the `Self` type in its return type - = help: consider moving `baz` to another trait - = note: required for the cast from `&T` to `&dyn Baz` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs index 1311faf97bc..84c229e252d 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.rs +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -2,9 +2,9 @@ // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { diff --git a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..52f6865b6f3 --- /dev/null +++ b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:22:27 + | +LL | let b: Box = Box::new(Bar); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter + = help: only type `Bar` implements the trait, consider using it directly instead + = note: required for the cast from `Box` to `Box` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr deleted file mode 100644 index 52f6865b6f3..00000000000 --- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 - | -LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | fn foo() {} - | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead - = note: required for the cast from `Box` to `Box` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) {} - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized {} - | +++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/object-safety/object-safety-no-static.rs index 4f4e03d734e..54af16fe18e 100644 --- a/tests/ui/object-safety/object-safety-no-static.rs +++ b/tests/ui/object-safety/object-safety-no-static.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Foo { fn foo() {} diff --git a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..99066c104b7 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:16:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr deleted file mode 100644 index 99066c104b7..00000000000 --- a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 - | -LL | trait Bar - | --- this trait cannot be made into an object... -LL | where Self : Sized - | ^^^^^ ...because it requires `Self: Sized` - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs index cfb5d588d70..f5edd287f24 100644 --- a/tests/ui/object-safety/object-safety-sized-2.rs +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar where Self : Sized diff --git a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..5ce713375a4 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized.rs:8:12 + | +LL | trait Bar: Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr deleted file mode 100644 index 5ce713375a4..00000000000 --- a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 - | -LL | trait Bar: Sized { - | --- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs index f4d6c945b33..4c4fe3f8f25 100644 --- a/tests/ui/object-safety/object-safety-sized.rs +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar: Sized { fn bar(&self, t: T); diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs new file mode 100644 index 00000000000..e9206789756 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -0,0 +1,23 @@ +// Check that we if we get ahold of an object unsafe trait +// object with auto traits and lifetimes, we can downcast it +// +//@ check-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Trait: Sized {} + +fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { + t +} + +fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) + -> &'b (dyn Trait + 't) +where + 'a: 'b, + 't: 'a + 'b, +{ + t +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr new file mode 100644 index 00000000000..1489791b20d --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr new file mode 100644 index 00000000000..1489791b20d --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs new file mode 100644 index 00000000000..37e6f948ad1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -0,0 +1,69 @@ +// Check that we can manually implement an object-unsafe trait for its trait object. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ run-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Bad { + fn stat() -> char { + 'A' + } + fn virt(&self) -> char { + 'B' + } + fn indirect(&self) -> char { + Self::stat() + } +} + +trait Good { + fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used + panic!() + } + fn good_indirect(&self) -> char { + panic!() + } +} + +impl<'a> Bad for dyn Bad + 'a { + fn stat() -> char { + 'C' + } + fn virt(&self) -> char { + 'D' + } +} + +struct Struct {} + +impl Bad for Struct {} + +impl Good for Struct {} + +fn main() { + let s = Struct {}; + + let mut res = String::new(); + + // Directly call static. + res.push(Struct::stat()); // "A" + res.push(::stat()); // "AC" + + let good: &dyn Good = &s; + + // These look similar enough... + let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; + + // Call virtual. + res.push(s.virt()); // "ACB" + res.push(bad.virt()); // "ACBD" + + // Indirectly call static. + res.push(s.indirect()); // "ACBDA" + res.push(bad.indirect()); // "ACBDAC" + + assert_eq!(&res, "ACBDAC"); +} diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs new file mode 100644 index 00000000000..c38928a9f44 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs @@ -0,0 +1,37 @@ +// Check that we can statically dispatch methods for object +// unsafe trait objects, directly and indirectly +// +//@ check-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Statics { + fn plain() {} + fn generic() {} +} + +trait Trait: Sized {} + +impl<'a> Statics for dyn Trait + 'a {} + +fn static_poly() { + T::plain(); + T::generic::(); +} + +fn inferred_poly(t: &T) { + static_poly::(); + T::plain(); + T::generic::(); +} + +fn call(t: &dyn Trait) { + static_poly::(); + inferred_poly(t); +} + +fn main() { + static_poly::(); + ::plain(); + ::generic::() +} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs deleted file mode 100644 index d4337dcb165..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Check that we if we get ahold of an object unsafe trait -// object with auto traits and lifetimes, we can downcast it -// -//@ check-pass - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { - t -} - -fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) - -> &'b (dyn Trait + 't) -where - 'a: 'b, - 't: 'a + 'b, -{ - t -} - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr deleted file mode 100644 index 1489791b20d..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: methods `good_virt` and `good_indirect` are never used - --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 - | -LL | trait Good { - | ---- methods in this trait -LL | fn good_virt(&self) -> char { - | ^^^^^^^^^ -... -LL | fn good_indirect(&self) -> char { - | ^^^^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr deleted file mode 100644 index 1489791b20d..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: methods `good_virt` and `good_indirect` are never used - --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 - | -LL | trait Good { - | ---- methods in this trait -LL | fn good_virt(&self) -> char { - | ^^^^^^^^^ -... -LL | fn good_indirect(&self) -> char { - | ^^^^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs deleted file mode 100644 index a020d91fb14..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Check that we can manually implement an object-unsafe trait for its trait object. - -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@ run-pass - -#![feature(object_safe_for_dispatch)] - -trait Bad { - fn stat() -> char { - 'A' - } - fn virt(&self) -> char { - 'B' - } - fn indirect(&self) -> char { - Self::stat() - } -} - -trait Good { - fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used - panic!() - } - fn good_indirect(&self) -> char { - panic!() - } -} - -impl<'a> Bad for dyn Bad + 'a { - fn stat() -> char { - 'C' - } - fn virt(&self) -> char { - 'D' - } -} - -struct Struct {} - -impl Bad for Struct {} - -impl Good for Struct {} - -fn main() { - let s = Struct {}; - - let mut res = String::new(); - - // Directly call static. - res.push(Struct::stat()); // "A" - res.push(::stat()); // "AC" - - let good: &dyn Good = &s; - - // These look similar enough... - let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; - - // Call virtual. - res.push(s.virt()); // "ACB" - res.push(bad.virt()); // "ACBD" - - // Indirectly call static. - res.push(s.indirect()); // "ACBDA" - res.push(bad.indirect()); // "ACBDAC" - - assert_eq!(&res, "ACBDAC"); -} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs deleted file mode 100644 index cbf76a6830b..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Check that we can statically dispatch methods for object -// unsafe trait objects, directly and indirectly -// -//@ check-pass - -#![feature(object_safe_for_dispatch)] - -trait Statics { - fn plain() {} - fn generic() {} -} - -trait Trait: Sized {} - -impl<'a> Statics for dyn Trait + 'a {} - -fn static_poly() { - T::plain(); - T::generic::(); -} - -fn inferred_poly(t: &T) { - static_poly::(); - T::plain(); - T::generic::(); -} - -fn call(t: &dyn Trait) { - static_poly::(); - inferred_poly(t); -} - -fn main() { - static_poly::(); - ::plain(); - ::generic::() -} diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..fda07765c66 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,22 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = help: only type `usize` implements the trait, consider using it directly instead + = note: required for the cast from `Rc` to `Rc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr deleted file mode 100644 index fda07765c66..00000000000 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 - | -LL | fn foo(self: &Rc) -> usize; - | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` -... -LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | fn foo(self: &Rc) -> usize; - | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements the trait, consider using it directly instead - = note: required for the cast from `Rc` to `Rc` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-not-object-safe.rs index 0053eb5f739..940b2f1e8e2 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,6 +1,6 @@ -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::rc::Rc; @@ -33,7 +33,7 @@ fn make_foo() { let x = Rc::new(5usize) as Rc; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn make_bar() { diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs index c3707baf79f..2b0fbdb8d35 100644 --- a/tests/ui/suggestions/issue-104328.rs +++ b/tests/ui/suggestions/issue-104328.rs @@ -1,4 +1,4 @@ -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Foo { fn f() {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs index ffdb49a3be5..e32b04c4715 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects inside a Box -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs index 143b854ed6b..6f386352819 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects by ref -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs index c8731a8ecaf..07e90538b85 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.rs +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -1,7 +1,7 @@ // Check that we do not allow coercions to object // unsafe trait objects in match arms -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} -- cgit 1.4.1-3-g733a5 From a7dc98733da8b84cfc21a538541a41803c4529a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:41:13 -0400 Subject: Add variances to RPITITs --- compiler/rustc_hir_analysis/src/variance/mod.rs | 49 ++++++++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 4 ++ compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/relate.rs | 10 ++++ tests/ui/impl-trait/in-trait/variance.rs | 23 +++++---- tests/ui/impl-trait/in-trait/variance.stderr | 34 +++++++++---- .../precise-capturing/forgot-to-capture-type.rs | 3 +- .../forgot-to-capture-type.stderr | 17 ++----- .../precise-capturing/redundant.normal.stderr | 20 -------- .../precise-capturing/redundant.rpitit.stderr | 24 --------- tests/ui/impl-trait/precise-capturing/redundant.rs | 15 +++--- .../impl-trait/precise-capturing/redundant.stderr | 36 +++++++++++++ .../rpitit-captures-more-method-lifetimes.rs | 5 +- .../rpitit-captures-more-method-lifetimes.stderr | 23 +++------ .../rpitit-impl-captures-too-much.rs | 14 +++++ .../rpitit-impl-captures-too-much.stderr | 17 +++++++ tests/ui/impl-trait/precise-capturing/rpitit.rs | 31 +++++++++--- .../ui/impl-trait/precise-capturing/rpitit.stderr | 59 ++++++++++------------ .../impl-trait/precise-capturing/self-capture.rs | 5 +- .../precise-capturing/self-capture.stderr | 13 ----- 21 files changed, 241 insertions(+), 168 deletions(-) delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.normal.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 12bb9a3f9e0..02cfb57b836 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_arena::DroplessArena; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; @@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } + DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return variance_of_opaque( + tcx, + opaque_def_id.expect_local(), + ForceCaptureTraitArgs::Yes, + ); + } + None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {} + }, DefKind::OpaqueTy => { - return variance_of_opaque(tcx, item_def_id); + let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn { + parent: _, + in_trait_or_impl: Some(hir::RpitContext::Trait), + } = + tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin + { + ForceCaptureTraitArgs::Yes + } else { + ForceCaptureTraitArgs::No + }; + + return variance_of_opaque(tcx, item_def_id, force_capture_trait_args); } _ => {} } @@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item"); } +#[derive(Debug, Copy, Clone)] +enum ForceCaptureTraitArgs { + Yes, + No, +} + #[instrument(level = "trace", skip(tcx), ret)] -fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { +fn variance_of_opaque( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + force_capture_trait_args: ForceCaptureTraitArgs, +) -> &[ty::Variance] { let generics = tcx.generics_of(item_def_id); // Opaque types may only use regions that are bound. So for @@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc #[instrument(level = "trace", skip(self), ret)] fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::Alias(_, ty::AliasTy { def_id, args, .. }) - if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => - { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), @@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut generics = generics; while let Some(def_id) = generics.parent { generics = tcx.generics_of(def_id); + + // Don't mark trait params generic if we're in an RPITIT. + if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes) + && generics.parent.is_none() + { + debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + break; + } + for param in &generics.own_params { match param.kind { ty::GenericParamDefKind::Lifetime => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 610c682d3a4..afe03531861 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn => true, + DefKind::AssocTy => { + // Only encode variances for RPITITs (for traits) + matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. })) + } DefKind::Mod | DefKind::Field - | DefKind::AssocTy | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 90265f67bc1..590e1d336f3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(trait_def_id).implement_via_object } + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { + self.is_impl_trait_in_trait(def_id) + } + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a72e7b482a6..f06017d7e5c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -261,6 +261,8 @@ pub trait Interner: fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; + fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 1302906adab..e1f3e493e36 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -254,6 +254,16 @@ impl Relate for ty::AliasTy { b.args, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?, + ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => { + relate_args_with_variances( + relation, + a.def_id, + relation.cx().variances_of(a.def_id), + a.args, + b.args, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )? + } ty::Projection | ty::Weak | ty::Inherent => { relate_args_invariantly(relation, a.args, b.args)? } diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 0ac44bf7546..19905c608e3 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -1,22 +1,25 @@ -#![feature(rustc_attrs)] +#![feature(rustc_attrs, precise_capturing_in_traits)] #![allow(internal_features)] #![rustc_variance_of_opaques] -trait Captures<'a> {} -impl Captures<'_> for T {} - trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] + + fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o] fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: o, 'i: o] + + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'i: o, 'a: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 54e0afbaa95..f65174e1c35 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,26 +1,38 @@ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:9:44 +error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:6:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:12:44 +error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + --> $DIR/variance.rs:9:44 + | +LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [Self: o, 'i: o, 'a: *, 'i: o] + --> $DIR/variance.rs:12:40 | -LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'i: o, 'a: o] --> $DIR/variance.rs:18:48 | -LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [Self: o, 'i: o, 'i: o] + --> $DIR/variance.rs:21:44 + | +LL | fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 9d68819f657..6c2477c9744 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,10 +1,11 @@ +#![feature(precise_capturing_in_traits)] + fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope trait Foo { fn bar() -> impl Sized + use<>; //~^ ERROR `impl Trait` must mention the `Self` type of the trait - //~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 23d6a3bd11e..93b44a0c18c 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,16 +1,5 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/forgot-to-capture-type.rs:5:30 - | -LL | fn bar() -> impl Sized + use<>; - | ^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-type.rs:1:23 + --> $DIR/forgot-to-capture-type.rs:3:23 | LL | fn type_param() -> impl Sized + use<> {} | - ^^^^^^^^^^^^^^^^^^ @@ -20,7 +9,7 @@ LL | fn type_param() -> impl Sized + use<> {} = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention the `Self` type of the trait in `use<...>` - --> $DIR/forgot-to-capture-type.rs:5:17 + --> $DIR/forgot-to-capture-type.rs:7:17 | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` @@ -29,5 +18,5 @@ LL | fn bar() -> impl Sized + use<>; | = note: currently, all type parameters are required to be mentioned in the precise captures list -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr deleted file mode 100644 index d1bcbaa33ae..00000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:5:19 - | -LL | fn hello<'a>() -> impl Sized + use<'a> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - | - = note: `#[warn(impl_trait_redundant_captures)]` on by default - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:10:27 - | -LL | fn inherent(&self) -> impl Sized + use<'_> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - -warning: 2 warnings emitted - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr deleted file mode 100644 index 27f8ff92d3e..00000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:16:35 - | -LL | fn in_trait() -> impl Sized + use<'a, Self>; - | ^^^^^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:21:35 - | -LL | fn in_trait() -> impl Sized + use<'a> {} - | ^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 4a08ffb61be..e19d935f5b0 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -1,25 +1,24 @@ //@ compile-flags: -Zunstable-options --edition=2024 -//@ revisions: normal rpitit -//@[normal] check-pass +//@ check-pass + +#![feature(precise_capturing_in_traits)] fn hello<'a>() -> impl Sized + use<'a> {} -//[normal]~^ WARN all possible in-scope parameters are already captured +//~^ WARN all possible in-scope parameters are already captured struct Inherent; impl Inherent { fn inherent(&self) -> impl Sized + use<'_> {} - //[normal]~^ WARN all possible in-scope parameters are already captured + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] trait Test<'a> { fn in_trait() -> impl Sized + use<'a, Self>; - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] impl<'a> Test<'a> for () { fn in_trait() -> impl Sized + use<'a> {} - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr new file mode 100644 index 00000000000..274d9d2375f --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr @@ -0,0 +1,36 @@ +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:6:19 + | +LL | fn hello<'a>() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + | + = note: `#[warn(impl_trait_redundant_captures)]` on by default + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:11:27 + | +LL | fn inherent(&self) -> impl Sized + use<'_> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:16:22 + | +LL | fn in_trait() -> impl Sized + use<'a, Self>; + | ^^^^^^^^^^^^^------------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:20:22 + | +LL | fn in_trait() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: 4 warnings emitted + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index 062351afecb..b39c1408c05 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -2,13 +2,14 @@ // trait definition, which is not allowed. Due to the default lifetime capture // rules of RPITITs, this is only doable if we use precise capturing. +#![feature(precise_capturing_in_traits)] + pub trait Foo { fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } impl Foo for () { - fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} + fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} //~^ ERROR return type captures more lifetimes than trait definition } diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index ffd9646a403..45f755d3cc1 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -1,28 +1,17 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53 - | -LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: return type captures more lifetimes than trait definition - --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40 | -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} - | --- ^^^^^^^^^^^^^^^^ +LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} + | --- ^^^^^^^^^^^^^^^^^^^^^ | | | this lifetime was captured | note: hidden type must only reference lifetimes captured by this impl trait - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40 | LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: hidden type inferred to be `impl Sized + 'im` + = note: hidden type inferred to be `impl Sized` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs new file mode 100644 index 00000000000..b16b0522d6e --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs @@ -0,0 +1,14 @@ +#![feature(precise_capturing_in_traits)] + +struct Invariant<'a>(&'a mut &'a mut ()); + +trait Trait { + fn hello(self_: Invariant<'_>) -> impl Sized + use; +} + +impl Trait for () { + fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + //~^ ERROR return type captures more lifetimes than trait definition +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr new file mode 100644 index 00000000000..e1856b92910 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -0,0 +1,17 @@ +error: return type captures more lifetimes than trait definition + --> $DIR/rpitit-impl-captures-too-much.rs:10:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + | -- ^^^^^^^^^^^^^^^^^^^^ + | | + | this lifetime was captured + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/rpitit-impl-captures-too-much.rs:6:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Sized` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index feeeb1461e8..3f887e8e47f 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -1,19 +1,34 @@ -//@ known-bug: unknown - // RPITITs don't have variances in their GATs, so they always relate invariantly // and act as if they capture all their args. // To fix this soundly, we need to make sure that all the trait header args // remain captured, since they affect trait selection. -trait Foo<'a> { - fn hello() -> impl PartialEq + use; +#![feature(precise_capturing_in_traits)] + +fn eq_types(_: T, _: T) {} + +trait TraitLt<'a: 'a> { + fn hello() -> impl Sized + use; + //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list +} +fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + eq_types( + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + >::hello(), + >::hello(), + ); } -fn test<'a, 'b, T: for<'r> Foo<'r>>() { - PartialEq::eq( - &>::hello(), - &>::hello(), +trait MethodLt { + fn hello<'a: 'a>() -> impl Sized + use; +} +fn method_lt<'a, 'b, T: MethodLt> () { + eq_types( + T::hello::<'a>(), + T::hello::<'b>(), ); + // Good! } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index c162875f327..8c219bb04a2 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,47 +1,40 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit.rs:9:36 - | -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/rpitit.rs:9:19 + --> $DIR/rpitit.rs:11:19 | -LL | trait Foo<'a> { - | -- this lifetime parameter is captured -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` +LL | trait TraitLt<'a: 'a> { + | -- this lifetime parameter is captured +LL | fn hello() -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'b` must outlive `'a` | @@ -49,5 +42,5 @@ LL | | ); help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index a61a7f06edc..15985da50b5 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,6 +1,9 @@ +//@ check-pass + +#![feature(precise_capturing_in_traits)] + trait Foo { fn bar<'a>() -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr deleted file mode 100644 index 45ebc429d88..00000000000 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/self-capture.rs:2:34 - | -LL | fn bar<'a>() -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -- cgit 1.4.1-3-g733a5 From 36076ecdc726c4e1104e70df2d142f39501a4f48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:32 -0400 Subject: Clarify implicit captures for RPITIT --- compiler/rustc_hir_analysis/messages.ftl | 3 +++ compiler/rustc_hir_analysis/src/check/check.rs | 25 ++++++++++++++-------- .../src/errors/precise_captures.rs | 9 ++++++++ .../ui/impl-trait/precise-capturing/rpitit.stderr | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c73826c489f..a80dc87c622 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -259,6 +259,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl .label = type parameter declared here +hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + .param_label = all lifetime parameters originating from a trait are captured implicitly + hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters .label = move the lifetime before this parameter diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eb62ff86c71..d0063b449f8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -589,15 +589,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe param_span: tcx.def_span(def_id), }); } else { - // If the `use_span` is actually just the param itself, then we must - // have not duplicated the lifetime but captured the original. - // The "effective" `use_span` will be the span of the opaque itself, - // and the param span will be the def span of the param. - tcx.dcx().emit_err(errors::LifetimeNotCaptured { - opaque_span, - use_span: opaque_span, - param_span: use_span, - }); + if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait { + tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured { + opaque_span, + param_span: tcx.def_span(param.def_id), + }); + } else { + // If the `use_span` is actually just the param itself, then we must + // have not duplicated the lifetime but captured the original. + // The "effective" `use_span` will be the span of the opaque itself, + // and the param span will be the def span of the param. + tcx.dcx().emit_err(errors::LifetimeNotCaptured { + opaque_span, + use_span: opaque_span, + param_span: use_span, + }); + } } continue; } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index b6cffb90805..8a83866b7fa 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -34,6 +34,15 @@ pub(crate) struct LifetimeNotCaptured { pub opaque_span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_lifetime_implicitly_captured)] +pub(crate) struct LifetimeImplicitlyCaptured { + #[primary_span] + pub opaque_span: Span, + #[label(hir_analysis_param_label)] + pub param_span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_bad_precise_capture)] pub(crate) struct BadPreciseCapture { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 8c219bb04a2..498eae54a1c 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -2,9 +2,9 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use --> $DIR/rpitit.rs:11:19 | LL | trait TraitLt<'a: 'a> { - | -- this lifetime parameter is captured + | -- all lifetime parameters originating from a trait are captured implicitly LL | fn hello() -> impl Sized + use; - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` + | ^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/rpitit.rs:15:5 -- cgit 1.4.1-3-g733a5 From 322c4bdac595e7689dcf08b847d0bd4d82a4bad9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:53 -0400 Subject: Don't fire refinement lint if there are errors --- compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 80334c6efe7..2d6b9813271 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -64,6 +64,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; + if hidden_tys.items().any(|(_, &ty)| ty.skip_binder().references_error()) { + return; + } + let mut collector = ImplTraitInTraitCollector { tcx, types: FxIndexSet::default() }; trait_m_sig.visit_with(&mut collector); -- cgit 1.4.1-3-g733a5 From 9a2772e1c2d6e770e13716d4691bc0a943cd7d61 Mon Sep 17 00:00:00 2001 From: VulnBandit <183613941+VulnBandit@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:10:28 +0200 Subject: Don't assume traits used as type are trait objs --- .../rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 53 ++++---- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 19 ++- tests/crashes/120241-2.rs | 10 -- tests/crashes/120241.rs | 13 -- tests/crashes/120482.rs | 13 -- tests/crashes/125512.rs | 10 -- .../suggest-assoc-ty-bound-on-eq-bound.rs | 20 ++- .../suggest-assoc-ty-bound-on-eq-bound.stderr | 58 ++------- ...body-to-be-a-closure-or-coroutine-ice-113776.rs | 4 +- ...-to-be-a-closure-or-coroutine-ice-113776.stderr | 39 +----- tests/ui/const-generics/not_wf_param_in_rpitit.rs | 3 +- .../const-generics/not_wf_param_in_rpitit.stderr | 55 ++++---- .../avoid-ice-on-warning-2.new.stderr | 40 ++---- .../avoid-ice-on-warning-2.old.stderr | 2 +- .../ui/dyn-compatibility/avoid-ice-on-warning-2.rs | 7 +- .../avoid-ice-on-warning-3.new.stderr | 74 ++++++----- .../avoid-ice-on-warning-3.old.stderr | 10 +- .../ui/dyn-compatibility/avoid-ice-on-warning-3.rs | 8 +- .../avoid-ice-on-warning.new.stderr | 16 ++- tests/ui/dyn-compatibility/avoid-ice-on-warning.rs | 1 + .../bare-trait-dont-suggest-dyn.new.fixed | 3 +- .../bare-trait-dont-suggest-dyn.new.stderr | 15 +-- .../bare-trait-dont-suggest-dyn.rs | 3 +- ...-trait-in-fn-inputs-and-outputs-issue-125139.rs | 57 ++++----- ...it-in-fn-inputs-and-outputs-issue-125139.stderr | 141 +++++++++------------ tests/ui/dyn-keyword/dyn-2021-edition-error.rs | 6 +- tests/ui/dyn-keyword/dyn-2021-edition-error.stderr | 10 +- .../suggest-dyn-on-bare-trait-in-pat.rs | 3 +- .../suggest-dyn-on-bare-trait-in-pat.stderr | 4 +- tests/ui/editions/dyn-trait-sugg-2021.rs | 2 +- tests/ui/editions/dyn-trait-sugg-2021.stderr | 4 +- ...th-implicit-hrtb-without-dyn.edition2021.stderr | 15 +-- .../generic-with-implicit-hrtb-without-dyn.rs | 3 +- tests/ui/resolve/issue-111312.rs | 3 +- tests/ui/resolve/issue-111312.stderr | 21 +-- tests/ui/resolve/issue-111727.rs | 3 +- tests/ui/resolve/issue-111727.stderr | 15 +-- .../ui/rust-2021/ice-return-unsized-can-impl-2.rs | 15 +++ .../rust-2021/ice-return-unsized-can-impl-2.stderr | 57 +++++++++ tests/ui/rust-2021/ice-return-unsized-can-impl.rs | 16 +++ .../rust-2021/ice-return-unsized-can-impl.stderr | 30 +++++ tests/ui/rust-2021/ice-unsized-fn-params-2.rs | 12 ++ tests/ui/rust-2021/ice-unsized-fn-params-2.stderr | 19 +++ tests/ui/rust-2021/ice-unsized-fn-params.rs | 18 +++ tests/ui/rust-2021/ice-unsized-fn-params.stderr | 57 +++++++++ ...tible-trait-should-use-self-2021-without-dyn.rs | 15 +-- ...e-trait-should-use-self-2021-without-dyn.stderr | 81 ++---------- tests/ui/suggestions/issue-116434-2021.rs | 6 +- tests/ui/suggestions/issue-116434-2021.stderr | 27 ++-- .../suggest-blanket-impl-local-trait.rs | 28 ++-- .../suggest-blanket-impl-local-trait.stderr | 28 ++-- ...gest-swapping-self-ty-and-trait-edition-2021.rs | 6 +- ...-swapping-self-ty-and-trait-edition-2021.stderr | 12 +- tests/ui/traits/bound/not-on-bare-trait-2021.rs | 8 +- .../ui/traits/bound/not-on-bare-trait-2021.stderr | 49 +------ tests/ui/traits/issue-106072.rs | 4 +- tests/ui/traits/issue-106072.stderr | 29 +---- .../traits/missing-for-type-in-impl.e2021.stderr | 4 +- tests/ui/traits/missing-for-type-in-impl.rs | 2 +- 59 files changed, 607 insertions(+), 679 deletions(-) delete mode 100644 tests/crashes/120241-2.rs delete mode 100644 tests/crashes/120241.rs delete mode 100644 tests/crashes/120482.rs delete mode 100644 tests/crashes/125512.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 5607fe873f6..11c0450bfe2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -1,6 +1,6 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, StashKey}; +use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::Applicability; @@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty( + &self, + self_ty: &hir::Ty<'_>, + ) -> Option { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = self_ty.kind else { - return; + return None; }; let in_path = match tcx.parent_hir_node(self_ty.hir_id) { @@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if self_ty.span.edition().at_least_rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; + let msg = "expected a type, found a trait"; + let label = "you can add the `dyn` keyword if you want a trait object"; let mut diag = rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() @@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + // In case there is an associate type with the same name + // Add the suggestion to this error + if let Some(mut sugg) = + tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) + && let Suggestions::Enabled(ref mut s1) = diag.suggestions + && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + { + s1.append(s2); + sugg.cancel(); + } + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); + None } } @@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 1. Independent functions // 2. Functions inside trait blocks // 3. Functions inside impl blocks - let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { - (sig, generics, None) + (sig, generics) } hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - let mut is_downgradable = true; - // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|(o, _)| match o.trait_ref.path.res { - Res::Def(DefKind::Trait, id) => { - if Some(id) == owner { - // For recursive traits, don't downgrade the error. (#119652) - is_downgradable = false; - } - tcx.is_dyn_compatible(id) - } + Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) } @@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion, Applicability::MachineApplicable, ); - } else if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); } return true; } @@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); if !is_dyn_compatible { diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); - if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); - } } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 28a1fc88741..682d29e6e82 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2063,13 +2063,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty); - - let repr = match repr { - TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, - TraitObjectSyntax::DynStar => ty::DynStar, - }; - self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { + // Don't continue with type analysis if the `dyn` keyword is missing + // It generates confusing errors, especially if the user meant to use another + // keyword like `impl` + Ty::new_error(tcx, guar) + } else { + let repr = match repr { + TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, + TraitObjectSyntax::DynStar => ty::DynStar, + }; + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + } } // If we encounter a fully qualified path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs deleted file mode 100644 index 91ec3362090..00000000000 --- a/tests/crashes/120241-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -#![feature(unsized_fn_params)] - -fn guard(_s: Copy) -> bool { - panic!() -} - -fn main() {} diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs deleted file mode 100644 index b4fcb903714..00000000000 --- a/tests/crashes/120241.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn f(a: A) -> A; -} - -trait A { - fn g(b: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs deleted file mode 100644 index a395855d796..00000000000 --- a/tests/crashes/120482.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120482 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn bar(&self, x: &Self); -} - -trait A { - fn g(new: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs deleted file mode 100644 index 37dbdf2f32f..00000000000 --- a/tests/crashes/125512.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#125512 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -trait B { - fn f(a: A) -> A; -} -trait A { - fn concrete(b: B) -> B; -} -fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs index 7df042d5f88..c8bb0ebd574 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -2,28 +2,24 @@ //@ edition: 2021 fn f(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR the trait `Copy` cannot be made into an object fn g(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR only auto traits can be used as additional traits in a trait object -//~| HELP consider creating a new trait -//~| ERROR the trait `Eq` cannot be made into an object fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here // Don't suggest assoc ty bound in trait object types, that's not valid: type Obj = dyn Trait; -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object trait Trait { type T; } diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr index bec60187e42..dbe285c5310 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -1,41 +1,10 @@ -error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20 - | -LL | fn f(_: impl Trait) {} - | ^^^^^^^^ `Copy` cannot be made into an object - | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42 - | -LL | fn g(_: impl Trait) {} - | --------------- ^^ additional non-auto trait - | | - | first non-auto trait - | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}` - = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit - -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 - | -LL | fn g(_: impl Trait) {} - | ^^^^^^^^^^^^^^^^^^^^ `Eq` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24 | LL | fn f(_: impl Trait) {} | ^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn f(_: impl Trait) {} | +++ @@ -44,13 +13,13 @@ help: you might have meant to write a bound here LL | fn f(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24 | LL | fn g(_: impl Trait) {} | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn g(_: impl Trait) {} | +++ @@ -59,13 +28,13 @@ help: you might have meant to write a bound here LL | fn g(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26 | LL | fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn h(_: impl Trait = dyn 'static + for<'a> Fn(&'a ())>) {} | +++ @@ -74,18 +43,17 @@ help: you might have meant to write a bound here LL | fn h(_: impl Trait: 'static + for<'a> Fn(&'a ())>) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26 | LL | type Obj = dyn Trait; | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | type Obj = dyn Trait; | +++ -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0038, E0225, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs index 4bea3ad87f5..c1d3321f840 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs @@ -14,10 +14,8 @@ fn f( 1 }], ) -> impl Iterator { -//~^ ERROR the type parameter `Rhs` must be explicitly specified +//~^ ERROR expected a type, found a trait //~| ERROR `()` is not an iterator -//~| ERROR trait objects must include the `dyn` keyword -//~| ERROR the type parameter `Rhs` must be explicitly specified [E0393] } pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr index 416a9381124..5c4d643a28e 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -16,37 +16,6 @@ help: you might be missing a type parameter LL | fn f( | +++ -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - error[E0277]: `()` is not an iterator --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6 | @@ -55,13 +24,13 @@ LL | ) -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 | LL | ) -> impl Iterator { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ) -> impl Iterator { | +++ @@ -70,7 +39,7 @@ help: you might have meant to write a bound here LL | ) -> impl Iterator { | ~ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0393, E0412, E0782. +Some errors have detailed explanations: E0277, E0412, E0782. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs index eb672194340..b454562ad49 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.rs +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -1,12 +1,11 @@ //@ edition:2021 -trait Trait { +trait Trait { //~^ ERROR: cannot find value `bar` in this scope //~| ERROR: cycle detected when computing type of `Trait::N` //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: trait objects must include the `dyn` keyword async fn a() {} } diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr index ade40550c73..2500409e828 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -1,33 +1,33 @@ error[E0425]: cannot find value `bar` in this scope - --> $DIR/not_wf_param_in_rpitit.rs:3:30 + --> $DIR/not_wf_param_in_rpitit.rs:3:34 | -LL | trait Trait { - | ^^^ not found in this scope +LL | trait Trait { + | ^^^ not found in this scope error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/not_wf_param_in_rpitit.rs:3:22 + --> $DIR/not_wf_param_in_rpitit.rs:3:26 | -LL | trait Trait { - | ^^^^^ +LL | trait Trait { + | ^^^^^ | = note: ...which immediately requires computing type of `Trait::N` again note: cycle used when computing explicit predicates of trait `Trait` --> $DIR/not_wf_param_in_rpitit.rs:3:1 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:22 | -LL | trait Trait { - | ^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -44,13 +44,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -67,13 +67,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -88,18 +88,7 @@ help: alternatively, consider constraining `a` so it does not apply to trait obj LL | async fn a() where Self: Sized {} | +++++++++++++++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not_wf_param_in_rpitit.rs:3:22 - | -LL | trait Trait { - | ^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | trait Trait { - | +++ - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0038, E0391, E0425, E0782. +Some errors have detailed explanations: E0038, E0391, E0425. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr index 4e3d2ebebad..83795f3128e 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr @@ -1,41 +1,19 @@ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { - | ^^^^ `Copy` cannot be made into an object + | ^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` | -LL | fn id(f: Copy) -> usize { - | - `f` has type `(dyn Copy + 'static)` -... -LL | f() - | ^-- - | | - | call expression requires function - -error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time - --> $DIR/avoid-ice-on-warning-2.rs:4:13 - | -LL | fn id(f: Copy) -> usize { - | ^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference | LL | fn id(f: impl Copy) -> usize { | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn id(f: &dyn Copy) -> usize { - | ++++ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0277, E0618. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr index 180cd679dea..54daefea31c 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr @@ -36,7 +36,7 @@ LL | fn id(f: Copy) -> usize { = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + --> $DIR/avoid-ice-on-warning-2.rs:12:5 | LL | fn id(f: Copy) -> usize { | - `f` has type `(dyn Copy + 'static)` diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs index db2f4aea05b..3c2da667b39 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs @@ -2,13 +2,14 @@ //@[old] edition:2015 //@[new] edition:2021 fn id(f: Copy) -> usize { -//~^ ERROR the trait `Copy` cannot be made into an object -//~| ERROR: the size for values of type `(dyn Copy + 'static)` +//[new]~^ ERROR expected a type, found a trait +//[old]~^^ ERROR the trait `Copy` cannot be made into an object +//[old]~| ERROR the size for values of type `(dyn Copy + 'static)` //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() - //~^ ERROR: expected function, found `(dyn Copy + 'static)` + //[old]~^ ERROR: expected function, found `(dyn Copy + 'static)` } fn main() {} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr index fdd3e8ab507..813b5863738 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr @@ -1,47 +1,57 @@ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:4:19 +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | -LL | trait B { fn f(a: A) -> A; } - | ^ `A` cannot be made into an object +LL | trait A { fn g(b: B) -> B; } + | ^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } - | - ^ ...because associated function `g` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `g` into a method by giving it a `&self` argument + | ^ | -LL | trait A { fn g(&self, b: B) -> B; } - | ++++++ -help: alternatively, consider constraining `g` so it does not apply to trait objects +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type | -LL | trait A { fn g(b: B) -> B where Self: Sized; } - | +++++++++++++++++ +LL | trait A { fn g(b: B) -> impl B; } + | ++++ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } - | ^ `B` cannot be made into an object +LL | trait B { fn f(a: A) -> A; } + | ^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:4:14 + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | LL | trait B { fn f(a: A) -> A; } - | - ^ ...because associated function `f` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `f` into a method by giving it a `&self` argument + | ^ | -LL | trait B { fn f(&self, a: A) -> A; } - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type | -LL | trait B { fn f(a: A) -> A where Self: Sized; } - | +++++++++++++++++ +LL | trait B { fn f(a: A) -> impl A; } + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index bd362abb355..6bc2d73a0d0 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -26,7 +26,7 @@ LL | trait B { fn f(a: A) -> dyn A; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -39,7 +39,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:25 + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -72,7 +72,7 @@ LL | trait B { fn f(a: A) -> A; } | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + --> $DIR/avoid-ice-on-warning-3.rs:14:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -88,7 +88,7 @@ LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -102,7 +102,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` cannot be made into an object diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs index 38bee8142bb..00d47225e92 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs @@ -2,7 +2,9 @@ //@[old] edition:2015 //@[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ ERROR the trait `A` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `A` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated @@ -10,7 +12,9 @@ trait B { fn f(a: A) -> A; } //[old]~| WARN this is accepted in the current edition //[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ ERROR the trait `B` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `B` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr index 4ff45d7a848..e9eb1cdd0c2 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr @@ -15,6 +15,18 @@ error[E0405]: cannot find trait `call_that` in this scope LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning.rs:4:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: `Fn(&str) + call_that` is dyn-incompatible, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0405`. +Some errors have detailed explanations: E0405, E0782. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs index b90d8911d50..ef82321df0e 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs @@ -4,6 +4,7 @@ fn call_this(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope +//[new]~| ERROR expected a type, found a trait //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed index 4f5310082e1..a54892afd3e 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr index bb2bf6ddcda..52168261a64 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr @@ -1,21 +1,14 @@ -error[E0038]: the trait `Ord` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 | LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ `Ord` cannot be made into an object + | ^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - ::: $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter -help: consider using an opaque type instead +help: `Ord` is dyn-incompatible, use `impl Ord` to return an opaque type, as long as you return a single underlying type | LL | fn ord_prefer_dot(s: String) -> impl Ord { | ++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs index cb5a305eab0..cf9be612d2e 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs index dabaa309c16..7bc2af463cb 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs @@ -6,104 +6,102 @@ struct IceCream; impl IceCream { fn foo(_: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(self, _: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(&self, _: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } trait Sing { fn foo(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait; //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } fn foo(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait struct Type; @@ -111,32 +109,31 @@ impl Trait for Type {} fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } fn main() {} diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr index 8bdfea7766e..4c6d84f0534 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr @@ -65,7 +65,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:16 | LL | fn bar(_: &'a Trait); | ^^ undeclared lifetime @@ -80,7 +80,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:17 | LL | fn cat() -> &Trait; | ^ expected named lifetime parameter @@ -97,7 +97,7 @@ LL + fn cat() -> Trait; | error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:21 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -109,7 +109,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:21 | LL | fn kitten() -> &'a Trait { | ^^ undeclared lifetime @@ -124,7 +124,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:20 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:20 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -136,7 +136,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:12 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:12 | LL | fn bar(_: &'a Trait) {} | - ^^ undeclared lifetime @@ -144,7 +144,7 @@ LL | fn bar(_: &'a Trait) {} | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:13 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:13 | LL | fn cat() -> &Trait { | ^ expected named lifetime parameter @@ -156,7 +156,7 @@ LL | fn cat() -> &'static Trait { | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:17 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -168,7 +168,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:17 | LL | fn kitten() -> &'a Trait { | - ^^ undeclared lifetime @@ -176,7 +176,7 @@ LL | fn kitten() -> &'a Trait { | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:16 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -187,35 +187,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn parrot() -> &'static mut Trait { | +++++++ -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:47:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:90:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:138:5 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:53:16 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 | LL | fn foo(_: &Trait); | ^^^^^ @@ -233,8 +206,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 | LL | fn bar(_: &'a Trait); | ^^^^^ @@ -252,8 +225,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:60:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 | LL | fn alice<'a>(_: &Trait); | ^^^^^ @@ -271,8 +244,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:63:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 | LL | fn bob<'a>(_: &'a Trait); | ^^^^^ @@ -290,8 +263,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 | LL | fn cat() -> &Trait; | ^^^^^ @@ -305,8 +278,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box; | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -320,8 +293,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:24 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -335,8 +308,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:82:27 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -350,8 +323,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -365,8 +338,8 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:95:12 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:93:12 | LL | fn foo(_: &Trait) {} | ^^^^^ @@ -384,8 +357,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:15 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:15 | LL | fn bar(_: &'a Trait) {} | ^^^^^ @@ -403,8 +376,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:102:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:100:18 | LL | fn alice<'a>(_: &Trait) {} | ^^^^^ @@ -422,8 +395,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:105:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:103:19 | LL | fn bob<'a>(_: &'a Trait) {} | ^^^^^ @@ -441,8 +414,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:14 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:14 | LL | fn cat() -> &Trait { | ^^^^^ @@ -456,8 +429,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:18 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -471,8 +444,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:20 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:20 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -486,8 +459,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:130:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:128:23 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -501,8 +474,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:21 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -516,7 +489,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:8:16 | LL | fn foo(_: &Trait) {} @@ -535,7 +508,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:25 | LL | fn bar(self, _: &'a Trait) {} @@ -554,7 +527,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(self, _: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:15:29 | LL | fn alice<'a>(&self, _: &Trait) {} @@ -573,7 +546,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(&self, _: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:18:23 | LL | fn bob<'a>(_: &'a Trait) {} @@ -592,7 +565,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:18 | LL | fn cat() -> &Trait { @@ -607,7 +580,7 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:22 | LL | fn dog<'a>() -> &Trait { @@ -622,7 +595,7 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:24 | LL | fn kitten() -> &'a Trait { @@ -637,7 +610,7 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:39:27 | LL | fn puppy<'a>() -> &'a Trait { @@ -652,7 +625,7 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25 | LL | fn parrot() -> &mut Trait { @@ -667,7 +640,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error: aborting due to 45 previous errors +error: aborting due to 42 previous errors -Some errors have detailed explanations: E0106, E0261, E0515, E0782. +Some errors have detailed explanations: E0106, E0261, E0782. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs index f98bf4ef5d1..5d607d82ea1 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs @@ -1,10 +1,10 @@ //@ edition:2021 fn function(x: &SomeTrait, y: Box) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait let _x: &SomeTrait = todo!(); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } trait SomeTrait {} diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr index 52ee6c81ab7..6d1a1618ac0 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr @@ -1,4 +1,4 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:17 | LL | fn function(x: &SomeTrait, y: Box) { @@ -17,24 +17,24 @@ help: alternatively, use a trait object to accept any type that implements `Some LL | fn function(x: &dyn SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:35 | LL | fn function(x: &SomeTrait, y: Box) { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn function(x: &SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:6:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | let _x: &dyn SomeTrait = todo!(); | +++ diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs index 19b5edb620f..bee15788da9 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -9,6 +9,7 @@ impl dyn Trait { fn main() { match () { Trait::CONST => {} - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| HELP you can add the `dyn` keyword if you want a trait object } } diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr index 4446a89b63b..6a2bb3ec09a 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 | LL | Trait::CONST => {} | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::CONST => {} | ++++ + diff --git a/tests/ui/editions/dyn-trait-sugg-2021.rs b/tests/ui/editions/dyn-trait-sugg-2021.rs index d702bfb2f88..a5364662600 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.rs +++ b/tests/ui/editions/dyn-trait-sugg-2021.rs @@ -8,5 +8,5 @@ impl dyn Foo { fn main() { Foo::hi(123); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr index 8a65fea11c9..3aea8ac491d 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.stderr +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); | ^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::hi(123); | ++++ + diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 7917fa991ee..1e268bc7f49 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -1,21 +1,14 @@ -error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied - --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 | LL | fn ice() -> impl AsRef { | ^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn ice() -> impl AsRef { | +++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 582386aa759..c71f794d5d1 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -5,8 +5,7 @@ fn ice() -> impl AsRef { //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] - //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] - //[edition2021]~| ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] todo!() } diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs index 79c6f67dadd..574e9870cd2 100644 --- a/tests/ui/resolve/issue-111312.rs +++ b/tests/ui/resolve/issue-111312.rs @@ -8,6 +8,5 @@ trait HasNot {} fn main() { HasNot::has(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `has` found for trait `HasNot` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 431802ead30..a1f8d6bc46c 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -1,27 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111312.rs:10:5 | LL | HasNot::has(); | ^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::has(); | ++++ + -error[E0599]: no function or associated item named `has` found for trait `HasNot` - --> $DIR/issue-111312.rs:10:13 - | -LL | HasNot::has(); - | ^^^ function or associated item not found in `HasNot` - | -note: `Has` defines an item `has` - --> $DIR/issue-111312.rs:3:1 - | -LL | trait Has { - | ^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs index fcab924b809..a5c2c0ca8c6 100644 --- a/tests/ui/resolve/issue-111727.rs +++ b/tests/ui/resolve/issue-111727.rs @@ -2,6 +2,5 @@ fn main() { std::any::Any::create(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `create` found for trait `Any` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 1ef5a1a1d5e..71ea989ac34 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -1,21 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111727.rs:4:5 | LL | std::any::Any::create(); | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::create(); | ++++ + -error[E0599]: no function or associated item named `create` found for trait `Any` - --> $DIR/issue-111727.rs:4:20 - | -LL | std::any::Any::create(); - | ^^^^^^ function or associated item not found in `Any` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs new file mode 100644 index 00000000000..e57e9ce4844 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs @@ -0,0 +1,15 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/125512 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +trait A { + fn concrete(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr new file mode 100644 index 00000000000..b8a9a5c8129 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:20 + | +LL | fn concrete(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn concrete(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn concrete(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:26 + | +LL | fn concrete(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn concrete(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs new file mode 100644 index 00000000000..055b11b4424 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs @@ -0,0 +1,16 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/120482 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn bar(&self, x: &Self); +} + +trait A { + fn g(new: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr new file mode 100644 index 00000000000..c0969570e92 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr @@ -0,0 +1,30 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:15 + | +LL | fn g(new: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(new: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(new: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:21 + | +LL | fn g(new: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(new: B) -> impl B; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.rs b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs new file mode 100644 index 00000000000..2b4f7bd088f --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs @@ -0,0 +1,12 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] +#![feature(unsized_fn_params)] + +fn guard(_s: Copy) -> bool { + //~^ ERROR: expected a type, found a trait + panic!() +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr new file mode 100644 index 00000000000..d35c8ab3e42 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr @@ -0,0 +1,19 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params-2.rs:7:14 + | +LL | fn guard(_s: Copy) -> bool { + | ^^^^ + | + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn guard(_s: T) -> bool { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn guard(_s: impl Copy) -> bool { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.rs b/tests/ui/rust-2021/ice-unsized-fn-params.rs new file mode 100644 index 00000000000..6d8c1c3f152 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +trait A { + fn g(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.stderr b/tests/ui/rust-2021/ice-unsized-fn-params.stderr new file mode 100644 index 00000000000..d56e9981a28 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:13 + | +LL | fn g(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:19 + | +LL | fn g(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs index 37afab6b643..10b4781eb04 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs @@ -2,24 +2,21 @@ #![allow(bare_trait_objects)] trait A: Sized { fn f(a: A) -> A; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` cannot be made into an object } trait B { fn f(b: B) -> B; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` cannot be made into an object } trait C { fn f(&self, c: C) -> C; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `C` cannot be made into an object } fn main() {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 53304382584..c0cfb18955c 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -11,22 +11,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | fn f(a: A) -> A; - | ^ `A` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:3:10 - | -LL | trait A: Sized { - | - ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | trait B { | - in this trait @@ -38,30 +24,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(b: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 - | -LL | fn f(b: B) -> B; - | ^ `B` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:8 - | -LL | trait B { - | - this trait cannot be made into an object... -LL | fn f(b: B) -> B; - | ^ ...because associated function `f` has no `self` parameter -help: consider turning `f` into a method by giving it a `&self` argument - | -LL | fn f(&self, b: B) -> B; - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects - | -LL | fn f(b: B) -> B where Self: Sized; - | +++++++++++++++++ - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | trait C { | - in this trait @@ -73,23 +37,7 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `C` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 - | -LL | fn f(&self, c: C) -> C; - | ----- ^ `C` cannot be made into an object - | | - | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:10 - | -LL | trait C { - | - this trait cannot be made into an object... -LL | fn f(&self, c: C) -> C; - | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; @@ -105,7 +53,7 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(a: impl A) -> A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:19 | LL | fn f(a: A) -> A; @@ -116,8 +64,8 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | fn f(b: B) -> B; | ^ @@ -132,8 +80,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(b: impl B) -> B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:19 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:19 | LL | fn f(b: B) -> B; | ^ @@ -143,8 +91,8 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -159,8 +107,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(&self, c: impl C) -> C; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:26 | LL | fn f(&self, c: C) -> C; | ^ @@ -170,7 +118,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0038, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 6feba3dc6c1..77cdfb8b614 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -3,7 +3,8 @@ trait Foo { type Clone; fn foo() -> Clone; - //~^ ERROR the trait `Clone` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } @@ -12,7 +13,8 @@ trait DbHandle: Sized {} trait DbInterface { type DbHandle; fn handle() -> DbHandle; - //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index 7f8cc147210..3853f03f1db 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -1,29 +1,28 @@ -error[E0038]: the trait `Clone` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/issue-116434-2021.rs:5:17 | LL | fn foo() -> Clone; - | ^^^^^ `Clone` cannot be made into an object + | ^^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +help: `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type + | +LL | fn foo() -> impl Clone; + | ++++ help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ -error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2021.rs:14:20 +error[E0782]: expected a type, found a trait + --> $DIR/issue-116434-2021.rs:15:20 | LL | fn handle() -> DbHandle; - | ^^^^^^^^ `DbHandle` cannot be made into an object + | ^^^^^^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-116434-2021.rs:10:17 +help: `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type | -LL | trait DbHandle: Sized {} - | -------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... +LL | fn handle() -> impl DbHandle; + | ++++ help: there is an associated type with the same name | LL | fn handle() -> Self::DbHandle; @@ -31,4 +30,4 @@ LL | fn handle() -> Self::DbHandle; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs index 76300c6a3f4..dd7e203abd7 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -11,48 +11,48 @@ trait LocalTraitTwo { } trait GenericTrait {} impl LocalTraitTwo for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` impl fmt::Display for LocalTraitOne { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl fmt::Display for LocalTraitTwo + Send { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl LocalTraitOne for fmt::Display {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` impl LocalTraitOne for fmt::Display + Send {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` impl GenericTrait for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` trait GenericTraitTwo {} impl GenericTraitTwo for GenericTrait {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` fn main() {} diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr index 769f3bd64f3..102438e1ec5 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 | LL | impl LocalTraitOne for fmt::Display {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display {} | +++ @@ -13,13 +13,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | +++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 | LL | impl LocalTraitOne for fmt::Display + Send {} | ^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display + Send {} | +++ @@ -28,13 +28,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | ++++++++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 | LL | impl LocalTraitTwo for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitTwo for dyn LocalTraitOne {} | +++ @@ -43,13 +43,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitTwo` fo LL | impl LocalTraitTwo for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 | LL | impl GenericTrait for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTrait for dyn LocalTraitOne {} | +++ @@ -58,35 +58,35 @@ help: alternatively use a blanket implementation to implement `GenericTrait` LL | impl GenericTrait for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 | LL | impl fmt::Display for LocalTraitOne { | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitOne { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 | LL | impl fmt::Display for LocalTraitTwo + Send { | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitTwo + Send { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 | LL | impl GenericTraitTwo for GenericTrait {} | ^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTraitTwo for dyn GenericTrait {} | +++ diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs index a5ab8be7f45..fe36d093430 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -14,14 +14,14 @@ pub union Union { impl<'a, T> Struct for Trait<'a, T> {} //~^ ERROR expected trait, found struct `Struct` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Enum for Trait<'a, T> {} //~^ ERROR expected trait, found enum `Enum` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Union for Trait<'a, T> {} //~^ ERROR expected trait, found union `Union` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr index 2893370570d..0bd601e2170 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -58,35 +58,35 @@ LL | pub union Union { = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:27 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:25 | LL | impl<'a, T> Enum for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Enum for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:26 | LL | impl<'a, T> Union for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Union for dyn Trait<'a, T> {} | +++ diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.rs b/tests/ui/traits/bound/not-on-bare-trait-2021.rs index 07b866cb4a6..93d2f04b54e 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.rs +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.rs @@ -6,13 +6,11 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait } fn bar(x: Foo) -> Foo { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait x } diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index e05ae8e5267..e50186aff7e 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -1,38 +1,4 @@ -error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:8:12 - | -LL | fn foo(_x: Foo + Send) { - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + - -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:12:11 - | -LL | fn bar(x: Foo) -> Foo { - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn bar(x: impl Foo) -> Foo { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn bar(x: &dyn Foo) -> Foo { - | ++++ - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/not-on-bare-trait-2021.rs:8:12 | LL | fn foo(_x: Foo + Send) { @@ -51,8 +17,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:11 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:11 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -70,8 +36,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo` LL | fn bar(x: &dyn Foo) -> Foo { | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:19 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:19 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -85,7 +51,6 @@ help: alternatively, you can return an owned trait object LL | fn bar(x: Foo) -> Box { | +++++++ + -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 8adbac46a5b..696bd765ebc 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] //~ trait objects must include the `dyn` keyword -//~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known -//~| ERROR: return type cannot have an unboxed trait object +#[derive(Clone)] //~ expected a type, found a trait struct Foo; trait Foo {} //~ the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 6476c8b3237..4a48e4e898d 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -8,26 +8,7 @@ LL | trait Foo {} | = note: `Foo` must be defined only once in the type namespace of this module -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` -note: required by a bound in `Clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] @@ -35,7 +16,7 @@ LL | #[derive(Clone)] | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0428, E0746, E0782. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr index b5a607a54cb..a49c5d9d45b 100644 --- a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr +++ b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr @@ -10,13 +10,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^^^^ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/missing-for-type-in-impl.rs:8:6 | LL | impl Foo { | ^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl dyn Foo { | +++ diff --git a/tests/ui/traits/missing-for-type-in-impl.rs b/tests/ui/traits/missing-for-type-in-impl.rs index 7d4ad479e77..e5dd3651609 100644 --- a/tests/ui/traits/missing-for-type-in-impl.rs +++ b/tests/ui/traits/missing-for-type-in-impl.rs @@ -6,7 +6,7 @@ trait Foo { /* note the "missing" for ... (in this case for i64, in order for this to compile) */ impl Foo { -//[e2021]~^ ERROR trait objects must include the `dyn` keyword +//[e2021]~^ ERROR expected a type, found a trait //[e2015]~^^ WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -- cgit 1.4.1-3-g733a5 From 0d8a978e8a55b08778ec6ee861c2c5ed6703eb6c Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Fri, 5 Jan 2024 21:04:41 -0700 Subject: intrinsics.fmuladdf{16,32,64,128}: expose llvm.fmuladd.* semantics Add intrinsics `fmuladd{f16,f32,f64,f128}`. This computes `(a * b) + c`, to be fused if the code generator determines that (i) the target instruction set has support for a fused operation, and (ii) that the fused operation is more efficient than the equivalent, separate pair of `mul` and `add` instructions. https://llvm.org/docs/LangRef.html#llvm-fmuladd-intrinsic MIRI support is included for f32 and f64. The codegen_cranelift uses the `fma` function from libc, which is a correct implementation, but without the desired performance semantic. I think this requires an update to cranelift to expose a suitable instruction in its IR. I have not tested with codegen_gcc, but it should behave the same way (using `fma` from libc). --- .../rustc_codegen_cranelift/src/intrinsics/mod.rs | 5 +- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 3 ++ compiler/rustc_codegen_llvm/src/context.rs | 5 ++ compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ++ compiler/rustc_hir_analysis/src/check/intrinsic.rs | 13 ++++++ compiler/rustc_span/src/symbol.rs | 4 ++ library/core/src/intrinsics.rs | 53 ++++++++++++++++++++++ src/tools/miri/src/intrinsics/mod.rs | 31 +++++++++++++ src/tools/miri/tests/pass/float.rs | 18 ++++++++ .../pass/intrinsics/fmuladd_nondeterministic.rs | 44 ++++++++++++++++++ tests/ui/intrinsics/intrinsic-fmuladd.rs | 42 +++++++++++++++++ 11 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs create mode 100644 tests/ui/intrinsics/intrinsic-fmuladd.rs (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 19e5adc2538..35f0ccff3f9 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -328,6 +328,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64 sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), @@ -381,7 +384,7 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { - sym::fmaf32 | sym::fmaf64 => { + sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 945eedf5556..972d6632140 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -66,6 +66,9 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0a116971e07..c836dd5473f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -884,6 +884,11 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fmuladd.f16", fn(t_f16, t_f16, t_f16) -> t_f16); + ifn!("llvm.fmuladd.f32", fn(t_f32, t_f32, t_f32) -> t_f32); + ifn!("llvm.fmuladd.f64", fn(t_f64, t_f64, t_f64) -> t_f64); + ifn!("llvm.fmuladd.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 30c6f08e894..bfe623e7fc3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -86,6 +86,11 @@ fn get_simple_intrinsic<'ll>( sym::fmaf64 => "llvm.fma.f64", sym::fmaf128 => "llvm.fma.f128", + sym::fmuladdf16 => "llvm.fmuladd.f16", + sym::fmuladdf32 => "llvm.fmuladd.f32", + sym::fmuladdf64 => "llvm.fmuladd.f64", + sym::fmuladdf128 => "llvm.fmuladd.f128", + sym::fabsf16 => "llvm.fabs.f16", sym::fabsf32 => "llvm.fabs.f32", sym::fabsf64 => "llvm.fabs.f64", diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 25e219ef3f2..06317a3b304 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -357,6 +357,19 @@ pub fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } + sym::fmuladdf16 => { + (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16) + } + sym::fmuladdf32 => { + (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32) + } + sym::fmuladdf64 => { + (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64) + } + sym::fmuladdf128 => { + (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) + } + sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db..cc3bda99a11 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -914,6 +914,10 @@ symbols! { fmt_debug, fmul_algebraic, fmul_fast, + fmuladdf128, + fmuladdf16, + fmuladdf32, + fmuladdf64, fn_align, fn_delegation, fn_must_use, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909ca..061fba9a1f7 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1795,6 +1795,59 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; + /// Returns `a * b + c` for `f16` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; + /// Returns `a * b + c` for `f32` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; + /// Returns `a * b + c` for `f64` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; + /// Returns `a * b + c` for `f128` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; + /// Returns the absolute value of an `f16`. /// /// The stabilized version of this intrinsic is diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 665dd7c441a..9f772cfa982 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -295,6 +295,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + "fmuladdf32" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f32()?; + let b = this.read_scalar(b)?.to_f32()?; + let c = this.read_scalar(c)?.to_f32()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "fmuladdf64" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f64()?; + let b = this.read_scalar(b)?.to_f64()?; + let c = this.read_scalar(c)?.to_f64()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "powf32" => { let [f1, f2] = check_arg_count(args)?; let f1 = this.read_scalar(f1)?.to_f32()?; diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 6ab18a5345e..853d3e80517 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -30,6 +30,7 @@ fn main() { libm(); test_fast(); test_algebraic(); + test_fmuladd(); } trait Float: Copy + PartialEq + Debug { @@ -1041,3 +1042,20 @@ fn test_algebraic() { test_operations_f32(11., 2.); test_operations_f32(10., 15.); } + +fn test_fmuladd() { + use std::intrinsics::{fmuladdf32, fmuladdf64}; + + #[inline(never)] + pub fn test_operations_f32(a: f32, b: f32, c: f32) { + assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c); + } + + #[inline(never)] + pub fn test_operations_f64(a: f64, b: f64, c: f64) { + assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c); + } + + test_operations_f32(0.1, 0.2, 0.3); + test_operations_f64(1.1, 1.2, 1.3); +} diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs new file mode 100644 index 00000000000..b46cf1ddf65 --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -0,0 +1,44 @@ +#![feature(core_intrinsics)] +use std::intrinsics::{fmuladdf32, fmuladdf64}; + +fn main() { + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = unsafe { fmuladdf64(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf64` failed to be evaluated as both fused and unfused" + ); + + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = unsafe { fmuladdf32(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf32` failed to be evaluated as both fused and unfused" + ); +} diff --git a/tests/ui/intrinsics/intrinsic-fmuladd.rs b/tests/ui/intrinsics/intrinsic-fmuladd.rs new file mode 100644 index 00000000000..d03297884f7 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-fmuladd.rs @@ -0,0 +1,42 @@ +//@ run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + }}; +} + +fn main() { + unsafe { + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + assert_approx_eq!(fmuladdf32(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf32(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf32(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf32(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf32(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf32(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf32(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf32(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf32(-3.2, 2.4, neg_inf), neg_inf); + } + unsafe { + let nan: f64 = f64::NAN; + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = f64::NEG_INFINITY; + assert_approx_eq!(fmuladdf64(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf64(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf64(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf64(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf64(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf64(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf64(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf64(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf64(-3.2, 2.4, neg_inf), neg_inf); + } +} -- cgit 1.4.1-3-g733a5 From 7ec06b0d1d08cbcc6ed2f7e6ae87fe18056f69ef Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Wed, 9 Oct 2024 01:02:55 +0100 Subject: Swap Vec to type alias --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- .../src/obligation_forest/mod.rs | 3 +- compiler/rustc_hir_analysis/src/autoderef.rs | 11 ++-- compiler/rustc_hir_typeck/src/autoderef.rs | 5 +- compiler/rustc_hir_typeck/src/closure.rs | 4 +- compiler/rustc_hir_typeck/src/coercion.rs | 33 +++++------ .../src/fn_ctxt/inspect_obligations.rs | 13 ++--- compiler/rustc_hir_typeck/src/method/mod.rs | 3 +- .../src/infer/canonical/query_response.rs | 7 ++- compiler/rustc_infer/src/infer/mod.rs | 10 ++-- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 8 +-- compiler/rustc_infer/src/infer/projection.rs | 4 +- compiler/rustc_infer/src/infer/relate/lattice.rs | 8 +-- .../rustc_infer/src/infer/relate/type_relating.rs | 8 +-- compiler/rustc_infer/src/traits/engine.rs | 10 ++-- compiler/rustc_infer/src/traits/mod.rs | 2 + compiler/rustc_infer/src/traits/project.rs | 6 +- .../src/error_reporting/mod.rs | 7 +-- .../rustc_trait_selection/src/solve/fulfill.rs | 17 +++--- .../rustc_trait_selection/src/traits/coherence.rs | 9 +-- .../rustc_trait_selection/src/traits/engine.rs | 3 +- .../rustc_trait_selection/src/traits/fulfill.rs | 54 +++++++++++------- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- .../rustc_trait_selection/src/traits/normalize.rs | 14 ++--- .../src/traits/outlives_bounds.rs | 2 +- .../rustc_trait_selection/src/traits/project.rs | 63 +++++++++++---------- .../src/traits/query/normalize.rs | 14 +++-- .../src/traits/query/type_op/mod.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 6 +- .../src/traits/select/confirmation.rs | 65 +++++++++++----------- .../rustc_trait_selection/src/traits/select/mod.rs | 20 +++---- compiler/rustc_trait_selection/src/traits/wf.rs | 39 +++++++------ .../rustc_traits/src/normalize_projection_ty.rs | 5 +- 33 files changed, 250 insertions(+), 215 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 82aeca66693..238d7d0749a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -18,6 +18,7 @@ use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::{ BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, }; +use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -40,7 +41,6 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; -use rustc_trait_selection::traits::PredicateObligation; use rustc_trait_selection::traits::query::type_op::custom::{ CustomTypeOp, scrape_region_constraints, }; @@ -2940,7 +2940,7 @@ impl NormalizeLocation for Location { pub(super) struct InstantiateOpaqueType<'tcx> { pub base_universe: Option, pub region_constraints: Option>, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> { diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index cfe7dd13e80..aca99b9fab1 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -402,9 +402,10 @@ impl ObligationForest { } /// Returns the set of obligations that are in a pending state. - pub fn map_pending_obligations(&self, f: F) -> Vec

+ pub fn map_pending_obligations(&self, f: F) -> R where F: Fn(&O) -> P, + R: FromIterator

, { self.nodes .iter() diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 8d11328743c..5a66c31a0cc 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,4 +1,5 @@ use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Limit; use rustc_span::Span; @@ -23,7 +24,7 @@ struct AutoderefSnapshot<'tcx> { reached_recursion_limit: bool, steps: Vec<(Ty<'tcx>, AutoderefKind)>, cur_ty: Ty<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } pub struct Autoderef<'a, 'tcx> { @@ -119,7 +120,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { state: AutoderefSnapshot { steps: vec![], cur_ty: infcx.resolve_vars_if_possible(base_ty), - obligations: vec![], + obligations: PredicateObligations::new(), at_start: true, reached_recursion_limit: false, }, @@ -165,7 +166,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn structurally_normalize( &self, ty: Ty<'tcx>, - ) -> Option<(Ty<'tcx>, Vec>)> { + ) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> { let ocx = ObligationCtxt::new(self.infcx); let Ok(normalized_ty) = ocx.structurally_normalize( &traits::ObligationCause::misc(self.span, self.body_id), @@ -204,11 +205,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self.state.steps.len() } - pub fn into_obligations(self) -> Vec> { + pub fn into_obligations(self) -> PredicateObligations<'tcx> { self.state.obligations } - pub fn current_obligations(&self) -> Vec> { + pub fn current_obligations(&self) -> PredicateObligations<'tcx> { self.state.obligations.clone() } diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index d2d6da8f32b..e4ca1cee757 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -5,6 +5,7 @@ use std::iter; use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; +use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -36,10 +37,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> InferOk<'tcx, Vec>> { let steps = autoderef.steps(); if steps.is_empty() { - return InferOk { obligations: vec![], value: vec![] }; + return InferOk { obligations: PredicateObligations::new(), value: vec![] }; } - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); let steps: Vec<_> = steps diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fcaa5751152..fd6ac7de14a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult}; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::span_bug; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; @@ -805,7 +805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // [c1]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341089706 // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796 self.commit_if_ok(|_| { - let mut all_obligations = vec![]; + let mut all_obligations = PredicateObligations::new(); let supplied_sig = self.instantiate_binder_with_fresh_vars( self.tcx.def_span(expr_def_id), BoundRegionConversionTime::FnCall, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bd0b9870298..f81bc727aa1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,6 +46,7 @@ use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{ IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation, + PredicateObligations, }; use rustc_middle::lint::in_external_macro; use rustc_middle::span_bug; @@ -120,7 +121,7 @@ fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec( adj: Vec>, target: Ty<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, ) -> CoerceResult<'tcx> { Ok(InferOk { value: (adj, target), obligations }) } @@ -184,7 +185,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { if self.coerce_never { - return success(simple(Adjust::NeverToAny)(b), b, vec![]); + return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); } else { // Otherwise the only coercion we can do is unification. return self.unify_and(a, b, identity); @@ -278,7 +279,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Two unresolved type variables: create a `Coerce` predicate. let target_ty = if self.use_lub { self.next_ty_var(self.cause.span) } else { b }; - let mut obligations = Vec::with_capacity(2); + let mut obligations = PredicateObligations::with_capacity(2); for &source_ty in &[a, b] { if source_ty != target_ty { obligations.push(Obligation::new( @@ -744,7 +745,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Check the obligations of the cast -- for example, when casting // `usize` to `dyn* Clone + 'static`: - let mut obligations: Vec<_> = predicates + let obligations = predicates .iter() .map(|predicate| { // For each existential predicate (e.g., `?Self: Clone`) instantiate @@ -764,21 +765,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::OutlivesPredicate(a, b_region), ))), ), + // Enforce that the type is `usize`/pointer-sized. + Obligation::new( + self.tcx, + self.cause.clone(), + self.param_env, + ty::TraitRef::new( + self.tcx, + self.tcx + .require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)), + [a], + ), + ), ]) .collect(); - // Enforce that the type is `usize`/pointer-sized. - obligations.push(Obligation::new( - self.tcx, - self.cause.clone(), - self.param_env, - ty::TraitRef::new( - self.tcx, - self.tcx.require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)), - [a], - ), - )); - Ok(InferOk { value: ( vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }], diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index 2aad9a043f9..693cb4465cc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,6 +1,6 @@ //! A utility module to inspect currently ambiguous obligations in the current context. -use rustc_infer::traits::{self, ObligationCause}; +use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; @@ -15,10 +15,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a list of all obligations whose self type has been unified /// with the unconstrained type `self_ty`. #[instrument(skip(self), level = "debug")] - pub(crate) fn obligations_for_self_ty( - &self, - self_ty: ty::TyVid, - ) -> Vec> { + pub(crate) fn obligations_for_self_ty(&self, self_ty: ty::TyVid) -> PredicateObligations<'tcx> { if self.next_trait_solver() { self.obligations_for_self_ty_next(self_ty) } else { @@ -75,10 +72,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn obligations_for_self_ty_next( &self, self_ty: ty::TyVid, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let obligations = self.fulfillment_cx.borrow().pending_obligations(); debug!(?obligations); - let mut obligations_for_self_ty = vec![]; + let mut obligations_for_self_ty = PredicateObligations::new(); for obligation in obligations { let mut visitor = NestedObligationsForSelfTy { fcx: self, @@ -103,7 +100,7 @@ struct NestedObligationsForSelfTy<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, self_ty: ty::TyVid, root_cause: &'a ObligationCause<'tcx>, - obligations_for_self_ty: &'a mut Vec>, + obligations_for_self_ty: &'a mut PredicateObligations<'tcx>, } impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index cb8b1df2c6e..2de5947b16f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ @@ -412,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); // FIXME(effects): revisit when binops get `#[const_trait]` diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 7791bd73628..1d3d32ef749 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -28,7 +28,8 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; use crate::traits::query::NoSolution; use crate::traits::{ - Obligation, ObligationCause, PredicateObligation, ScrubbedTraitError, TraitEngine, + Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError, + TraitEngine, }; impl<'tcx> InferCtxt<'tcx> { @@ -493,7 +494,7 @@ impl<'tcx> InferCtxt<'tcx> { ), }; - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); // Carry all newly resolved opaque types to the caller's scope for &(a, b) in &query_response.value.opaque_types { @@ -598,7 +599,7 @@ impl<'tcx> InferCtxt<'tcx> { variables1: &OriginalQueryValues<'tcx>, variables2: impl Fn(BoundVar) -> GenericArg<'tcx>, ) -> InferResult<'tcx, ()> { - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); for (index, value1) in variables1.var_values.iter().enumerate() { let value2 = variables2(BoundVar::new(index)); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index bc813305ba4..7ef714475fc 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -50,7 +50,9 @@ use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; use crate::infer::region_constraints::UndoLog; -use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; +use crate::traits::{ + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, +}; pub mod at; pub mod canonical; @@ -68,7 +70,7 @@ pub(crate) mod snapshot; mod type_variable; /// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper -/// around `Vec>`, but it has one important property: +/// around `PredicateObligations<'tcx>`, but it has one important property: /// because `InferOk` is marked with `#[must_use]`, if you have a method /// `InferCtxt::f` that returns `InferResult<'tcx, ()>` and you call it with /// `infcx.f()?;` you'll get a warning about the obligations being discarded @@ -78,7 +80,7 @@ mod type_variable; #[derive(Debug)] pub struct InferOk<'tcx, T> { pub value: T, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } pub type InferResult<'tcx, T> = Result, TypeError<'tcx>>; @@ -658,7 +660,7 @@ impl<'tcx, T> InferOk<'tcx, T> { } impl<'tcx> InferOk<'tcx, ()> { - pub fn into_obligations(self) -> Vec> { + pub fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 365ddaba138..853ae6d2641 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -16,7 +16,7 @@ use tracing::{debug, instrument}; use super::DefineOpaqueTypes; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; -use crate::traits::{self, Obligation}; +use crate::traits::{self, Obligation, PredicateObligations}; mod table; @@ -46,14 +46,14 @@ impl<'tcx> InferCtxt<'tcx> { ) -> InferOk<'tcx, T> { // We handle opaque types differently in the new solver. if self.next_trait_solver() { - return InferOk { value, obligations: vec![] }; + return InferOk { value, obligations: PredicateObligations::new() }; } if !value.has_opaque_types() { - return InferOk { value, obligations: vec![] }; + return InferOk { value, obligations: PredicateObligations::new() }; } - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index b78f9d49268..1bee9632110 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -2,7 +2,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty}; use super::InferCtxt; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; impl<'tcx> InferCtxt<'tcx> { /// Instead of normalizing an associated type projection, @@ -17,7 +17,7 @@ impl<'tcx> InferCtxt<'tcx> { projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Ty<'tcx> { debug_assert!(!self.next_trait_solver()); let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id)); diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 7eb61abfbc1..4eb77a99be7 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -27,7 +27,7 @@ use tracing::{debug, instrument}; use super::StructurallyRelateAliases; use super::combine::PredicateEmittingRelation; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; #[derive(Clone, Copy)] pub(crate) enum LatticeOpKind { @@ -52,7 +52,7 @@ pub(crate) struct LatticeOp<'infcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, // Mutable fields kind: LatticeOpKind, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { @@ -62,10 +62,10 @@ impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, kind: LatticeOpKind, ) -> LatticeOp<'infcx, 'tcx> { - LatticeOp { infcx, trace, param_env, kind, obligations: vec![] } + LatticeOp { infcx, trace, param_env, kind, obligations: PredicateObligations::new() } } - pub(crate) fn into_obligations(self) -> Vec> { + pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 35103c070c2..009271a8378 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -11,7 +11,7 @@ use tracing::{debug, instrument}; use crate::infer::BoundRegionConversionTime::HigherRankedType; use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases}; use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; -use crate::traits::{Obligation, PredicateObligation}; +use crate::traits::{Obligation, PredicateObligations}; /// Enforce that `a` is equal to or a subtype of `b`. pub(crate) struct TypeRelating<'infcx, 'tcx> { @@ -24,7 +24,7 @@ pub(crate) struct TypeRelating<'infcx, 'tcx> { // Mutable fields. ambient_variance: ty::Variance, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. @@ -65,12 +65,12 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { param_env, define_opaque_types, ambient_variance, - obligations: vec![], + obligations: PredicateObligations::new(), cache: Default::default(), } } - pub(crate) fn into_obligations(self) -> Vec> { + pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> { self.obligations } } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index a076cdad672..ba1516655b0 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Ty, Upcast}; -use super::{ObligationCause, PredicateObligation}; +use super::{ObligationCause, PredicateObligation, PredicateObligations}; use crate::infer::InferCtxt; use crate::traits::Obligation; @@ -20,7 +20,7 @@ pub enum ScrubbedTraitError<'tcx> { /// An ambiguity. This goal may hold if further inference is done. Ambiguity, /// An old-solver-style cycle error, which will fatal. - Cycle(Vec>), + Cycle(PredicateObligations<'tcx>), } impl<'tcx> ScrubbedTraitError<'tcx> { @@ -62,7 +62,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, ) { for obligation in obligations { self.register_predicate_obligation(infcx, obligation); @@ -84,7 +84,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { self.collect_remaining_errors(infcx) } - fn pending_obligations(&self) -> Vec>; + fn pending_obligations(&self) -> PredicateObligations<'tcx>; /// Among all pending obligations, collect those are stalled on a inference variable which has /// changed since the last call to `select_where_possible`. Those obligations are marked as @@ -92,7 +92,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { fn drain_unstalled_obligations( &mut self, infcx: &InferCtxt<'tcx>, - ) -> Vec>; + ) -> PredicateObligations<'tcx>; } pub trait FromSolverError<'tcx, E>: Debug + 'tcx { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 34b0fe3e967..2d02391c57a 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -84,6 +84,8 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +pub type PredicateObligations<'tcx> = Vec>; + impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. /// diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 64b72de3986..cab2ce9f5a0 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -6,7 +6,7 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty; use tracing::{debug, info}; -use super::PredicateObligation; +use super::PredicateObligations; use crate::infer::snapshot::undo_log::InferCtxtUndoLogs; pub(crate) type UndoLog<'tcx> = @@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> { #[derive(Clone)] pub struct Normalized<'tcx, T> { pub value: T, - pub obligations: Vec>, + pub obligations: PredicateObligations<'tcx>, } pub type NormalizedTerm<'tcx> = Normalized<'tcx, ty::Term<'tcx>>; @@ -191,7 +191,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); let mut ty = ty.clone(); if result.must_apply_considering_regions() { - ty.obligations = vec![]; + ty.obligations = PredicateObligations::new(); } map.insert(key, ProjectionCacheEntry::NormalizedTerm { ty, diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index cb7efeaae0b..82695688ae8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use rustc_errors::DiagCtxtHandle; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::PredicateObligation; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::ty::{self, Ty}; @@ -28,8 +28,7 @@ pub struct TypeErrCtxt<'a, 'tcx> { pub normalize_fn_sig: Box) -> ty::PolyFnSig<'tcx> + 'a>, - pub autoderef_steps: - Box) -> Vec<(Ty<'tcx>, Vec>)> + 'a>, + pub autoderef_steps: Box) -> Vec<(Ty<'tcx>, PredicateObligations<'tcx>)> + 'a>, } #[extension(pub trait InferCtxtErrorExt<'tcx>)] @@ -45,7 +44,7 @@ impl<'tcx> InferCtxt<'tcx> { normalize_fn_sig: Box::new(|fn_sig| fn_sig), autoderef_steps: Box::new(|ty| { debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck"); - vec![(ty, vec![])] + vec![(ty, PredicateObligations::new())] }), } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 081d7a6a769..8ec4427091d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -7,7 +7,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, + ObligationCauseCode, PredicateObligation, PredicateObligations, SelectionError, TraitEngine, }; use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -49,8 +49,8 @@ struct ObligationStorage<'tcx> { /// We cannot eagerly return these as error so we instead store them here /// to avoid recomputing them each time `select_where_possible` is called. /// This also allows us to return the correct `FulfillmentError` for them. - overflowed: Vec>, - pending: Vec>, + overflowed: PredicateObligations<'tcx>, + pending: PredicateObligations<'tcx>, } impl<'tcx> ObligationStorage<'tcx> { @@ -58,13 +58,13 @@ impl<'tcx> ObligationStorage<'tcx> { self.pending.push(obligation); } - fn clone_pending(&self) -> Vec> { + fn clone_pending(&self) -> PredicateObligations<'tcx> { let mut obligations = self.pending.clone(); obligations.extend(self.overflowed.iter().cloned()); obligations } - fn take_pending(&mut self) -> Vec> { + fn take_pending(&mut self) -> PredicateObligations<'tcx> { let mut obligations = mem::take(&mut self.pending); obligations.append(&mut self.overflowed); obligations @@ -197,14 +197,11 @@ where errors } - fn pending_obligations(&self) -> Vec> { + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } - fn drain_unstalled_obligations( - &mut self, - _: &InferCtxt<'tcx>, - ) -> Vec> { + fn drain_unstalled_obligations(&mut self, _: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> { self.obligations.take_pending() } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index b29e41beab5..f4a2483cebf 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,6 +11,7 @@ use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; @@ -279,7 +280,7 @@ fn equate_impl_headers<'tcx>( param_env: ty::ParamEnv<'tcx>, impl1: &ty::ImplHeader<'tcx>, impl2: &ty::ImplHeader<'tcx>, -) -> Option>> { +) -> Option> { let result = match (impl1.trait_ref, impl2.trait_ref) { (Some(impl1_ref), Some(impl2_ref)) => infcx @@ -491,7 +492,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } else { ty.super_visit_with(self); } @@ -514,7 +515,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } else { ct.super_visit_with(self); } @@ -545,7 +546,7 @@ fn plug_infer_with_placeholders<'tcx>( else { bug!("we always expect to be able to plug an infer var with placeholder") }; - assert_eq!(obligations, &[]); + assert_eq!(obligations.len(), 0); } } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d562692c1a8..eda3f6e8023 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -10,6 +10,7 @@ use rustc_infer::infer::canonical::{ }; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError, TypeTrace}; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; @@ -208,7 +209,7 @@ where /// getting ignored. You can make a new `ObligationCtxt` if this /// needs to be done in a loop, for example. #[must_use] - pub fn into_pending_obligations(self) -> Vec> { + pub fn into_pending_obligations(self) -> PredicateObligations<'tcx> { self.engine.borrow().pending_obligations() } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 33b8cf03701..3e3834a11c6 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,8 @@ use rustc_data_structures::obligation_forest::{ }; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::{ - FromSolverError, PolyTraitObligation, ProjectionCacheKey, SelectionError, TraitEngine, + FromSolverError, PolyTraitObligation, PredicateObligations, ProjectionCacheKey, SelectionError, + TraitEngine, }; use rustc_middle::bug; use rustc_middle::mir::interpret::ErrorHandled; @@ -27,6 +28,8 @@ use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; +pub(crate) type PendingPredicateObligations<'tcx> = Vec>; + impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// Note that we include both the `ParamEnv` and the `Predicate`, /// as the `ParamEnv` can influence whether fulfillment succeeds @@ -161,15 +164,16 @@ where fn drain_unstalled_obligations( &mut self, infcx: &InferCtxt<'tcx>, - ) -> Vec> { - let mut processor = DrainProcessor { removed_predicates: Vec::new(), infcx }; + ) -> PredicateObligations<'tcx> { + let mut processor = + DrainProcessor { removed_predicates: PredicateObligations::new(), infcx }; let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor); assert!(outcome.errors.is_empty()); return processor.removed_predicates; struct DrainProcessor<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, - removed_predicates: Vec>, + removed_predicates: PredicateObligations<'tcx>, } impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> { @@ -190,7 +194,7 @@ where ) -> ProcessResult, !> { assert!(self.needs_process_obligation(pending_obligation)); self.removed_predicates.push(pending_obligation.obligation.clone()); - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } fn process_backedge<'c, I>( @@ -207,7 +211,7 @@ where } } - fn pending_obligations(&self) -> Vec> { + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } } @@ -216,7 +220,7 @@ struct FulfillProcessor<'a, 'tcx> { selcx: SelectionContext<'a, 'tcx>, } -fn mk_pending(os: Vec>) -> Vec> { +fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> { os.into_iter() .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) .collect() @@ -321,7 +325,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; if obligation.predicate.has_aliases() { - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let predicate = normalize_with_depth_to( &mut self.selcx, obligation.param_env, @@ -369,7 +373,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); - ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) + let mut obligations = PredicateObligations::with_capacity(1); + obligations.push(obligation.with(infcx.tcx, pred)); + + ProcessResult::Changed(mk_pending(obligations)) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::NormalizesTo(..) => { @@ -395,7 +402,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)); } - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( @@ -405,7 +412,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if infcx.considering_regions { infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause); } - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => { @@ -422,7 +429,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { if !self.selcx.tcx().is_dyn_compatible(trait_def_id) { ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented)) } else { - ProcessResult::Changed(vec![]) + ProcessResult::Changed(Default::default()) } } @@ -451,7 +458,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { pending_obligation.stalled_on.extend([var]); return ProcessResult::Unchanged; } - ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]), + ty::ConstKind::Error(_) => { + return ProcessResult::Changed(PendingPredicateObligations::new()); + } ty::ConstKind::Value(ty, _) => ty, ty::ConstKind::Unevaluated(uv) => { infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) @@ -460,7 +469,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // `>::Output` when this is an `Expr` representing // `lhs + rhs`. ty::ConstKind::Expr(_) => { - return ProcessResult::Changed(mk_pending(vec![])); + return ProcessResult::Changed(mk_pending(PredicateObligations::new())); } ty::ConstKind::Placeholder(_) => { bug!("placeholder const {:?} in old solver", ct) @@ -568,7 +577,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { obligation.param_env, obligation.cause.span, ) { - Ok(()) => ProcessResult::Changed(vec![]), + Ok(()) => ProcessResult::Changed(Default::default()), Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( @@ -722,7 +731,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("process_child_obligations: coinductive match"); Ok(()) } else { - let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); + let cycle = cycle.map(|c| c.obligation.clone()).collect(); Err(FulfillmentErrorCode::Cycle(cycle)) } } @@ -745,7 +754,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { "selecting trait at depth {} evaluated to holds", obligation.recursion_depth ); - return ProcessResult::Changed(vec![]); + return ProcessResult::Changed(Default::default()); } } @@ -809,7 +818,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { .projection_cache() .complete(key, EvaluationResult::EvaluatedToOk); } - return ProcessResult::Changed(vec![]); + return ProcessResult::Changed(Default::default()); } else { debug!("Does NOT hold: {:?}", obligation); } @@ -826,9 +835,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { ProcessResult::Unchanged } // Let the caller handle the recursion - ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![ - project_obligation.with(tcx, project_obligation.predicate), - ])), + ProjectAndUnifyResult::Recursive => { + let mut obligations = PredicateObligations::with_capacity(1); + obligations.push(project_obligation.with(tcx, project_obligation.predicate)); + + ProcessResult::Changed(mk_pending(obligations)) + } ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProcessResult::Error(FulfillmentErrorCode::Project(e)) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 655bef0bab7..0fb795fc184 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -114,7 +114,7 @@ impl<'tcx> Debug for FulfillmentError<'tcx> { pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only /// if it is already implemented. - Cycle(Vec>), + Cycle(PredicateObligations<'tcx>), Select(SelectionError<'tcx>), Project(MismatchedProjectionTypes<'tcx>), Subtype(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index a7130cbd28f..7eac3559348 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -4,7 +4,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::InferOk; use rustc_infer::infer::at::At; use rustc_infer::traits::{ - FromSolverError, Normalized, Obligation, PredicateObligation, TraitEngine, + FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; use rustc_macros::extension; use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal}; @@ -29,7 +29,7 @@ impl<'tcx> At<'_, 'tcx> { /// projection may be fallible. fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { if self.infcx.next_trait_solver() { - InferOk { value, obligations: Vec::new() } + InferOk { value, obligations: PredicateObligations::new() } } else { let mut selcx = SelectionContext::new(self.infcx); let Normalized { value, obligations } = @@ -83,7 +83,7 @@ pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>( where T: TypeFoldable>, { - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations); Normalized { value, obligations } } @@ -95,14 +95,14 @@ pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>( cause: ObligationCause<'tcx>, depth: usize, value: T, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> T where T: TypeFoldable>, { debug!(obligations.len = obligations.len()); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); - let result = ensure_sufficient_stack(|| normalizer.fold(value)); + let result = ensure_sufficient_stack(|| AssocTypeNormalizer::fold(&mut normalizer, value)); debug!(?result, obligations.len = normalizer.obligations.len()); debug!(?normalizer.obligations,); result @@ -128,7 +128,7 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> { selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, - obligations: &'a mut Vec>, + obligations: &'a mut PredicateObligations<'tcx>, depth: usize, universes: Vec>, } @@ -139,7 +139,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &'a mut Vec>, + obligations: &'a mut PredicateObligations<'tcx>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { debug_assert!(!selcx.infcx.next_trait_solver()); AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index f1faff2c036..339e4bf1f22 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -77,7 +77,7 @@ fn implied_outlives_bounds<'a, 'tcx>( else { return vec![]; }; - assert_eq!(&obligations, &[]); + assert_eq!(obligations.len(), 0); // Because of #109628, we may have unexpected placeholders. Ignore them! // FIXME(#109628): panic in this case once the issue is fixed. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9cd99d99fc3..7f7c9bced18 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -9,7 +9,7 @@ use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; pub use rustc_middle::traits::Reveal; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; @@ -146,7 +146,7 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { /// of the old return type, which was: /// ```ignore (not-rust) /// Result< -/// Result>>, InProgress>, +/// Result>, InProgress>, /// MismatchedProjectionTypes<'tcx>, /// > /// ``` @@ -155,7 +155,7 @@ pub(super) enum ProjectAndUnifyResult<'tcx> { /// projection cannot be normalized because the required trait bound does /// not hold, this is returned, with `obligations` being a predicate that /// cannot be proven. - Holds(Vec>), + Holds(PredicateObligations<'tcx>), /// The projection cannot be normalized due to ambiguity. Resolving some /// inference variables in the projection may fix this. FailedNormalization, @@ -231,7 +231,7 @@ fn project_and_unify_term<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionObligation<'tcx>, ) -> ProjectAndUnifyResult<'tcx> { - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let infcx = selcx.infcx; let normalized = match opt_normalize_projection_term( @@ -289,7 +289,7 @@ pub fn normalize_projection_ty<'a, 'b, 'tcx>( projection_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Term<'tcx> { opt_normalize_projection_term( selcx, @@ -330,7 +330,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( projection_term: ty::AliasTerm<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Result>, InProgress> { let infcx = selcx.infcx; debug_assert!(!selcx.infcx.next_trait_solver()); @@ -452,7 +452,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( Ok(Some(result.value)) } Ok(Projected::NoProgress(projected_ty)) => { - let result = Normalized { value: projected_ty, obligations: vec![] }; + let result = + Normalized { value: projected_ty, obligations: PredicateObligations::new() }; if use_cache { infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); } @@ -519,13 +520,14 @@ fn normalize_to_error<'a, 'tcx>( selcx.infcx.next_const_var(cause.span).into() } }; - let trait_obligation = Obligation { + let mut obligations = PredicateObligations::new(); + obligations.push(Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.upcast(selcx.tcx()), - }; - Normalized { value: new_value, obligations: vec![trait_obligation] } + }); + Normalized { value: new_value, obligations } } /// Confirm and normalize the given inherent projection. @@ -536,7 +538,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> Ty<'tcx> { let tcx = selcx.tcx(); @@ -604,7 +606,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>( alias_ty: ty::AliasTy<'tcx>, cause: ObligationCause<'tcx>, depth: usize, - obligations: &mut Vec>, + obligations: &mut PredicateObligations<'tcx>, ) -> ty::GenericArgsRef<'tcx> { let tcx = selcx.tcx(); @@ -657,15 +659,15 @@ enum Projected<'tcx> { struct Progress<'tcx> { term: ty::Term<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, } impl<'tcx> Progress<'tcx> { fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Progress { term: Ty::new_error(tcx, guar).into(), obligations: vec![] } + Progress { term: Ty::new_error(tcx, guar).into(), obligations: PredicateObligations::new() } } - fn with_addl_obligations(mut self, mut obligations: Vec>) -> Self { + fn with_addl_obligations(mut self, mut obligations: PredicateObligations<'tcx>) -> Self { self.obligations.append(&mut obligations); self } @@ -1351,7 +1353,7 @@ fn confirm_select_candidate<'cx, 'tcx>( fn confirm_coroutine_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1410,7 +1412,7 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( fn confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1458,7 +1460,7 @@ fn confirm_future_candidate<'cx, 'tcx>( fn confirm_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let ty::Coroutine(_, args) = self_ty.kind() else { @@ -1504,7 +1506,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( fn confirm_async_iterator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let ty::Coroutine(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() else { @@ -1558,7 +1560,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( fn confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - data: Vec>, + data: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); @@ -1569,17 +1571,17 @@ fn confirm_builtin_candidate<'cx, 'tcx>( let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); assert_eq!(discriminant_def_id, item_def_id); - (self_ty.discriminant_ty(tcx).into(), Vec::new()) + (self_ty.discriminant_ty(tcx).into(), PredicateObligations::new()) } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) { let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0]; assert_eq!(destructor_def_id, item_def_id); - (self_ty.async_destructor_ty(tcx).into(), Vec::new()) + (self_ty.async_destructor_ty(tcx).into(), PredicateObligations::new()) } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) { let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, item_def_id); - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let normalize = |ty| { normalize_with_depth_to( selcx, @@ -1627,7 +1629,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1663,7 +1665,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1782,7 +1784,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( fn confirm_async_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -1934,7 +1936,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: Vec>, + nested: PredicateObligations<'tcx>, ) -> Progress<'tcx> { let [ // We already checked that the goal_kind >= closure_kind @@ -1987,7 +1989,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); let cache_projection = cache_entry.projection_term; - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let obligation_projection = obligation.predicate; let obligation_projection = ensure_sufficient_stack(|| { normalize_with_depth_to( @@ -2034,7 +2036,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( ); debug!("confirm_param_env_candidate: {}", msg); let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg); - Progress { term: err.into(), obligations: vec![] } + Progress { term: err.into(), obligations: PredicateObligations::new() } } } } @@ -2047,6 +2049,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source; + let assoc_item_id = obligation.predicate.def_id; let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); @@ -2102,7 +2105,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( fn assoc_ty_own_obligations<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, - nested: &mut Vec>, + nested: &mut PredicateObligations<'tcx>, ) { let tcx = selcx.tcx(); let predicates = tcx diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 36b24eac5c4..18412b844ff 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -4,6 +4,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; @@ -20,8 +21,7 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::normalize::needs_normalization; use crate::traits::{ - BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, PredicateObligation, - Reveal, ScrubbedTraitError, + BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, Reveal, ScrubbedTraitError, }; #[extension(pub trait QueryNormalizeExt<'tcx>)] @@ -80,7 +80,9 @@ impl<'a, 'tcx> At<'a, 'tcx> { match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError<'tcx>>( self, value, universes, ) { - Ok(value) => return Ok(Normalized { value, obligations: vec![] }), + Ok(value) => { + return Ok(Normalized { value, obligations: PredicateObligations::new() }); + } Err(_errors) => { return Err(NoSolution); } @@ -88,14 +90,14 @@ impl<'a, 'tcx> At<'a, 'tcx> { } if !needs_normalization(&value, self.param_env.reveal()) { - return Ok(Normalized { value, obligations: vec![] }); + return Ok(Normalized { value, obligations: PredicateObligations::new() }); } let mut normalizer = QueryNormalizer { infcx: self.infcx, cause: self.cause, param_env: self.param_env, - obligations: vec![], + obligations: PredicateObligations::new(), cache: SsoHashMap::new(), anon_depth: 0, universes, @@ -164,7 +166,7 @@ struct QueryNormalizer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - obligations: Vec>, + obligations: PredicateObligations<'tcx>, cache: SsoHashMap, Ty<'tcx>>, anon_depth: usize, universes: Vec>, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index a765de92afd..5ae8c87ec02 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_errors::ErrorGuaranteed; use rustc_infer::infer::canonical::Certainty; -use rustc_infer::traits::PredicateObligation; +use rustc_infer::traits::PredicateObligations; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; @@ -103,13 +103,13 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable> + 't ( Self::QueryResponse, Option>>, - Vec>, + PredicateObligations<'tcx>, Certainty, ), NoSolution, > { if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { - return Ok((result, None, vec![], Certainty::Proven)); + return Ok((result, None, PredicateObligations::new(), Certainty::Proven)); } let mut canonical_var_values = OriginalQueryValues::default(); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 20adda6f0de..52048ca79f9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -12,7 +12,9 @@ use hir::LangItem; use hir::def_id::DefId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_hir as hir; -use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError}; +use rustc_infer::traits::{ + Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError, +}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -963,7 +965,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 0, // We're *intentionally* throwing these away, // since we don't actually use them. - &mut vec![], + &mut PredicateObligations::new(), ) .as_type() .unwrap(); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 5141e969608..cc5c7532b50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -24,7 +24,7 @@ use rustc_span::def_id::DefId; use tracing::{debug, instrument}; use super::SelectionCandidate::{self, *}; -use super::{BuiltinImplConditions, SelectionContext}; +use super::{BuiltinImplConditions, PredicateObligations, SelectionContext}; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::util::{self, closure_trait_ref_and_return_type}; use crate::traits::{ @@ -85,7 +85,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // No nested obligations or confirmation process. The checks that we do in // candidate assembly are sufficient. - AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]), + AsyncFnKindHelperCandidate => { + ImplSource::Builtin(BuiltinImplSource::Misc, PredicateObligations::new()) + } CoroutineCandidate => { let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?; @@ -121,7 +123,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new()) + ImplSource::Builtin(BuiltinImplSource::Misc, PredicateObligations::new()) } BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?, @@ -149,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, idx: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let tcx = self.tcx(); let placeholder_trait_predicate = @@ -179,7 +181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { HigherRankedType, candidate, ); - let mut obligations = Vec::new(); + let mut obligations = PredicateObligations::new(); let candidate = normalize_with_depth_to( self, obligation.param_env, @@ -226,7 +228,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, param: ty::PolyTraitRef<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, ?param, "confirm_param_candidate"); // During evaluation, we already checked that this @@ -249,7 +251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, has_nested: bool, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let tcx = self.tcx(); @@ -279,7 +281,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested, ) } else { - vec![] + PredicateObligations::new() }; debug!(?obligations); @@ -291,7 +293,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_transmutability_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { use rustc_transmute::{Answer, Assume, Condition}; /// Generate sub-obligations for reference-to-reference transmutations. @@ -301,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (src_lifetime, src_ty, src_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), (dst_lifetime, dst_ty, dst_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), assume: Assume, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let make_transmute_obl = |src, dst| { let transmute_trait = obligation.predicate.def_id(); let assume = obligation.predicate.skip_binder().trait_ref.args.const_at(2); @@ -347,7 +349,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Given a transmutation from `&'a (mut) Src` and `&'dst (mut) Dst`, // it is always the case that `Src` must be transmutable into `Dst`, // and that that `'src` must outlive `'dst`. - let mut obls = vec![make_transmute_obl(src_ty, dst_ty)]; + let mut obls = PredicateObligations::with_capacity(1); + obls.push(make_transmute_obl(src_ty, dst_ty)); if !assume.lifetimes { obls.push(make_outlives_obl(src_lifetime, dst_lifetime)); } @@ -382,7 +385,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, cond: Condition>, assume: Assume, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { match cond { // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll` // Not possible until the trait solver supports disjunctions of obligations @@ -424,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let fully_flattened = match maybe_transmutable { Answer::No(_) => Err(Unimplemented)?, Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, cond, assume), - Answer::Yes => vec![], + Answer::Yes => PredicateObligations::new(), }; debug!(?fully_flattened); @@ -439,7 +442,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_auto_impl_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); @@ -453,14 +456,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, trait_def_id: DefId, nested: ty::Binder<'tcx, Vec>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); - let trait_obligations: Vec> = self.impl_or_trait_obligations( + let trait_obligations = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, obligation.param_env, @@ -566,7 +569,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref)); let unnormalized_upcast_trait_ref = @@ -706,7 +709,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, fn_host_effect: ty::Const<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); @@ -750,7 +753,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_trait_alias_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { debug!(?obligation, "confirm_trait_alias_candidate"); let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); @@ -775,7 +778,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_coroutine_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -805,7 +808,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_future_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -835,7 +838,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_iterator_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -865,7 +868,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_async_iterator_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let ty::Coroutine(coroutine_def_id, args) = *self_ty.kind() else { @@ -896,7 +899,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_closure_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty: Ty<'_> = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); @@ -926,13 +929,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_async_closure_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); let tcx = self.tcx(); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let (trait_ref, kind_ty) = match *self_ty.kind() { ty::CoroutineClosure(_, args) => { let args = args.as_coroutine_closure(); @@ -1055,7 +1058,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: TraitObligation<'tcx>, found_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let found_trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, HigherRankedType, @@ -1210,7 +1213,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // words, if the object type is `Foo + Send`, this would create an obligation for // the `Send` check.) // - Projection predicates - let mut nested: Vec<_> = data + let mut nested: PredicateObligations<'_> = data .iter() .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source))) .collect(); @@ -1254,7 +1257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tail_field = def.non_enum_variant().tail(); let tail_field_ty = tcx.type_of(tail_field.did); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); // Extract `TailField` and `TailField` from `Struct` and `Struct`, // normalizing in the process, since `type_of` returns something directly from @@ -1339,7 +1342,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, impl_def_id: Option, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result, SelectionError<'tcx>> { let Some(host_effect_index) = self.tcx().generics_of(obligation.predicate.def_id()).host_effect_index else { @@ -1353,7 +1356,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let self_ty = obligation.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty)); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); // If we have a custom `impl const Drop`, then diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fba1d1025ca..621babe9104 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -18,7 +18,7 @@ use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; -use rustc_infer::traits::TraitObligation; +use rustc_infer::traits::{PredicateObligations, TraitObligation}; use rustc_middle::bug; use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; use rustc_middle::mir::interpret::ErrorHandled; @@ -1067,7 +1067,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && fresh_trait_pred.has_aliases() && fresh_trait_pred.is_global() { - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let predicate = normalize_with_depth_to( this, param_env, @@ -1715,7 +1715,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> ProjectionMatchesProjection { debug_assert_eq!(obligation.predicate.def_id, env_predicate.projection_def_id()); - let mut nested_obligations = Vec::new(); + let mut nested_obligations = PredicateObligations::new(); let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, BoundRegionConversionTime::HigherRankedType, @@ -2410,7 +2410,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { recursion_depth: usize, trait_def_id: DefId, types: ty::Binder<'tcx, Vec>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound // regions. For example, `for<'a> Foo<&'a i32> : Copy` would @@ -2552,9 +2552,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { b_data: &'tcx ty::List>, a_region: ty::Region<'tcx>, b_region: ty::Region<'tcx>, - ) -> SelectionResult<'tcx, Vec>> { + ) -> SelectionResult<'tcx, PredicateObligations<'tcx>> { let tcx = self.tcx(); - let mut nested = vec![]; + let mut nested = PredicateObligations::new(); // We may upcast to auto traits that are either explicitly listed in // the object type's bounds, or implied by the principal trait ref's @@ -2705,7 +2705,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, ()> { + ) -> Result, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) } @@ -2716,7 +2716,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Result>, ()> { + ) -> Result, ()> { let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let trait_ref = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, @@ -2797,7 +2797,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { def_id: DefId, // of impl or trait args: GenericArgsRef<'tcx>, // for impl or trait parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let tcx = self.tcx(); // To allow for one-pass evaluation of the nested obligation, @@ -2817,7 +2817,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let predicates = tcx.predicates_of(def_id); assert_eq!(predicates.parent, None); let predicates = predicates.instantiate_own(tcx, args); - let mut obligations = Vec::with_capacity(predicates.len()); + let mut obligations = PredicateObligations::with_capacity(predicates.len()); for (index, (predicate, span)) in predicates.into_iter().enumerate() { let cause = if tcx.is_lang_item(parent_trait_pred.def_id(), LangItem::CoerceUnsized) { cause.clone() diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a849cdfe125..07e68e5a3e8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::bug; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, @@ -27,7 +27,7 @@ pub fn obligations<'tcx>( recursion_depth: usize, arg: GenericArg<'tcx>, span: Span, -) -> Option>> { +) -> Option> { // Handle the "livelock" case (see comment above) by bailing out if necessary. let arg = match arg.unpack() { GenericArgKind::Type(ty) => { @@ -61,11 +61,18 @@ pub fn obligations<'tcx>( .into() } // There is nothing we have to do for lifetimes. - GenericArgKind::Lifetime(..) => return Some(Vec::new()), + GenericArgKind::Lifetime(..) => return Some(PredicateObligations::new()), }; - let mut wf = - WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: PredicateObligations::new(), + recursion_depth, + item: None, + }; wf.compute(arg); debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); @@ -82,7 +89,7 @@ pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, -) -> Option>> { +) -> Option> { debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); // However, if `arg` IS an unresolved inference variable, returns `None`, @@ -93,7 +100,7 @@ pub fn unnormalized_obligations<'tcx>( } if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { - return Some(vec![]); + return Some(PredicateObligations::new()); } let mut wf = WfPredicates { @@ -101,7 +108,7 @@ pub fn unnormalized_obligations<'tcx>( param_env, body_id: CRATE_DEF_ID, span: DUMMY_SP, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: None, }; @@ -120,13 +127,13 @@ pub fn trait_obligations<'tcx>( trait_pred: ty::TraitPredicate<'tcx>, span: Span, item: &'tcx hir::Item<'tcx>, -) -> Vec> { +) -> PredicateObligations<'tcx> { let mut wf = WfPredicates { infcx, param_env, body_id, span, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: Some(item), }; @@ -147,13 +154,13 @@ pub fn clause_obligations<'tcx>( body_id: LocalDefId, clause: ty::Clause<'tcx>, span: Span, -) -> Vec> { +) -> PredicateObligations<'tcx> { let mut wf = WfPredicates { infcx, param_env, body_id, span, - out: vec![], + out: PredicateObligations::new(), recursion_depth: 0, item: None, }; @@ -192,7 +199,7 @@ struct WfPredicates<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, span: Span, - out: Vec>, + out: PredicateObligations<'tcx>, recursion_depth: usize, item: Option<&'tcx hir::Item<'tcx>>, } @@ -323,7 +330,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) } - fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec> { + fn normalize(self, infcx: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> { // Do not normalize `wf` obligations with the new solver. // // The current deep normalization routine with the new solver does not @@ -336,7 +343,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(ObligationCauseCode::WellFormed(None)); let param_env = self.param_env; - let mut obligations = Vec::with_capacity(self.out.len()); + let mut obligations = PredicateObligations::with_capacity(self.out.len()); for mut obligation in self.out { assert!(!obligation.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); @@ -553,7 +560,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { &mut self, def_id: DefId, args: GenericArgsRef<'tcx>, - ) -> Vec> { + ) -> PredicateObligations<'tcx> { let predicates = self.tcx().predicates_of(def_id); let mut origins = vec![def_id; predicates.predicates.len()]; let mut head = predicates; diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 3102da218db..4c2b7e4769a 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -30,7 +31,7 @@ fn normalize_canonicalized_projection_ty<'tcx>( debug_assert!(!ocx.infcx.next_trait_solver()); let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let answer = traits::normalize_projection_ty(selcx, param_env, goal, cause, 0, &mut obligations); ocx.register_obligations(obligations); @@ -99,7 +100,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>( |ocx, ParamEnvAnd { param_env, value: goal }| { let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); - let mut obligations = vec![]; + let mut obligations = PredicateObligations::new(); let answer = traits::normalize_inherent_projection( selcx, param_env, -- cgit 1.4.1-3-g733a5 From b6b6c12819bbffca3aa75298afb79cf1a70e0312 Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Mon, 14 Oct 2024 08:07:41 +0200 Subject: Update lint message for ABI not supported --- compiler/rustc_hir_analysis/src/check/check.rs | 6 +++--- compiler/rustc_lint_defs/src/builtin.rs | 2 +- tests/ui/abi/unsupported.aarch64.stderr | 20 ++++++++++---------- tests/ui/abi/unsupported.arm.stderr | 18 +++++++++--------- tests/ui/abi/unsupported.i686.stderr | 14 +++++++------- tests/ui/abi/unsupported.riscv32.stderr | 18 +++++++++--------- tests/ui/abi/unsupported.riscv64.stderr | 18 +++++++++--------- tests/ui/abi/unsupported.x64.stderr | 18 +++++++++--------- 8 files changed, 57 insertions(+), 57 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 4429f6346e8..94da3d4ea84 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -61,9 +61,9 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab Some(true) => (), Some(false) | None => { tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { - lint.primary_message( - "use of calling convention not supported on this target on function pointer", - ); + lint.primary_message(format!( + "the calling convention {abi} is not supported on this target" + )); }); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 23dc5214fe2..da603df9a9a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3859,7 +3859,7 @@ declare_lint! { /// This will produce: /// /// ```text - /// warning: use of calling convention not supported on this target on function pointer + /// warning: the calling convention `"stdcall"` is not supported on this target /// --> $DIR/unsupported.rs:34:15 /// | /// LL | fn stdcall_ptr(f: extern "stdcall" fn()) { diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index 00a5b4b2ee1..82908ef88a8 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -104,7 +104,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -123,7 +123,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -132,7 +132,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index dfb5ceb0c33..39ec5d16fcd 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 6537ce66057..1dc01a66aab 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -83,7 +83,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index a53f85f28bc..e7d5197feeb 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index a53f85f28bc..e7d5197feeb 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "x86-interrupt" is not supported on this target --> $DIR/unsupported.rs:116:15 | LL | fn x86_ptr(f: extern "x86-interrupt" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index 45ba9a6649c..bbca754dd41 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,4 +1,4 @@ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "ptx-kernel" is not supported on this target --> $DIR/unsupported.rs:35:15 | LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) { @@ -14,7 +14,7 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "aapcs" is not supported on this target --> $DIR/unsupported.rs:49:17 | LL | fn aapcs_ptr(f: extern "aapcs" fn()) { @@ -29,7 +29,7 @@ error[E0570]: `"aapcs"` is not a supported ABI for the current target LL | extern "aapcs" {} | ^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "msp430-interrupt" is not supported on this target --> $DIR/unsupported.rs:71:18 | LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) { @@ -44,7 +44,7 @@ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "avr-interrupt" is not supported on this target --> $DIR/unsupported.rs:81:15 | LL | fn avr_ptr(f: extern "avr-interrupt" fn()) { @@ -59,7 +59,7 @@ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target LL | extern "avr-interrupt" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "riscv-interrupt-m" is not supported on this target --> $DIR/unsupported.rs:94:17 | LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) { @@ -74,7 +74,7 @@ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current targe LL | extern "riscv-interrupt-m" {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "thiscall" is not supported on this target --> $DIR/unsupported.rs:139:20 | LL | fn thiscall_ptr(f: extern "thiscall" fn()) { @@ -89,7 +89,7 @@ error[E0570]: `"thiscall"` is not a supported ABI for the current target LL | extern "thiscall" {} | ^^^^^^^^^^^^^^^^^^^^ -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "stdcall" is not supported on this target --> $DIR/unsupported.rs:170:19 | LL | fn stdcall_ptr(f: extern "stdcall" fn()) { @@ -108,7 +108,7 @@ LL | extern "stdcall" {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-call" is not supported on this target --> $DIR/unsupported.rs:195:21 | LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { @@ -117,7 +117,7 @@ LL | fn cmse_call_ptr(f: extern "C-cmse-nonsecure-call" fn()) { = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #130260 -warning: use of calling convention not supported on this target on function pointer +warning: the calling convention "C-cmse-nonsecure-entry" is not supported on this target --> $DIR/unsupported.rs:203:22 | LL | fn cmse_entry_ptr(f: extern "C-cmse-nonsecure-entry" fn()) { -- cgit 1.4.1-3-g733a5 From 7500e09b8baa6d21c85a699ef359c8c4e6175629 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Oct 2024 09:16:03 -0400 Subject: Move trait bound modifiers into hir::PolyTraitRef --- compiler/rustc_ast_lowering/src/lib.rs | 43 ++++++++++------------ .../src/diagnostics/region_errors.rs | 4 +- .../rustc_borrowck/src/diagnostics/region_name.rs | 2 +- compiler/rustc_hir/src/hir.rs | 15 ++++---- compiler/rustc_hir/src/intravisit.rs | 4 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/collect/predicates_of.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 4 +- .../src/hir_ty_lowering/bounds.rs | 8 ++-- .../src/hir_ty_lowering/dyn_compatibility.rs | 9 +++-- .../src/hir_ty_lowering/errors.rs | 8 ++-- .../rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 4 +- compiler/rustc_hir_pretty/src/lib.rs | 14 +++---- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_lint/src/traits.rs | 5 ++- compiler/rustc_middle/src/ty/diagnostics.rs | 3 +- .../infer/nice_region_error/find_anon_type.rs | 2 +- .../infer/nice_region_error/static_impl_trait.rs | 2 +- .../src/error_reporting/infer/note_and_explain.rs | 4 +- .../src/error_reporting/infer/suggest.rs | 5 ++- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 6 +-- .../src/traits/dyn_compatibility.rs | 2 +- src/librustdoc/clean/mod.rs | 8 ++-- .../clippy_lints/src/implied_bounds_in_impls.rs | 6 ++- src/tools/clippy/clippy_lints/src/len_zero.rs | 2 +- src/tools/clippy/clippy_lints/src/lifetimes.rs | 4 +- .../clippy/clippy_lints/src/manual_async_fn.rs | 2 +- .../clippy_lints/src/needless_maybe_sized.rs | 8 ++-- src/tools/clippy/clippy_lints/src/trait_bounds.rs | 15 ++++---- .../clippy/clippy_lints/src/types/borrowed_box.rs | 2 +- .../clippy_lints/src/types/type_complexity.rs | 1 - 32 files changed, 102 insertions(+), 100 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 365924ef782..b19ccc59a71 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1225,7 +1225,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, TraitBoundModifiers::NONE, ); - let bound = (bound, hir::TraitBoundModifier::None); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) @@ -1328,8 +1327,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // const trait bounds in trait object types. GenericBound::Trait(ty, modifiers) => { let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers); - let polarity = this.lower_trait_bound_modifiers(*modifiers); - Some((trait_ref, polarity)) + Some(trait_ref) } GenericBound::Outlives(lifetime) => { if lifetime_bound.is_none() { @@ -1958,21 +1956,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span_ext: DUMMY_SP, }); - hir::GenericBound::Trait( - hir::PolyTraitRef { - bound_generic_params: &[], - trait_ref: hir::TraitRef { - path: self.make_lang_item_path( - trait_lang_item, - opaque_ty_span, - Some(bound_args), - ), - hir_ref_id: self.next_id(), - }, - span: opaque_ty_span, + hir::GenericBound::Trait(hir::PolyTraitRef { + bound_generic_params: &[], + modifiers: hir::TraitBoundModifier::None, + trait_ref: hir::TraitRef { + path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)), + hir_ref_id: self.next_id(), }, - hir::TraitBoundModifier::None, - ) + span: opaque_ty_span, + }) } #[instrument(level = "trace", skip(self))] @@ -1982,10 +1974,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, *modifiers), - self.lower_trait_bound_modifiers(*modifiers), - ), + GenericBound::Trait(p, modifiers) => { + hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx, *modifiers)) + } GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } @@ -2194,7 +2185,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } + let modifiers = self.lower_trait_bound_modifiers(modifiers); + hir::PolyTraitRef { + bound_generic_params, + modifiers, + trait_ref, + span: self.lower_span(p.span), + } } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { @@ -2634,10 +2631,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { let principal = hir::PolyTraitRef { bound_generic_params: &[], + modifiers: hir::TraitBoundModifier::None, trait_ref: hir::TraitRef { path, hir_ref_id: hir_id }, span: self.lower_span(span), }; - let principal = (principal, hir::TraitBoundModifier::None); // The original ID is taken by the `PolyTraitRef`, // so the `Ty` itself needs a different one. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 39175b406a4..6333d59a1bc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -254,7 +254,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!(?hrtb_bounds); hrtb_bounds.iter().for_each(|bound| { - let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { + let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); @@ -277,7 +277,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { return; }; bounds.iter().for_each(|bd| { - if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }, _) = bd + if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }) = bd && let Def(_, res_defid) = tr_ref.path.res && res_defid == trait_res_defid // trait id matches && let TyKind::Path(Resolved(_, path)) = bounded_ty.kind diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 1a5f9bdb154..b4b8373ac97 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -837,7 +837,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { hir_ty ); }; - if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref, _)], .. } = opaque_ty + if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(args) = segment.args && let [constraint] = args.constraints diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2ef6fa53f4e..1e9cbba94c7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -520,7 +520,7 @@ pub enum TraitBoundModifier { #[derive(Clone, Copy, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { - Trait(PolyTraitRef<'hir>, TraitBoundModifier), + Trait(PolyTraitRef<'hir>), Outlives(&'hir Lifetime), Use(&'hir [PreciseCapturingArg<'hir>], Span), } @@ -528,7 +528,7 @@ pub enum GenericBound<'hir> { impl GenericBound<'_> { pub fn trait_ref(&self) -> Option<&TraitRef<'_>> { match self { - GenericBound::Trait(data, _) => Some(&data.trait_ref), + GenericBound::Trait(data) => Some(&data.trait_ref), _ => None, } } @@ -2874,11 +2874,7 @@ pub enum TyKind<'hir> { OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject( - &'hir [(PolyTraitRef<'hir>, TraitBoundModifier)], - &'hir Lifetime, - TraitObjectSyntax, - ), + TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), /// Unused for now. Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been @@ -3182,6 +3178,11 @@ pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// The constness and polarity of the trait ref. + /// + /// The `async` modifier is lowered directly into a different trait for now. + pub modifiers: TraitBoundModifier, + /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`. pub trait_ref: TraitRef<'hir>, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 58916d05865..ffe519b0e7d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -905,7 +905,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul try_visit!(visitor.visit_array_length(length)); } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { - for (bound, _modifier) in bounds { + for bound in bounds { try_visit!(visitor.visit_poly_trait_ref(bound)); } try_visit!(visitor.visit_lifetime(lifetime)); @@ -1160,7 +1160,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>( bound: &'v GenericBound<'v>, ) -> V::Result { match *bound { - GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ), + GenericBound::Trait(ref typ) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), GenericBound::Use(args, _) => { walk_list!(visitor, visit_precise_capturing_arg, args); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3a9d2640eee..1d78ea0c919 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -832,7 +832,7 @@ impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { match ty.kind { - hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments { + hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments { [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), _ => false, }, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6d30f7c7b9d..a87b29b3093 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -866,7 +866,7 @@ impl<'tcx> ItemCtxt<'tcx> { #[instrument(level = "trace", skip(self))] fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool { match b { - hir::GenericBound::Trait(poly_trait_ref, _) => { + hir::GenericBound::Trait(poly_trait_ref) => { let trait_ref = &poly_trait_ref.trait_ref; if let Some(trait_did) = trait_ref.trait_def_id() { self.tcx.trait_may_define_assoc_item(trait_did, assoc_name) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index c8852a3a369..cb7f0901c7e 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -644,7 +644,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { debug!(?bounds, ?lifetime, "TraitObject"); let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { - for (bound, _) in bounds { + for bound in bounds { this.visit_poly_trait_ref_inner( bound, NonLifetimeBinderAllowed::Deny("trait object types"), @@ -1918,7 +1918,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { return None; } predicate.bounds.iter().find_map(|bound| { - let hir::GenericBound::Trait(trait_, _) = bound else { + let hir::GenericBound::Trait(trait_) = bound else { return None; }; BoundVarContext::supertrait_hrtb_vars( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 45cd46e3df2..8f7ca089c91 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -44,10 +44,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { for hir_bound in hir_bounds { - let hir::GenericBound::Trait(ptr, modifier) = hir_bound else { + let hir::GenericBound::Trait(ptr) = hir_bound else { continue; }; - match modifier { + match ptr.modifiers { hir::TraitBoundModifier::Maybe => unbounds.push(ptr), hir::TraitBoundModifier::Negative => { if let Some(sized_def_id) = sized_def_id @@ -156,8 +156,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { for hir_bound in hir_bounds { match hir_bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let (constness, polarity) = match modifier { + hir::GenericBound::Trait(poly_trait_ref) => { + let (constness, polarity) = match poly_trait_ref.modifiers { hir::TraitBoundModifier::Const => { (ty::BoundConstness::Const, ty::PredicatePolarity::Positive) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 394a263fbb5..98822eec2ac 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -30,7 +30,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], + hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, representation: DynKind, ) -> Ty<'tcx> { @@ -39,8 +39,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; - for (trait_bound, modifier) in hir_trait_bounds.iter().rev() { - if *modifier == hir::TraitBoundModifier::Maybe { + for trait_bound in hir_trait_bounds.iter().rev() { + // FIXME: This doesn't handle `? const`. + if trait_bound.modifiers == hir::TraitBoundModifier::Maybe { continue; } if let GenericArgCountResult { @@ -263,7 +264,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let args = tcx.mk_args(&args); let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| { + let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) && hir_bound.span.contains(span) }); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index a735b8cc2a4..01768c89cca 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -718,7 +718,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, associated_types: FxIndexMap>, potential_assoc_types: Vec, - trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)], + trait_bounds: &[hir::PolyTraitRef<'_>], ) { if associated_types.values().all(|v| v.is_empty()) { return; @@ -764,12 +764,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // related to issue #91997, turbofishes added only when in an expr or pat let mut in_expr_or_pat = false; if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { - let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.0.trait_ref.hir_ref_id)); + let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id)); in_expr_or_pat = match grandparent { hir::Node::Expr(_) | hir::Node::Pat(_) => true, _ => false, }; - match bound.0.trait_ref.path.segments { + match bound.trait_ref.path.segments { // FIXME: `trait_ref.path.span` can point to a full path with multiple // segments, even though `trait_ref.path.segments` is of length `1`. Work // around that bug here, even though it should be fixed elsewhere. @@ -810,7 +810,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // and we can then use their span to indicate this to the user. let bound_names = trait_bounds .iter() - .filter_map(|(poly_trait_ref, _)| { + .filter_map(|poly_trait_ref| { let path = poly_trait_ref.trait_ref.path.segments.last()?; let args = path.args?; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 11c0450bfe2..fd49e7e4439 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -50,7 +50,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .ok() .is_some_and(|s| s.trim_end().ends_with('<')); - let is_global = poly_trait_ref.0.trait_ref.path.is_global(); + let is_global = poly_trait_ref.trait_ref.path.is_global(); let mut sugg = vec![( self_ty.span.shrink_to_lo(), @@ -211,7 +211,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { - objects.iter().all(|(o, _)| match o.trait_ref.path.res { + objects.iter().all(|o| match o.trait_ref.path.res { Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9fe6a8ee342..9ebfd4f15ab 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -301,16 +301,13 @@ impl<'a> State<'a> { self.word_space("dyn"); } let mut first = true; - for (bound, modifier) in bounds { + for bound in bounds { if first { first = false; } else { self.nbsp(); self.word_space("+"); } - if *modifier == TraitBoundModifier::Maybe { - self.word("?"); - } self.print_poly_trait_ref(bound); } if !lifetime.is_elided() { @@ -679,6 +676,10 @@ impl<'a> State<'a> { } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { + // FIXME: This isn't correct! + if t.modifiers == TraitBoundModifier::Maybe { + self.word("?"); + } self.print_formal_generic_params(t.bound_generic_params); self.print_trait_ref(&t.trait_ref); } @@ -2077,10 +2078,7 @@ impl<'a> State<'a> { } match bound { - GenericBound::Trait(tref, modifier) => { - if modifier == &TraitBoundModifier::Maybe { - self.word("?"); - } + GenericBound::Trait(tref) => { self.print_poly_trait_ref(tref); } GenericBound::Outlives(lt) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 1df4d32f3cb..3e9e5326156 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -849,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::FnRetTy::Return(hir_ty) => { if let hir::TyKind::OpaqueDef(op_ty, ..) = hir_ty.kind // FIXME: account for RPITIT. - && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds + && let [hir::GenericBound::Trait(trait_ref)] = op_ty.bounds && let Some(hir::PathSegment { args: Some(generic_args), .. }) = trait_ref.trait_ref.path.segments.last() && let [constraint] = generic_args.constraints @@ -1035,7 +1035,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // extract all bounds from the source code using their spans let all_matching_bounds_strs = predicates_from_where .filter_map(|bound| match bound { - GenericBound::Trait(_, _) => { + GenericBound::Trait(_) => { self.tcx.sess.source_map().span_to_snippet(bound.span()).ok() } _ => None, diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index c0a01b0065e..5a3666dcbd4 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -112,10 +112,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; - for (bound, modifier) in &bounds[..] { + for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) - && *modifier != hir::TraitBoundModifier::Maybe + // FIXME: ?Drop is not a thing. + && bound.modifiers != hir::TraitBoundModifier::Maybe { let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id }); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 354ca746b46..4f408ee1574 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -192,7 +192,8 @@ fn suggest_changing_unsized_bound( .iter() .enumerate() .filter(|(_, bound)| { - if let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound + if let hir::GenericBound::Trait(poly) = bound + && poly.modifiers == hir::TraitBoundModifier::Maybe && poly.trait_ref.trait_def_id() == def_id { true diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 7a44c2ad661..2ecd28f4868 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -86,7 +86,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } hir::TyKind::TraitObject(bounds, ..) => { - for (bound, _) in bounds { + for bound in bounds { self.current_index.shift_in(1); self.visit_poly_trait_ref(bound); self.current_index.shift_out(1); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index a6ecd1cc987..8541621b23b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -599,7 +599,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { _, ) = t.kind { - for (ptr, _) in poly_trait_refs { + for ptr in poly_trait_refs { if Some(self.1) == ptr.trait_ref.trait_def_id() { self.0.push(ptr.span); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index cf0ab630f2e..62204f63dd0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -894,7 +894,9 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. let trait_bounds = bounds.iter().filter_map(|bound| match bound { - hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr), + hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifier::None => { + Some(ptr) + } _ => None, }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 709b6eb18e3..fc2d0ba36f0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -740,9 +740,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| match ( left, right, ) { - (hir::GenericBound::Trait(tl, ml), hir::GenericBound::Trait(tr, mr)) + // FIXME: Suspicious + (hir::GenericBound::Trait(tl), hir::GenericBound::Trait(tr)) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id() - && ml == mr => + && tl.modifiers == tr.modifiers => { true } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index becc1acfb66..ba57909fc23 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -439,7 +439,7 @@ pub fn report_dyn_incompatibility<'tcx>( if tcx.parent_hir_node(hir_id).fn_sig().is_some() { // Do not suggest `impl Trait` when dealing with things like super-traits. err.span_suggestion_verbose( - ty.span.until(trait_ref.0.span), + ty.span.until(trait_ref.span), "consider using an opaque type instead", "impl ", Applicability::MaybeIncorrect, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 87834c329e1..733baaa99e5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3074,11 +3074,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { match ty.kind { hir::TyKind::TraitObject(traits, _, _) => { let (span, kw) = match traits { - [(first, _), ..] if first.span.lo() == ty.span.lo() => { + [first, ..] if first.span.lo() == ty.span.lo() => { // Missing `dyn` in front of trait object. (ty.span.shrink_to_lo(), "dyn ") } - [(first, _), ..] => (ty.span.until(first.span), ""), + [first, ..] => (ty.span.until(first.span), ""), [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"), }; let needs_parens = traits.len() != 1; @@ -5162,7 +5162,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span); let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty(); - let [hir::GenericBound::Trait(trait_ref, _)] = future.bounds else { + let [hir::GenericBound::Trait(trait_ref)] = future.bounds else { // `async fn` should always lower to a single bound... but don't ICE. return None; }; diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 45e7de942fb..364a13b3a75 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -125,7 +125,7 @@ fn sized_trait_bound_spans<'tcx>( bounds: hir::GenericBounds<'tcx>, ) -> impl 'tcx + Iterator { bounds.iter().filter_map(move |b| match b { - hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None) + hir::GenericBound::Trait(trait_ref) if trait_has_sized_self( tcx, trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fa73733360c..1ddad917b78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -214,15 +214,15 @@ fn clean_generic_bound<'tcx>( ) -> Option { Some(match *bound { hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)), - hir::GenericBound::Trait(ref t, modifier) => { + hir::GenericBound::Trait(ref t) => { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if modifier == hir::TraitBoundModifier::MaybeConst + if t.modifiers == hir::TraitBoundModifier::MaybeConst && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap()) { return None; } - GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier) + GenericBound::TraitBound(clean_poly_trait_ref(t, cx), t.modifiers) } hir::GenericBound::Use(args, ..) => { GenericBound::Use(args.iter().map(|arg| arg.name()).collect()) @@ -1833,7 +1833,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, lifetime, _) => { - let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect(); + let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); let lifetime = if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None }; DynTrait(bounds, lifetime) diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 5f349d78053..590d9afd1b4 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -242,7 +242,8 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds bounds .iter() .filter_map(|bound| { - if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound + if let GenericBound::Trait(poly_trait) = bound + && let TraitBoundModifier::None = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() @@ -307,7 +308,8 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { // This involves some extra logic when generic arguments are present, since // simply comparing trait `DefId`s won't be enough. We also need to compare the generics. for (index, bound) in bounds.iter().enumerate() { - if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound + if let GenericBound::Trait(poly_trait) = bound + && let TraitBoundModifier::None = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints) diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 311bbce14bd..035ee40348c 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -310,7 +310,7 @@ fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<& if let ty::Alias(_, alias_ty) = ty.kind() && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir().get_if_local(alias_ty.def_id) && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin - && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds + && let [GenericBound::Trait(trait_ref)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(generic_args) = segment.args && let [constraint] = generic_args.constraints diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ec28671a061..a7c48eb216a 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -163,7 +163,7 @@ fn check_fn_inner<'tcx>( if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) { return; } - if let GenericBound::Trait(ref trait_ref, _) = *bound { + if let GenericBound::Trait(ref trait_ref) = *bound { let params = &trait_ref .trait_ref .path @@ -438,7 +438,7 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { if !lt.is_elided() { self.unelided_trait_object_lifetime = true; } - for (bound, _) in bounds { + for bound in bounds { self.visit_poly_trait_ref(bound); } }, diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 81115cffdca..67255c1af79 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -107,7 +107,7 @@ fn future_trait_ref<'tcx>( ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { if let TyKind::OpaqueDef(opaque, bounds) = ty.kind && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { - if let GenericBound::Trait(poly, _) = bound { + if let GenericBound::Trait(poly) = bound { Some(&poly.trait_ref) } else { None diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index bb44ff37b20..a56024f08d5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -40,7 +40,6 @@ struct Bound<'tcx> { ident: Ident, trait_bound: &'tcx PolyTraitRef<'tcx>, - modifier: TraitBoundModifier, predicate_pos: usize, bound_pos: usize, @@ -65,11 +64,10 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator Some(Bound { + &GenericBound::Trait(ref trait_bound) => Some(Bound { param, ident, trait_bound, - modifier, predicate_pos, bound_pos, }), @@ -120,13 +118,13 @@ impl LateLintPass<'_> for NeedlessMaybeSized { let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics) .filter(|bound| { bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait) - && bound.modifier == TraitBoundModifier::Maybe + && bound.trait_bound.modifiers == TraitBoundModifier::Maybe }) .map(|bound| (bound.param, bound)) .collect(); for bound in type_param_bounds(generics) { - if bound.modifier == TraitBoundModifier::None + if bound.trait_bound.modifiers == TraitBoundModifier::None && let Some(sized_bound) = maybe_sized_params.get(&bound.param) && let Some(path) = path_to_sized_bound(cx, bound.trait_bound) { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 3c3973857e7..38befdee574 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // Iterate the bounds and add them to our seen hash // If we haven't yet seen it, add it to the fixed traits - for (bound, _) in bounds { + for bound in bounds { let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; @@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // If the number of unique traits isn't the same as the number of traits in the bounds, // there must be 1 or more duplicates if bounds.len() != unique_traits.len() { - let mut bounds_span = bounds[0].0.span; + let mut bounds_span = bounds[0].span; - for (bound, _) in bounds.iter().skip(1) { + for bound in bounds.iter().skip(1) { bounds_span = bounds_span.to(bound.span); } @@ -229,7 +229,8 @@ impl TraitBounds { /// this MSRV? See for details. fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) - && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound + && let GenericBound::Trait(tr) = bound + && let TraitBoundModifier::Maybe = tr.modifiers { cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() } else { @@ -375,11 +376,11 @@ impl Default for ComparableTraitRef { } fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> { - if let GenericBound::Trait(t, tbm) = bound { + if let GenericBound::Trait(t) = bound { let trait_path = t.trait_ref.path; let trait_span = { let path_span = trait_path.span; - if let TraitBoundModifier::Maybe = tbm { + if let TraitBoundModifier::Maybe = t.modifiers { path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?` } else { path_span @@ -430,7 +431,7 @@ fn rollup_traits( let mut repeated_res = false; let only_comparable_trait_refs = |bound: &GenericBound<'_>| { - if let GenericBound::Trait(t, _) = bound { + if let GenericBound::Trait(t) = bound { Some((into_comparable_trait_ref(&t.trait_ref), t.span)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 2fcfc71a8c7..eb7ffbbe360 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -82,7 +82,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m // Returns true if given type is `Any` trait. fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { if let TyKind::TraitObject(traits, ..) = t.kind { - return traits.iter().any(|(bound, _)| { + return traits.iter().any(|bound| { if let Some(trait_did) = bound.trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Any, trait_did) { diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index 0b64fddb447..b89bd6a8d05 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -55,7 +55,6 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::TraitObject(param_bounds, _, _) => { let has_lifetime_parameters = param_bounds.iter().any(|bound| { bound - .0 .bound_generic_params .iter() .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) -- cgit 1.4.1-3-g733a5 From 10aa255541964bceddaac8f49d7a11f1d736e24d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 14 Oct 2024 22:32:32 +0200 Subject: improve error messages for `C-cmse-nonsecure-entry` functions --- compiler/rustc_hir_analysis/messages.ftl | 15 +- compiler/rustc_hir_analysis/src/errors.rs | 17 ++- .../rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 157 +++++++++++++-------- .../cmse-nonsecure-entry/generics.rs | 77 ++++++++++ .../cmse-nonsecure-entry/generics.stderr | 78 ++++++++++ .../cmse-nonsecure-entry/params-on-registers.rs | 16 --- .../cmse-nonsecure-entry/params-on-stack.rs | 21 --- .../cmse-nonsecure-entry/params-on-stack.stderr | 4 - .../cmse-nonsecure-entry/params-via-stack.rs | 26 ++++ .../cmse-nonsecure-entry/params-via-stack.stderr | 43 ++++++ .../cmse-nonsecure-entry/return-via-stack.rs | 84 +++++++++++ .../cmse-nonsecure-entry/return-via-stack.stderr | 84 +++++++++++ .../cmse-nonsecure-entry/trustzone-only.stderr | 9 ++ .../cmse-nonsecure-entry/via-registers.rs | 89 ++++++++++++ 14 files changed, 612 insertions(+), 108 deletions(-) create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs delete mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index da814cd2d69..a9f30ffd6da 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -68,18 +68,21 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo hir_analysis_cmse_call_generic = function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type -hir_analysis_cmse_call_inputs_stack_spill = - arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers +hir_analysis_cmse_entry_generic = + functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + +hir_analysis_cmse_inputs_stack_spill = + arguments for `"{$abi_name}"` function too large to pass via registers .label = {$plural -> [false] this argument doesn't *[true] these arguments don't } fit in the available registers - .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers + .note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers -hir_analysis_cmse_call_output_stack_spill = - return value of `"C-cmse-nonsecure-call"` function too large to pass via registers +hir_analysis_cmse_output_stack_spill = + return value of `"{$abi_name}"` function too large to pass via registers .label = this type doesn't fit in the available registers - .note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + .note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9099703e812..af4445a7fd4 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1627,23 +1627,25 @@ pub(crate) struct InvalidReceiverTy<'tcx> { pub(crate) struct EffectsWithoutNextSolver; #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)] +#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)] #[note] -pub(crate) struct CmseCallInputsStackSpill { +pub(crate) struct CmseInputsStackSpill { #[primary_span] #[label] pub span: Span, pub plural: bool, + pub abi_name: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)] +#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)] #[note(hir_analysis_note1)] #[note(hir_analysis_note2)] -pub(crate) struct CmseCallOutputStackSpill { +pub(crate) struct CmseOutputStackSpill { #[primary_span] #[label] pub span: Span, + pub abi_name: &'static str, } #[derive(Diagnostic)] @@ -1659,3 +1661,10 @@ pub(crate) struct BadReturnTypeNotation { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_cmse_entry_generic, code = E0798)] +pub(crate) struct CmseEntryGeneric { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index a562759da11..672dc8ddeda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,8 +1,8 @@ use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; +use rustc_middle::bug; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; -use rustc_span::Span; use rustc_target::spec::abi; use crate::errors; @@ -17,61 +17,104 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: abi::Abi, fn_sig: ty::PolyFnSig<'tcx>, ) { - if let abi::Abi::CCmseNonSecureCall = abi { - let hir_node = tcx.hir_node(hir_id); - let hir::Node::Ty(hir::Ty { - span: bare_fn_span, - kind: hir::TyKind::BareFn(bare_fn_ty), - .. - }) = hir_node - else { - let span = match tcx.parent_hir_node(hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::ForeignMod { .. }, span, .. - }) => *span, - _ => tcx.hir().span(hir_id), + let abi_name = abi.name(); + + match abi { + abi::Abi::CCmseNonSecureCall => { + let hir_node = tcx.hir_node(hir_id); + let hir::Node::Ty(hir::Ty { + span: bare_fn_span, + kind: hir::TyKind::BareFn(bare_fn_ty), + .. + }) = hir_node + else { + let span = match tcx.parent_hir_node(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ForeignMod { .. }, + span, + .. + }) => *span, + _ => tcx.hir().span(hir_id), + }; + struct_span_code_err!( + tcx.dcx(), + span, + E0781, + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + ) + .emit(); + return; }; - struct_span_code_err!( - tcx.dcx(), - span, - E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" - ) - .emit(); - return; - }; - match is_valid_cmse_inputs(tcx, fn_sig) { - Ok(Ok(())) => {} - Ok(Err(index)) => { - // fn(x: u32, u32, u32, u16, y: u16) -> u32, - // ^^^^^^ - let span = bare_fn_ty.param_names[index] - .span - .to(bare_fn_ty.decl.inputs[index].span) - .to(bare_fn_ty.decl.inputs.last().unwrap().span); - let plural = bare_fn_ty.param_names.len() - index != 1; - dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural }); - } - Err(layout_err) => { - if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) { - dcx.emit_err(err); + match is_valid_cmse_inputs(tcx, fn_sig) { + Ok(Ok(())) => {} + Ok(Err(index)) => { + // fn(x: u32, u32, u32, u16, y: u16) -> u32, + // ^^^^^^ + let span = bare_fn_ty.param_names[index] + .span + .to(bare_fn_ty.decl.inputs[index].span) + .to(bare_fn_ty.decl.inputs.last().unwrap().span); + let plural = bare_fn_ty.param_names.len() - index != 1; + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + } } } + + match is_valid_cmse_output(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + let span = bare_fn_ty.decl.output.span(); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + } + } + }; } + abi::Abi::CCmseNonSecureEntry => { + let hir_node = tcx.hir_node(hir_id); + let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else { + // might happen when this ABI is used incorrectly. That will be handled elsewhere + return; + }; - match is_valid_cmse_output(tcx, fn_sig) { - Ok(true) => {} - Ok(false) => { - let span = bare_fn_ty.decl.output.span(); - dcx.emit_err(errors::CmseCallOutputStackSpill { span }); - } - Err(layout_err) => { - if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) { - dcx.emit_err(err); + match is_valid_cmse_inputs(tcx, fn_sig) { + Ok(Ok(())) => {} + Ok(Err(index)) => { + // fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32, + // ^^^^^^ + let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span); + let plural = decl.inputs.len() - index != 1; + dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span }); + } } } - }; + + match is_valid_cmse_output(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + let span = decl.output.span(); + dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name }); + } + Err(layout_err) => { + if should_emit_generic_error(abi, layout_err) { + dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span }); + } + } + }; + } + _ => (), } } @@ -152,22 +195,22 @@ fn is_valid_cmse_output<'tcx>( Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64) } -fn cmse_layout_err<'tcx>( - layout_err: &'tcx LayoutError<'tcx>, - span: Span, -) -> Option { +fn should_emit_generic_error<'tcx>(abi: abi::Abi, layout_err: &'tcx LayoutError<'tcx>) -> bool { use LayoutError::*; match layout_err { Unknown(ty) => { - if ty.is_impl_trait() { - None // prevent double reporting of this error - } else { - Some(errors::CmseCallGeneric { span }) + match abi { + abi::Abi::CCmseNonSecureCall => { + // prevent double reporting of this error + !ty.is_impl_trait() + } + abi::Abi::CCmseNonSecureEntry => true, + _ => bug!("invalid ABI: {abi}"), } } SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => { - None // not our job to report these + false // not our job to report these } } } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs new file mode 100644 index 00000000000..a264bba6f3c --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -0,0 +1,77 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, c_variadic, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for u32 {} + +#[repr(C)] +struct Wrapper(T); + +impl Wrapper { + extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + //~^ ERROR [E0798] + 0 + } + + extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( + //~^ ERROR [E0798] + _: Wrapper, + _: u32, + _: u32, + _: u32, + ) -> u64 { + 0 + } +} + +extern "C-cmse-nonsecure-entry" fn introduced_generic( + //~^ ERROR [E0798] + _: U, + _: u32, + _: u32, + _: u32, +) -> u64 { + 0 +} + +extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { + //~^ ERROR [E0798] + 0 +} + +extern "C-cmse-nonsecure-entry" fn reference(x: &usize) -> usize { + *x +} + +trait Trait {} + +extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +extern "C-cmse-nonsecure-entry" fn static_trait_object( + x: &'static dyn Trait, +) -> &'static dyn Trait { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +#[repr(transparent)] +struct WrapperTransparent<'a>(&'a dyn Trait); + +extern "C-cmse-nonsecure-entry" fn wrapped_trait_object( + x: WrapperTransparent, +) -> WrapperTransparent { + //~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798] + x +} + +extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR requires `va_list` lang_item +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr new file mode 100644 index 00000000000..9e67f881f75 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -0,0 +1,78 @@ +error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + --> $DIR/generics.rs:74:55 + | +LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:31:1 + | +LL | / extern "C-cmse-nonsecure-entry" fn introduced_generic( +LL | | +LL | | _: U, +LL | | _: u32, +LL | | _: u32, +LL | | _: u32, +LL | | ) -> u64 { + | |________^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:41:1 + | +LL | extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:15:5 + | +LL | extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + --> $DIR/generics.rs:20:5 + | +LL | / extern "C-cmse-nonsecure-entry" fn ambient_generic_nested( +LL | | +LL | | _: Wrapper, +LL | | _: u32, +LL | | _: u32, +LL | | _: u32, +LL | | ) -> u64 { + | |____________^ + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:52:67 + | +LL | extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait { + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:59:6 + | +LL | ) -> &'static dyn Trait { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/generics.rs:69:6 + | +LL | ) -> WrapperTransparent { + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error: requires `va_list` lang_item + --> $DIR/generics.rs:74:55 + | +LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { + | ^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs deleted file mode 100644 index de6888fae62..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ build-pass -//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -//@ needs-llvm-components: arm -#![feature(cmse_nonsecure_entry, no_core, lang_items)] -#![no_core] -#![crate_type = "lib"] -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} -impl Copy for u32 {} - -#[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { - d -} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs deleted file mode 100644 index 4413c461c04..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ build-fail -//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -//@ needs-llvm-components: arm -#![feature(cmse_nonsecure_entry, no_core, lang_items)] -#![no_core] -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} -impl Copy for u32 {} - -#[no_mangle] -pub extern "C-cmse-nonsecure-entry" fn entry_function( - _: u32, - _: u32, - _: u32, - _: u32, - e: u32, -) -> u32 { - e -} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr deleted file mode 100644 index cfbdda509e5..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: :0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack - -error: aborting due to 1 previous error - diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs new file mode 100644 index 00000000000..572d792d5a5 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs @@ -0,0 +1,26 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for u32 {} + +#[repr(C, align(16))] +#[allow(unused)] +pub struct AlignRelevant(u32); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} //~ ERROR [E0798] +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [E0798] + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr new file mode 100644 index 00000000000..b77e64c6bfb --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr @@ -0,0 +1,43 @@ +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:16:78 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} + | ^^^^^^^^^^^ these arguments don't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:18:78 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:20:62 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:22:64 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} + | ^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:26:46 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} + | ^^^^^^^^ this argument doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs new file mode 100644 index 00000000000..5746d14f9b1 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs @@ -0,0 +1,84 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for u32 {} +impl Copy for u8 {} + +#[repr(C)] +pub struct ReprCU64(u64); + +#[repr(C)] +pub struct ReprCBytes(u8, u8, u8, u8, u8); + +#[repr(C)] +pub struct U64Compound(u32, u32); + +#[repr(C, align(16))] +pub struct ReprCAlign16(u16); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { + //~^ ERROR [E0798] + ReprCU64(0) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { + //~^ ERROR [E0798] + ReprCBytes(0, 1, 2, 3, 4) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { + //~^ ERROR [E0798] + U64Compound(2, 3) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { + //~^ ERROR [E0798] + ReprCAlign16(4) +} + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { + //~^ ERROR [E0798] + [0xAA; 5] +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { + //~^ ERROR [E0798] + 123 +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { + //~^ ERROR [E0798] + 456 +} + +#[repr(Rust)] +pub union ReprRustUnionU64 { + _unused: u64, +} + +#[repr(C)] +pub union ReprCUnionU64 { + _unused: u64, +} + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { + //~^ ERROR [E0798] + ReprRustUnionU64 { _unused: 1 } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { + //~^ ERROR [E0798] + ReprCUnionU64 { _unused: 2 } +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr new file mode 100644 index 00000000000..9c885d95318 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.stderr @@ -0,0 +1,84 @@ +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:25:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 { + | ^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:30:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes { + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:35:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound { + | ^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:40:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 { + | ^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:47:48 + | +LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] { + | ^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:53:50 + | +LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 { + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:59:50 + | +LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 { + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:76:56 + | +LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 { + | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/return-via-stack.rs:81:53 + | +LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 { + | ^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr new file mode 100644 index 00000000000..77379f7049d --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr @@ -0,0 +1,9 @@ +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:5:1 + | +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs new file mode 100644 index 00000000000..8978b35d356 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs @@ -0,0 +1,89 @@ +//@ build-pass +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for u32 {} +impl Copy for u8 {} + +#[repr(transparent)] +pub struct ReprTransparentStruct { + _marker1: (), + _marker2: (), + field: T, + _marker3: (), +} + +#[repr(transparent)] +pub enum ReprTransparentEnumU64 { + A(u64), +} + +#[repr(C)] +pub struct U32Compound(u16, u16); + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs1() {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs2(_: u32, _: u32, _: u32, _: u32) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs3(_: u64, _: u64) {} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn inputs4(_: u128) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct, _: U32Compound) {} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {} + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs1() -> u32 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs2() -> u64 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs3() -> i64 { + 0 +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs4() -> f64 { + 0.0 +} +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C-cmse-nonsecure-entry" fn outputs5() -> [u8; 4] { + [0xAA; 4] +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct { + ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs7( +) -> ReprTransparentStruct> { + ReprTransparentStruct { + _marker1: (), + _marker2: (), + field: ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () }, + _marker3: (), + } +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs8() -> ReprTransparentEnumU64 { + ReprTransparentEnumU64::A(0) +} +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn outputs9() -> U32Compound { + U32Compound(1, 2) +} -- cgit 1.4.1-3-g733a5 From 4886e9a134aa7c8c9bb1fed42ebfe22d7f5b2a63 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 14:39:49 -0400 Subject: Unify secondary_span and swap_secondary_and_primary --- .../rustc_hir_analysis/src/check/compare_impl_item.rs | 9 +++------ compiler/rustc_hir_analysis/src/check/mod.rs | 1 - compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 1 - compiler/rustc_passes/src/check_attr.rs | 1 - .../src/error_reporting/infer/mod.rs | 18 +++++++----------- .../src/error_reporting/traits/fulfillment_errors.rs | 3 +-- 6 files changed, 11 insertions(+), 22 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9ca5f25447b..75956165e87 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -592,14 +592,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( &cause, hir.get_if_local(impl_m.def_id) .and_then(|node| node.fn_decl()) - .map(|decl| (decl.output.span(), Cow::from("return type in trait"))), + .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_return_ty.into(), found: impl_return_ty.into(), })), terr, false, - false, ); return Err(diag.emit()); } @@ -1018,14 +1017,13 @@ fn report_trait_method_mismatch<'tcx>( infcx.err_ctxt().note_type_err( &mut diag, &cause, - trait_err_span.map(|sp| (sp, Cow::from("type in trait"))), + trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)), Some(infer::ValuePairs::PolySigs(ExpectedFound { expected: ty::Binder::dummy(trait_sig), found: ty::Binder::dummy(impl_sig), })), terr, false, - false, ); diag.emit() @@ -1825,14 +1823,13 @@ fn compare_const_predicate_entailment<'tcx>( infcx.err_ctxt().note_type_err( &mut diag, &cause, - trait_c_span.map(|span| (span, Cow::from("type in trait"))), + trait_c_span.map(|span| (span, Cow::from("type in trait"), false)), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_ty.into(), found: impl_ty.into(), })), terr, false, - false, ); return Err(diag.emit()); }; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 004540b2643..959b17b2d40 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -652,7 +652,6 @@ pub fn check_function_signature<'tcx>( })), err, false, - false, ); return Err(diag.emit()); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fa471647d02..44c0da0744a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1114,7 +1114,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, Some(trace.values), e, - false, true, ); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7ce29260e36..4516ea94cad 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2302,7 +2302,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { })), terr, false, - false, ); diag.emit(); self.abort.set(true); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index bd78a6ee3af..df5800ab58a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1127,18 +1127,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// the message in `secondary_span` as the primary label, and apply the message that would /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on /// E0271, like `tests/ui/issues/issue-39970.stderr`. - #[instrument( - level = "debug", - skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label) - )] + #[instrument(level = "debug", skip(self, diag, secondary_span, prefer_label))] pub fn note_type_err( &self, diag: &mut Diag<'_>, cause: &ObligationCause<'tcx>, - secondary_span: Option<(Span, Cow<'static, str>)>, + secondary_span: Option<(Span, Cow<'static, str>, bool)>, mut values: Option>, terr: TypeError<'tcx>, - swap_secondary_and_primary: bool, prefer_label: bool, ) { let span = cause.span(); @@ -1304,7 +1300,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.span_note(span, msg); } }; - if let Some((sp, msg)) = secondary_span { + if let Some((secondary_span, secondary_msg, swap_secondary_and_primary)) = secondary_span { if swap_secondary_and_primary { let terr = if let Some(infer::ValuePairs::Terms(ExpectedFound { expected, .. @@ -1314,11 +1310,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { terr.to_string(self.tcx) }; - label_or_note(sp, terr); - label_or_note(span, msg); + label_or_note(secondary_span, terr); + label_or_note(span, secondary_msg); } else { label_or_note(span, terr.to_string(self.tcx)); - label_or_note(sp, msg); + label_or_note(secondary_span, secondary_msg); } } else if let Some(values) = values && let Some((e, f)) = values.ty() @@ -1788,7 +1784,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.type_error_additional_suggestions(&trace, terr), ); let mut diag = self.dcx().create_err(failure_code); - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); diag } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 824c25db07d..8a4c22fdf86 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -710,7 +710,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)), false, - false, ); diag } @@ -1435,6 +1434,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cx.into_buffer() } ))), + true, )), _ => None, } @@ -1452,7 +1452,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )) }), err, - true, false, ); self.note_obligation_cause(&mut diag, obligation); -- cgit 1.4.1-3-g733a5 From 68885216b63f6e75e50b4c0f3c7250ca4ac7afda Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 14:58:41 -0400 Subject: Don't report bivariance error when nesting a struct with field errors into another struct --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 60 ++++++++++++++++++---- .../type-resolve-error-two-structs-deep.rs | 13 +++++ .../type-resolve-error-two-structs-deep.stderr | 9 ++++ 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 tests/ui/variance/type-resolve-error-two-structs-deep.rs create mode 100644 tests/ui/variance/type-resolve-error-two-structs-deep.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 607068f162a..f788456d4e9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1875,24 +1875,15 @@ fn check_variances_for_type_defn<'tcx>( item: &'tcx hir::Item<'tcx>, hir_generics: &hir::Generics<'tcx>, ) { - let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id); - match item.kind { ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { - for field in tcx.adt_def(item.owner_id).all_fields() { - if field.ty(tcx, identity_args).references_error() { - return; - } - } + // Ok } ItemKind::TyAlias(..) => { assert!( tcx.type_alias_is_lazy(item.owner_id), "should not be computing variance of non-weak type alias" ); - if tcx.type_of(item.owner_id).skip_binder().references_error() { - return; - } } kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"), } @@ -1955,6 +1946,15 @@ fn check_variances_for_type_defn<'tcx>( continue; } + // Look for `ErrorGuaranteed` deeply within this type. + if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx + .type_of(item.owner_id) + .instantiate_identity() + .visit_with(&mut HasErrorDeep { tcx, seen: Default::default() }) + { + continue; + } + match hir_param.name { hir::ParamName::Error => {} _ => { @@ -1965,6 +1965,46 @@ fn check_variances_for_type_defn<'tcx>( } } +/// Look for `ErrorGuaranteed` deeply within structs' (unsubstituted) fields. +struct HasErrorDeep<'tcx> { + tcx: TyCtxt<'tcx>, + seen: FxHashSet, +} +impl<'tcx> TypeVisitor> for HasErrorDeep<'tcx> { + type Result = ControlFlow; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match *ty.kind() { + ty::Adt(def, _) => { + if self.seen.insert(def.did()) { + for field in def.all_fields() { + self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?; + } + } + } + ty::Error(guar) => return ControlFlow::Break(guar), + _ => {} + } + ty.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + if let Err(guar) = r.error_reported() { + ControlFlow::Break(guar) + } else { + ControlFlow::Continue(()) + } + } + + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { + if let Err(guar) = c.error_reported() { + ControlFlow::Break(guar) + } else { + ControlFlow::Continue(()) + } + } +} + fn report_bivariance<'tcx>( tcx: TyCtxt<'tcx>, param: &'tcx hir::GenericParam<'tcx>, diff --git a/tests/ui/variance/type-resolve-error-two-structs-deep.rs b/tests/ui/variance/type-resolve-error-two-structs-deep.rs new file mode 100644 index 00000000000..47ec532ab96 --- /dev/null +++ b/tests/ui/variance/type-resolve-error-two-structs-deep.rs @@ -0,0 +1,13 @@ +// Make sure we don't report bivariance errors when nesting structs w/ unresolved +// fields into *other* structs. + +struct Hello<'a> { + missing: Missing<'a>, + //~^ ERROR cannot find type `Missing` in this scope +} + +struct Other<'a> { + hello: Hello<'a>, +} + +fn main() {} diff --git a/tests/ui/variance/type-resolve-error-two-structs-deep.stderr b/tests/ui/variance/type-resolve-error-two-structs-deep.stderr new file mode 100644 index 00000000000..3458d924bb1 --- /dev/null +++ b/tests/ui/variance/type-resolve-error-two-structs-deep.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/type-resolve-error-two-structs-deep.rs:5:14 + | +LL | missing: Missing<'a>, + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. -- cgit 1.4.1-3-g733a5