diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 54d083a094883..9b621a0c35d1b 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1140,6 +1140,12 @@ pub enum AttributeKind { /// Represents `#[rustc_allow_lifetime_dependent_specialization]`. RustcAllowLifetimeDependentSpecialization, + /// Represents `#[rustc_anti_fundamental]`. This marks a trait so that it + /// cannot be implemented for non-local `#[fundamental]` types. This in particular + /// prevents the implementation of `Deref`, `DerefMut`, and `DispatchFromDyn` on + /// fundamental wrappers like `Pin` and `Box`. + RustcAntiFundamental, + /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). RustcAsPtr, diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 270ec0399799e..7bb75e54440b1 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -107,6 +107,7 @@ impl AttributeKind { RustcAllowConstFnUnstable(..) => No, RustcAllowIncoherentImpl(..) => No, RustcAllowLifetimeDependentSpecialization => No, + RustcAntiFundamental => No, RustcAsPtr => Yes, RustcAutodiff(..) => Yes, RustcBodyStability { .. } => No, diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 1d0d26ea62cb3..5968efa2d815f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -123,6 +123,14 @@ impl NoArgsAttributeParser for RustcCoinductiveParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoinductive; } +pub(crate) struct RustcAntiFundamentalParser; +impl NoArgsAttributeParser for RustcAntiFundamentalParser { + const PATH: &[Symbol] = &[sym::rustc_anti_fundamental]; + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const STABILITY: AttributeStability = unstable!(rustc_attrs); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAntiFundamental; +} + pub(crate) struct RustcAllowIncoherentImplParser; impl NoArgsAttributeParser for RustcAllowIncoherentImplParser { const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl]; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index cf99311cc0cfc..7e4b0149a0c70 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -295,6 +295,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index ea557d5321598..d10712b3b532f 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -10,7 +10,9 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice}; use tracing::debug; -use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict}; +use crate::{ + AccessDepth, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict, +}; // This analysis is different to most others. Its results aren't computed with // `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are @@ -432,7 +434,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { // If the borrowed place is a local with no projections, all other borrows of this // local must conflict. This is purely an optimization so we don't have to call - // `places_conflict` for every borrow. + // `places_conflict::borrow_conflicts_with_place` for every borrow. if place.projection.is_empty() { if !self.body.local_decls[place.local].is_ref_to_static() { state.kill_all(other_borrows_of_local); @@ -445,11 +447,13 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { // will be assured that two places being compared definitely denotes the same sets of // locations. let definitely_conflicting_borrows = other_borrows_of_local.filter(|&i| { - places_conflict( + places_conflict::borrow_conflicts_with_place( self.tcx, self.body, self.borrow_set[i].borrowed_place, - place, + self.borrow_set[i].kind, + place.as_ref(), + AccessDepth::Deep, PlaceConflictBias::NoOverlap, ) }); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0e5ab5c00bd76..7e840163e958c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -560,7 +560,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // we'll use this to check whether it was originally from an overloaded // operator. match self.move_data.rev_lookup.find(deref_base) { - LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => { + LookupResult::Exact(mpi) | LookupResult::Parent { mpi, .. } => { debug!("borrowed_content_source: mpi={:?}", mpi); for i in &self.move_data.init_path_map[mpi] { @@ -597,7 +597,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } // Base is a `static` so won't be from an overloaded operator - _ => (), + LookupResult::None => (), }; // If we didn't find an overloaded deref or index, then assume it's a diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 9fac00016eac2..b70b4aa1fc4a1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -189,7 +189,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { match self.move_data.rev_lookup.find(match_place.as_ref()) { // Error with the match place - LookupResult::Parent(_) => { + LookupResult::Parent { .. } | LookupResult::None => { for ge in &mut *grouped_errors { if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge && match_span == *span @@ -219,7 +219,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } // Error with the pattern LookupResult::Exact(_) => { - let LookupResult::Parent(Some(mpi)) = + let LookupResult::Parent { mpi, .. } = self.move_data.rev_lookup.find(move_from.as_ref()) else { // move_from should be a projection from match_place. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b10570db1cdd2..c347e933013f2 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2077,15 +2077,43 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // This code covers scenarios 1, 2, and 3. debug!("check_if_full_path_is_moved place: {:?}", place_span.0); - let (prefix, mpi) = self.move_path_closest_to(place_span.0); - if maybe_uninits.contains(mpi) { + + let uninit_mpi = match self.move_data.rev_lookup.find(place_span.0) { + // Index projections arbitrarily overlap sibling move paths, so we need to check all descendents of the parent + // Subslice and ConstantIndex projections of slices also overlap siblings, + // but the parent slice will never have a move path + // Subslice projections of arrays are specifically checked in `check_if_subslice_element_is_moved` + LookupResult::Parent { mpi, next_elem: ProjectionKind::Index(..) } => self + .move_data + .find_in_move_path_or_its_descendants(mpi, |mpi| maybe_uninits.contains(mpi)), + + LookupResult::Exact(mpi) + | LookupResult::Parent { + mpi, + next_elem: + ProjectionKind::Deref + | ProjectionKind::Field(..) + | ProjectionKind::ConstantIndex { .. } + | ProjectionKind::Subslice { .. } + | ProjectionKind::Downcast(..) + | ProjectionKind::OpaqueCast(..) + | ProjectionKind::UnwrapUnsafeBinder(..) + | ProjectionKind::PhantomDeref, + } => maybe_uninits.contains(mpi).then_some(mpi), + + LookupResult::None => bug!("should have move path for every Local"), + }; + + if let Some(mpi) = uninit_mpi { self.report_use_of_moved_or_uninitialized( location, desired_action, - (prefix, place_span.0, place_span.1), + (self.move_data.move_paths[mpi].place.as_ref(), place_span.0, place_span.1), mpi, ); - } // Only query longest prefix with a MovePath, not further + } + + // Only query longest prefix with a MovePath, not further // ancestors; dataflow recurs on children when parents // move (to support partial (re)inits). // @@ -2207,32 +2235,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } } - /// Currently MoveData does not store entries for all places in - /// the input MIR. For example it will currently filter out - /// places that are Copy; thus we do not track places of shared - /// reference type. This routine will walk up a place along its - /// prefixes, searching for a foundational place that *is* - /// tracked in the MoveData. - /// - /// An Err result includes a tag indicated why the search failed. - /// Currently this can only occur if the place is built off of a - /// static variable, as we do not track those in the MoveData. - fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) { - match self.move_data.rev_lookup.find(place) { - LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => { - (self.move_data.move_paths[mpi].place.as_ref(), mpi) - } - LookupResult::Parent(None) => panic!("should have move path for every Local"), - } - } - fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option { // If returns None, then there is no move path corresponding // to a direct owner of `place` (which means there is nothing // that borrowck tracks for its analysis). match self.move_data.rev_lookup.find(place) { - LookupResult::Parent(_) => None, + LookupResult::Parent { .. } | LookupResult::None => None, LookupResult::Exact(mpi) => Some(mpi), } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index dc174775af2e5..49858232b3563 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> { match context { PlaceContext::NonMutatingUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { - let (LookupResult::Exact(path) | LookupResult::Parent(Some(path))) = + let (LookupResult::Exact(path) | LookupResult::Parent { mpi: path, .. }) = self.move_data.rev_lookup.find(place.as_ref()) else { // There's no path access to emit. diff --git a/compiler/rustc_error_codes/src/error_codes/E0224.md b/compiler/rustc_error_codes/src/error_codes/E0224.md index 628488575b2f8..a6fd0e0fd3a48 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0224.md +++ b/compiler/rustc_error_codes/src/error_codes/E0224.md @@ -11,5 +11,5 @@ Rust does not currently support this. To solve, ensure that the trait object has at least one trait: ``` -type Foo = dyn 'static + Copy; +type Foo = dyn 'static + std::fmt::Debug; ``` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f79a8e9ffc79c..e4b4e3296803f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -346,6 +346,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ sym::rustc_never_returns_null_ptr, sym::rustc_no_implicit_autorefs, sym::rustc_coherence_is_core, + sym::rustc_anti_fundamental, sym::rustc_coinductive, sym::rustc_comptime, sym::rustc_allow_incoherent_impl, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1895f586df2f0..33e5992e1eda3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -756,6 +756,22 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } +fn check_function_clauses(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { + let clauses = tcx.clauses_of(def_id); + let param_env = tcx.param_env(def_id); + enter_wf_checking_ctxt(tcx, def_id, |wfcx| { + for (clause, span) in clauses.clauses { + wfcx.register_obligation(Obligation::new( + tcx, + ObligationCause::new(*span, def_id, ObligationCauseCode::WellFormed(None)), + param_env, + *clause, + )); + } + Ok(()) + }) +} + pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let mut res = Ok(()); let generics = tcx.generics_of(def_id); @@ -815,9 +831,9 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), DefKind::Fn => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); - tcx.ensure_ok().clauses_of(def_id); tcx.ensure_ok().fn_sig(def_id); tcx.ensure_ok().codegen_fn_attrs(def_id); + res = res.and(check_function_clauses(tcx, def_id)); if let Some(i) = tcx.intrinsic(def_id) { intrinsic::check_intrinsic_type( tcx, @@ -985,6 +1001,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), } else { check_type_alias_type_params_are_used(tcx, def_id); res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { + // FIXME(fmease): Update comment. // HACK: We sometimes incidentally check that const arguments have the correct // type as a side effect of the anon const desugaring. To make this "consistent" // for users we explicitly check `ConstArgHasType` clauses so that const args @@ -995,15 +1012,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), // // Changing this to normalized obligations is a breaking change: // `type Bar = [(); panic!()];` would become an error - if let Some(unnormalized_obligations) = wfcx.unnormalized_obligations(span, ty.skip_norm_wip()) + if let Some(obligations) = + wfcx.unnormalized_obligations(span, ty.skip_norm_wip()) { - let filtered_obligations = - unnormalized_obligations.into_iter().filter(|o| { - matches!(o.predicate.kind().skip_binder(), - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) - if matches!(ct.kind(), ty::ConstKind::Param(..))) - }); - wfcx.ocx.register_obligations(filtered_obligations) + wfcx.ocx.register_obligations(obligations.into_iter().filter(|o| { + match o.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + ct, + _, + )) => matches!(ct.kind(), ty::ConstKind::Param(..)), + ty::PredicateKind::DynCompatible(_) => true, + _ => false, + } + })) } Ok(()) })); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c970799d318fe..b7730551ae03a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -28,31 +28,41 @@ pub(crate) fn orphan_check_impl( match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) { Ok(()) => {} - Err(err) => match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) { - Ok(()) => match err { - OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => { - let hir_id = tcx.local_def_id_to_hir_id(impl_def_id); - - for param_def_id in uncovered_ty_params.uncovered { - let ident = tcx.item_ident(param_def_id); - - tcx.emit_node_span_lint( - UNCOVERED_PARAM_IN_PROJECTION, - hir_id, - ident.span, - diagnostics::UncoveredTyParam { - param: ident, - local_ty: uncovered_ty_params.local_ty, - }, - ); + Err(err) => { + if tcx.trait_def(trait_ref.def_id).is_anti_fundamental { + return Err(emit_orphan_check_error(tcx, trait_ref, impl_def_id, err)); + } + + match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) { + Ok(()) => match err { + OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => { + let hir_id = tcx.local_def_id_to_hir_id(impl_def_id); + + for param_def_id in uncovered_ty_params.uncovered { + let ident = tcx.item_ident(param_def_id); + + tcx.emit_node_span_lint( + UNCOVERED_PARAM_IN_PROJECTION, + hir_id, + ident.span, + diagnostics::UncoveredTyParam { + param: ident, + local_ty: uncovered_ty_params.local_ty, + }, + ); + } } - } - OrphanCheckErr::NonLocalInputType(_) => { - bug!("orphanck: shouldn't've gotten non-local input tys in compat mode") - } - }, - Err(err) => return Err(emit_orphan_check_error(tcx, trait_ref, impl_def_id, err)), - }, + OrphanCheckErr::NonLocalInputType(_) => { + bug!("orphanck: shouldn't've gotten non-local input tys in compat mode") + } + OrphanCheckErr::AntiFundamentalForeignType { .. } => { + // An anti-fundamental trait should return early above and never enter compat mode. + bug!("anti-fundamental traits never enter compat mode") + } + }, + Err(err) => return Err(emit_orphan_check_error(tcx, trait_ref, impl_def_id, err)), + } + } } let trait_def_id = trait_ref.def_id; @@ -381,6 +391,24 @@ fn orphan_check<'tcx>( }); OrphanCheckErr::NonLocalInputType(tys) } + OrphanCheckErr::AntiFundamentalForeignType { self_ty, fundamental_ty } => { + let (self_ty, fundamental_ty) = infcx.probe(|_| { + for (arg, id_arg) in + std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id)) + { + let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq( + DefineOpaqueTypes::No, + arg, + id_arg, + ); + } + ( + infcx.resolve_vars_if_possible(self_ty), + infcx.resolve_vars_if_possible(fundamental_ty), + ) + }); + OrphanCheckErr::AntiFundamentalForeignType { self_ty, fundamental_ty } + } }) } @@ -499,6 +527,16 @@ fn emit_orphan_check_error<'tcx>( } guar.unwrap() } + traits::OrphanCheckErr::AntiFundamentalForeignType { self_ty, fundamental_ty } => { + let item = tcx.hir_expect_item(impl_def_id); + let impl_ = item.expect_impl(); + tcx.dcx().emit_err(diagnostics::AntiFundamentalForeignImpl { + span: impl_.self_ty.span, + trait_name: tcx.def_path_str(trait_ref.def_id), + self_ty, + fundamental_ty, + }) + } } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 65fd562a4ebf6..775200988c1c6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1122,6 +1122,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let deny_explicit_impl = find_attr!(attrs, RustcDenyExplicitImpl); let force_dyn_incompatible = find_attr!(attrs, RustcDynIncompatibleTrait(span) => *span); + let is_anti_fundamental = find_attr!(attrs, RustcAntiFundamental); ty::TraitDef { def_id: def_id.to_def_id(), @@ -1139,6 +1140,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { must_implement_one_of, force_dyn_incompatible, deny_explicit_impl, + is_anti_fundamental, } } diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index a50aefd016059..f7b05dafc3bed 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -2144,7 +2144,6 @@ pub(crate) struct OnlyStructsCanBeViewedAdt<'tcx> { pub article: &'static str, pub kind: &'static str, } - #[derive(Diagnostic)] #[diag("the type of const parameters must not depend on other generic parameters", code = E0770)] pub(crate) struct ParamInTyOfConstParam<'tcx> { @@ -2153,3 +2152,18 @@ pub(crate) struct ParamInTyOfConstParam<'tcx> { pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } + +#[derive(Diagnostic)] +#[diag("cannot implement `{$trait_name}` for the fundamental type `{$fundamental_ty}`")] +#[note( + "`{$trait_name}` is `#[rustc_anti_fundamental]` and \ + cannot be implemented for `#[fundamental]` types from another crate" +)] +pub(crate) struct AntiFundamentalForeignImpl<'tcx> { + #[primary_span] + #[label("impl of `{$trait_name}` not allowed for `{$self_ty}`")] + pub(crate) span: Span, + pub(crate) trait_name: String, + pub(crate) self_ty: Ty<'tcx>, + pub(crate) fundamental_ty: Ty<'tcx>, +} diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..fdc02a8482010 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -638,6 +638,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(def_id).is_fundamental } + fn trait_is_anti_fundamental(self, def_id: DefId) -> bool { + self.trait_def(def_id).is_anti_fundamental + } + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { self.trait_def(trait_def_id).safety.is_unsafe() } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 5309e35b1073c..eb0c293938f66 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -80,6 +80,11 @@ pub struct TraitDef { /// This only applies to built-in traits, and is marked via /// `#[rustc_deny_explicit_impl]`. pub deny_explicit_impl: bool, + + /// If `true`, then this trait has the `#[rustc_anti_fundamental]` attribute + /// and cannot be implemented for `#[fundamental]` types from another crate. + /// Used for `Deref`, `DerefMut`, `DispatchFromDyn`, `CoerceUnsized`, etc. + pub is_anti_fundamental: bool, } /// Whether this trait is treated specially by the standard library diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index 7d7491dd643b0..262992e817b35 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -55,7 +55,7 @@ pub fn on_lookup_result_bits<'tcx, F>( F: FnMut(MovePathIndex), { match lookup_result { - LookupResult::Parent(..) => { + LookupResult::Parent { .. } | LookupResult::None => { // access to untracked value - do not touch children } LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child), diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index b6565588ae3f1..5c111d722a990 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -344,11 +344,18 @@ pub enum LookupResult { /// This exact thing has a move path. E.g. we looked up `x` or `x.m` and it has been moved. Exact(MovePathIndex), - /// - If the field is `None`, neither the exact thing nor any ancestor of it has a move path. - /// E.g. we looked up `x.m` and neither it nor `x` have a move path. - /// - If the field is `Some`, the exact thing has no move path, but an ancestor does. E.g. we - /// looked up `x.m` which has no move path but `x` has one. Not possible for locals. - Parent(Option), + /// The exact thing has no move path, but an ancestor does. + /// E.g. we looked up `x.m` which has no move path but `x` has one. Not possible for locals. + Parent { + mpi: MovePathIndex, + + /// The projection in the place immediately projecting from the parent move path. + next_elem: ProjectionKind, + }, + + /// Neither the exact thing nor any ancestor of it has a move path. + /// E.g. we looked up `x.m` and neither it nor `x` have a move path. + None, } impl<'tcx> MovePathLookup<'tcx> { @@ -359,7 +366,7 @@ impl<'tcx> MovePathLookup<'tcx> { pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult { // Look first in the locals (roots). let Some(mut result) = self.find_local(place.local) else { - return LookupResult::Parent(None); + return LookupResult::None; }; // Look for a projection through the found local. @@ -372,7 +379,7 @@ impl<'tcx> MovePathLookup<'tcx> { }; let Some(&subpath) = subpath else { - return LookupResult::Parent(Some(result)); + return LookupResult::Parent { mpi: result, next_elem: elem.kind() }; }; result = subpath; } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 35c601f09acd4..9f6ae5013d18a 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -224,7 +224,7 @@ where } } - LookupResult::Parent(..) => { + LookupResult::Parent { .. } | LookupResult::None => { tcx.dcx().emit_err(PeekArgumentUntracked { span: call.span }); } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 84c9c044ae6a6..8133274604182 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -314,8 +314,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { } }); } - LookupResult::Parent(None) => {} - LookupResult::Parent(Some(parent)) => { + LookupResult::None => {} + LookupResult::Parent { mpi: parent, .. } => { if self.body.local_decls[place.local].is_deref_temp() { continue; } @@ -387,8 +387,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { drop, ) } - LookupResult::Parent(None) => {} - LookupResult::Parent(Some(_)) => { + LookupResult::None => {} + LookupResult::Parent { .. } => { if !replace { self.tcx.dcx().span_bug( terminator.source_info.span, diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index eb6921e438528..a52c52d85f7a9 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -76,7 +76,7 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> { } MovePathIndexAtBlock::Unknown => { if let TerminatorKind::Drop { place, .. } = &terminator.kind - && let LookupResult::Exact(idx) | LookupResult::Parent(Some(idx)) = + && let LookupResult::Exact(idx) | LookupResult::Parent { mpi: idx, .. } = self.move_data.rev_lookup.find(place.as_ref()) { // Since we are working with MIRs at a very early stage, observing a `drop` diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index e37e69a617bbd..d64eef889a251 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -17,6 +17,12 @@ pub enum InCrate { Remote, } +impl InCrate { + pub fn def_id_is_local(self, def_id: impl DefId) -> bool { + matches!(self, InCrate::Local { .. }) && def_id.is_local() + } +} + #[derive(Copy, Clone, Debug)] pub enum OrphanCheckMode { /// Proper orphan check. @@ -118,6 +124,7 @@ impl From for IsFirstInputType { pub enum OrphanCheckErr { NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>), UncoveredTyParams(UncoveredTyParams), + AntiFundamentalForeignType { self_ty: I::Ty, fundamental_ty: I::Ty }, } #[derive_where(Debug; I: Interner, T: Debug)] @@ -160,6 +167,13 @@ pub struct UncoveredTyParams { /// - however, `LocalType>` is OK, because `T` is a subtree of /// `LocalType>`, which is local and has no types between it and /// the type parameter. +/// 5. If the trait is marked `#[rustc_anti_fundamental]`, the `Self` type +/// must not have a non-local `#[fundamental]` type at its head (even if +/// it wraps a local type as in (2)). +/// - e.g., `Box` or `&Pin` is rejected if the trait +/// is `#[rustc_anti_fundamental]`. +/// - This lets the standard library reserve control over traits like `Deref` +/// and `DispatchFromDyn` on fundamental wrappers such as `Box` and `Pin`. /// /// The orphan rules actually serve several different purposes: /// @@ -223,7 +237,7 @@ pub fn orphan_check_trait_ref( infcx: &Infcx, trait_ref: ty::TraitRef, in_crate: InCrate, - lazily_normalize_ty: impl FnMut(I::Ty) -> Result, + mut lazily_normalize_ty: impl FnMut(I::Ty) -> Result, ) -> Result>, E> where Infcx: InferCtxtLike, @@ -234,6 +248,20 @@ where panic!("orphan check only expects inference variables: {trait_ref:?}"); } + // Anti-fundamental check: if the trait is marked `#[rustc_anti_fundamental]`, + // we do not allow impls where the head of the Self type is a non-local fundamental + // type. This prevents downstream crates from implementing traits like `Deref` on + // fundamental wrappers like `Box` or `Pin`. + let cx = infcx.cx(); + if cx.trait_is_anti_fundamental(trait_ref.def_id) { + let self_ty = trait_ref.self_ty(); + if let Some(fundamental_ty) = + check_anti_fundamental_head(infcx, in_crate, &mut lazily_normalize_ty, self_ty)? + { + return Ok(Err(OrphanCheckErr::AntiFundamentalForeignType { self_ty, fundamental_ty })); + } + } + let mut checker = OrphanChecker::new(infcx, in_crate, lazily_normalize_ty); Ok(match trait_ref.visit_with(&mut checker) { ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)), @@ -256,6 +284,46 @@ where }) } +/// Checks the head of the Self type for a non-local fundamental type. +/// +/// If the head is a reference (`&` / `&mut`), we unwrap it and inspect the pointee type. +/// This ensures that wrapping a fundamental type in a reference (such as `&Pin`) +/// cannot be used to bypass the anti-fundamental restriction. +/// +/// Returns `Some(ty)` with the offending fundamental type if the check fails. +fn check_anti_fundamental_head( + infcx: &Infcx, + in_crate: InCrate, + mut lazily_normalize_ty: impl FnMut(I::Ty) -> Result, + mut ty: I::Ty, +) -> Result, E> +where + Infcx: InferCtxtLike, + I: Interner, +{ + loop { + ty = infcx.shallow_resolve(ty); + let norm_ty = match lazily_normalize_ty(ty)? { + norm if norm.is_ty_var() => ty, + norm => norm, + }; + + if let ty::Ref(_, inner, _) = norm_ty.kind() { + ty = inner; + continue; + } + + ty = norm_ty; + break; + } + + Ok(matches!( + ty.kind(), + ty::Adt(def, _) if def.is_fundamental() && !in_crate.def_id_is_local(def.def_id()) + ) + .then_some(ty)) +} + struct OrphanChecker<'a, Infcx, I: Interner, F> { infcx: &'a Infcx, in_crate: InCrate, @@ -296,11 +364,8 @@ where ControlFlow::Break(OrphanCheckEarlyExit::UncoveredTyParam(ty)) } - fn def_id_is_local(&mut self, def_id: impl DefId) -> bool { - match self.in_crate { - InCrate::Local { .. } => def_id.is_local(), - InCrate::Remote => false, - } + fn def_id_is_local(&self, def_id: impl DefId) -> bool { + self.in_crate.def_id_is_local(def_id) } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cd7f422fb72f3..663c286141f85 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -316,6 +316,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcAllocatorZeroedVariant { .. } => (), AttributeKind::RustcAllowIncoherentImpl(..) => (), AttributeKind::RustcAllowLifetimeDependentSpecialization => (), + AttributeKind::RustcAntiFundamental => (), AttributeKind::RustcAsPtr => (), AttributeKind::RustcAutodiff(..) => (), AttributeKind::RustcBodyStability { .. } => (), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3fcb59ea2d701..2c538d809936f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -271,7 +271,6 @@ symbols! { PartialEq, PartialOrd, Pending, - PinDerefMutHelper, PinMacroHelper, Pointer, Poll, @@ -1764,6 +1763,7 @@ symbols! { rustc_allow_incoherent_impl, rustc_allow_lifetime_dependent_specialization, rustc_allowed_through_unstable_modules, + rustc_anti_fundamental, rustc_as_ptr, rustc_attrs, rustc_autodiff, 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 7921250a85a9e..9ffb043934274 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4432,23 +4432,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // can do about it. As far as they are concerned, `?` is compiler magic. return; } - if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) { - let parent_predicate = - self.resolve_vars_if_possible(data.derived.parent_trait_pred); - // Skip PinDerefMutHelper in suggestions, but still show downstream suggestions. - - self.note_obligation_cause_code( - body_def_id, - err, - parent_predicate, - param_env, - &data.derived.parent_code, - obligated_types, - seen_requirements, - ); - return; - } let self_ty_str = tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path()); let trait_name = tcx.short_string( diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..18e61db5b6955 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -485,6 +485,8 @@ pub trait Interner: fn trait_is_fundamental(self, def_id: Self::TraitId) -> bool; + fn trait_is_anti_fundamental(self, def_id: Self::TraitId) -> bool; + /// Returns `true` if this is an `unsafe trait`. fn trait_is_unsafe(self, trait_def_id: Self::TraitId) -> bool; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 473f01660bdb4..e4940551b3741 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2502,7 +2502,7 @@ impl Future for Box { } #[stable(feature = "box_error", since = "1.8.0")] -impl Error for Box { +impl Error for Box { #[allow(deprecated)] fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) diff --git a/library/alloc/src/io/impls.rs b/library/alloc/src/io/impls.rs index 0296cada74171..b16d7b424c163 100644 --- a/library/alloc/src/io/impls.rs +++ b/library/alloc/src/io/impls.rs @@ -92,7 +92,7 @@ impl BufRead for &mut B { } #[stable(feature = "rust1", since = "1.0.0")] -impl Read for Box { +impl Read for Box { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) @@ -148,7 +148,7 @@ impl SizeHint for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl Write for Box { +impl Write for Box { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) @@ -185,7 +185,7 @@ impl Write for Box { } } #[stable(feature = "rust1", since = "1.0.0")] -impl Seek for Box { +impl Seek for Box { #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) @@ -212,7 +212,7 @@ impl Seek for Box { } } #[stable(feature = "rust1", since = "1.0.0")] -impl BufRead for Box { +impl BufRead for Box { #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index a57f3d58e3998..c2d0a740495cd 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -863,6 +863,20 @@ const impl AsMut for str { } } +#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +impl AsRef for ! { + fn as_ref(&self) -> &T { + match *self {} + } +} + +#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +impl AsMut for ! { + fn as_mut(&mut self) -> &mut T { + match *self {} + } +} + //////////////////////////////////////////////////////////////////////////////// // THE NO-ERROR ERROR TYPE //////////////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 58bf0e2d73b97..fffbf1210103d 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -136,6 +136,7 @@ use crate::marker::PointeeSized; #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Deref"] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] +#[rustc_anti_fundamental] pub const trait Deref: PointeeSized { /// The resulting type after dereferencing. #[stable(feature = "rust1", since = "1.0.0")] @@ -267,6 +268,7 @@ const impl Deref for &mut T { #[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] +#[rustc_anti_fundamental] pub const trait DerefMut: [const] Deref + PointeeSized { /// Mutably dereferences the value. #[stable(feature = "rust1", since = "1.0.0")] @@ -367,6 +369,7 @@ unsafe impl DerefPure for &mut T {} /// ``` #[lang = "receiver"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] +#[rustc_anti_fundamental] pub trait Receiver: PointeeSized { /// The target type on which the method may be called. #[rustc_diagnostic_item = "receiver_target"] diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index aade68df2b6ce..9179c1761215d 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -33,6 +33,7 @@ use crate::marker::{PointeeSized, Unsize}; /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "18598")] #[lang = "coerce_unsized"] +#[rustc_anti_fundamental] pub trait CoerceUnsized: Sized { // Empty. } @@ -119,6 +120,7 @@ impl, U: PointeeSized> CoerceUnsized<*const U> for * /// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] +#[rustc_anti_fundamental] pub trait DispatchFromDyn: Sized { // Empty. } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 58e63ff04af15..bb5b0fd50c2dc 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1691,89 +1691,23 @@ const impl Deref for Pin { } } -mod helper { - /// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`. - /// - /// The `Pin` type implements the unsafe trait `PinSafePointer`, which essentially requires - /// that the type does not have a malicious `Deref` or `DerefMut` impl. However, without this - /// helper module, downstream crates are able to write `impl DerefMut for Pin` as - /// long as it does not overlap with the impl provided by stdlib. This is because `Pin` is - /// `#[fundamental]`, so stdlib promises to never implement traits for `Pin` that it does not - /// implement today. - /// - /// However, this is problematic. Downstream crates could implement `DerefMut` for - /// `Pin<&LocalType>`, and they could do so maliciously. To prevent this, the implementation for - /// `Pin` delegates to this helper module. Since `helper::Pin` is not `#[fundamental]`, the - /// orphan rules assume that stdlib might implement `helper::DerefMut` for `helper::Pin<&_>` in - /// the future. Because of this, downstream crates can no longer provide an implementation of - /// `DerefMut` for `Pin<&_>`, as it might overlap with a trait impl that, according to the - /// orphan rules, the stdlib could introduce without a breaking change in a future release. - /// - /// See for the issue this fixes. - #[repr(transparent)] - #[unstable(feature = "pin_derefmut_internals", issue = "none")] - #[allow(missing_debug_implementations)] - pub struct PinHelper { - pointer: Ptr, - } - - #[unstable(feature = "pin_derefmut_internals", issue = "none")] - #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - #[rustc_diagnostic_item = "PinDerefMutHelper"] - pub const trait PinDerefMutHelper { - type Target: ?Sized; - fn deref_mut(&mut self) -> &mut Self::Target; - } - - #[unstable(feature = "pin_derefmut_internals", issue = "none")] - #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - const impl PinDerefMutHelper for PinHelper - where - Ptr::Target: crate::marker::Unpin, - { - type Target = Ptr::Target; - - #[inline(always)] - fn deref_mut(&mut self) -> &mut Ptr::Target { - &mut self.pointer - } - } -} - -#[stable(feature = "pin", since = "1.33.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -#[cfg(not(doc))] -const impl DerefMut for Pin -where - Ptr: [const] Deref, - helper::PinHelper: [const] helper::PinDerefMutHelper, -{ - #[inline] - fn deref_mut(&mut self) -> &mut Ptr::Target { - // SAFETY: Pin and PinHelper have the same layout, so this is equivalent to - // `&mut self.pointer` which is safe because `Target: Unpin`. - helper::PinDerefMutHelper::deref_mut(unsafe { - &mut *(self as *mut Pin as *mut helper::PinHelper) - }) - } -} - /// The `Target` type is restricted to `Unpin` types as it's not safe to obtain a mutable reference /// to a pinned value. /// /// For soundness reasons, implementations of `DerefMut` for `Pin` are rejected even when `T` is /// a local type not covered by this impl block. (Since `Pin` is [fundamental], such implementations -/// would normally be possible.) +/// would normally be possible.) This is enforced by the `#[rustc_anti_fundamental]` attribute on +/// the `DerefMut` trait. /// /// [fundamental]: ../../reference/items/implementations.html#r-items.impl.trait.fundamental #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] -#[cfg(doc)] const impl DerefMut for Pin where Ptr: [const] DerefMut, - ::Target: Unpin, + Ptr::Target: Unpin, { + #[inline] fn deref_mut(&mut self) -> &mut Ptr::Target { Pin::get_mut(Pin::as_mut(self)) } @@ -1953,9 +1887,9 @@ unsafe impl<'a, T: ?Sized> PinSafePointer for &'a mut T {} // The `Pin

` type only implements `DerefMut` when `P: DerefMut` and // `P::Target: Unpin`, so normally downstream crates would be able to provide // an implementation of `DerefMut` for `Pin` when `LocalType` does -// not satisfy those conditions. However, a special hack is used to prevent -// such downstream implementations, so this is not a problem. See -// [#145608](https://github.com/rust-lang/rust/pull/145608) for details. +// not satisfy those conditions. However, `#[rustc_anti_fundamental]` is used to +// prevent such downstream implementations, so this is not a problem. See +// [#160391](https://github.com/rust-lang/rust/pull/160391) for details. // // Conversely, downstream crates are able to implement `Clone`, `Debug` and // `Display` for `Pin` as long as `LocalType` does not implement diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 4ed5c43616a29..87a8e20bad0d3 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -7,6 +7,7 @@ use moto_rt::libc; use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::alloc::Allocator; #[cfg(not(target_os = "trusty"))] use crate::fs; use crate::marker::PhantomData; @@ -474,7 +475,7 @@ impl AsFd for crate::rc::UniqueRc { } #[stable(feature = "asfd_ptrs", since = "1.64.0")] -impl AsFd for Box { +impl AsFd for Box { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index a0c96e2836fc5..a8d981520efd2 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -9,6 +9,7 @@ use moto_rt::libc; #[cfg(target_os = "motor")] use super::owned::OwnedFd; +use crate::alloc::Allocator; #[cfg(not(target_os = "trusty"))] use crate::fs; use crate::io; @@ -282,7 +283,7 @@ impl AsRawFd for crate::rc::UniqueRc { } #[stable(feature = "asrawfd_ptrs", since = "1.63.0")] -impl AsRawFd for Box { +impl AsRawFd for Box { #[inline] fn as_raw_fd(&self) -> RawFd { (**self).as_raw_fd() diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index d4defb5f47fb0..ff79f192819ce 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -46,6 +46,7 @@ #![unstable(feature = "solid_ext", issue = "none")] +use crate::alloc::Allocator; use crate::marker::PhantomData; use crate::mem::ManuallyDrop; use crate::sys::{AsInner, FromInner, IntoInner}; @@ -283,7 +284,7 @@ impl AsFd for crate::rc::Rc { } } -impl AsFd for Box { +impl AsFd for Box { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 29697bbb5f8fc..01bd36155b110 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -3,6 +3,7 @@ #![stable(feature = "io_safety", since = "1.63.0")] use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; +use crate::alloc::Allocator; use crate::marker::PhantomData; use crate::mem::ManuallyDrop; use crate::sys::{AsInner, FromInner, IntoInner, cvt}; @@ -491,7 +492,7 @@ impl AsHandle for crate::rc::UniqueRc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsHandle for Box { +impl AsHandle for Box { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index ae1b7eaee8d12..d625a9ac52730 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -3,6 +3,7 @@ #![stable(feature = "io_safety", since = "1.63.0")] use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +use crate::alloc::Allocator; use crate::marker::PhantomData; use crate::mem::{self, ManuallyDrop}; #[cfg(not(target_vendor = "uwp"))] @@ -275,7 +276,7 @@ impl AsSocket for crate::rc::UniqueRc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsSocket for Box { +impl AsSocket for Box { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { (**self).as_socket() diff --git a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 4b117a453c326..4ad4946c00099 100644 --- a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -58,33 +58,35 @@ + let mut _38: &mut std::future::Ready<()>; + let mut _39: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 13 (inlined > as DerefMut>::deref_mut) { -+ let mut _40: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; -+ let mut _41: *mut std::pin::Pin<&mut std::future::Ready<()>>; -+ scope 14 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { -+ let mut _42: &mut &mut std::future::Ready<()>; -+ scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 14 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _40: &mut &mut std::future::Ready<()>; ++ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } ++ scope 17 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ } ++ } ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 16 (inlined Option::<()>::take) { -+ let mut _43: std::option::Option<()>; -+ scope 17 (inlined std::mem::replace::>) { -+ scope 18 { ++ scope 18 (inlined Option::<()>::take) { ++ let mut _41: std::option::Option<()>; ++ scope 19 (inlined std::mem::replace::>) { ++ scope 20 { + } + } + } -+ scope 19 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _44: isize; -+ let mut _45: !; -+ scope 20 { ++ scope 21 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _42: isize; ++ let mut _43: !; ++ scope 22 { + } + } + } + } + scope 10 (inlined as IntoFuture>::into_future) { + } -+ scope 21 (inlined ready::<()>) { -+ let mut _46: std::option::Option<()>; ++ scope 23 (inlined ready::<()>) { ++ let mut _44: std::option::Option<()>; + } + } + } @@ -179,23 +181,18 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_38); -+ StorageLive(_40); -+ StorageLive(_45); ++ StorageLive(_43); + StorageLive(_35); + StorageLive(_36); ++ _38 = no_retag copy (_19.0: &mut std::future::Ready<()>); + StorageLive(_41); -+ _41 = &raw mut _19; -+ _40 = copy _41 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_41); -+ _38 = no_retag copy ((*_40).0: &mut std::future::Ready<()>); -+ StorageLive(_43); -+ _43 = Option::<()>::None; ++ _41 = Option::<()>::None; + _36 = copy ((*_38).0: std::option::Option<()>); -+ ((*_38).0: std::option::Option<()>) = move _43; -+ StorageDead(_43); -+ StorageLive(_44); -+ _44 = discriminant(_36); -+ switchInt(move _44) -> [0: bb11, 1: bb12, otherwise: bb4]; ++ ((*_38).0: std::option::Option<()>) = move _41; ++ StorageDead(_41); ++ StorageLive(_42); ++ _42 = discriminant(_36); ++ switchInt(move _42) -> [0: bb11, 1: bb12, otherwise: bb4]; + } + bb4: { @@ -262,10 +259,10 @@ + StorageLive(_13); + StorageLive(_14); + _14 = (); -+ StorageLive(_46); -+ _46 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _46); -+ StorageDead(_46); ++ StorageLive(_44); ++ _44 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _44); ++ StorageDead(_44); + StorageDead(_14); + _12 = move _13; + StorageDead(_13); @@ -274,17 +271,16 @@ + } + + bb11: { -+ _45 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ _43 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; + } + + bb12: { + _35 = move ((_36 as Some).0: ()); -+ StorageDead(_44); ++ StorageDead(_42); + StorageDead(_36); + _18 = Poll::<()>::Ready(move _35); + StorageDead(_35); -+ StorageDead(_45); -+ StorageDead(_40); ++ StorageDead(_43); + StorageDead(_38); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index c365aee05f4ec..09c6199fff29e 100644 --- a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -58,33 +58,35 @@ + let mut _38: &mut std::future::Ready<()>; + let mut _39: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 13 (inlined > as DerefMut>::deref_mut) { -+ let mut _40: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; -+ let mut _41: *mut std::pin::Pin<&mut std::future::Ready<()>>; -+ scope 14 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { -+ let mut _42: &mut &mut std::future::Ready<()>; -+ scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 14 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _40: &mut &mut std::future::Ready<()>; ++ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } ++ scope 17 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ } ++ } ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 16 (inlined Option::<()>::take) { -+ let mut _43: std::option::Option<()>; -+ scope 17 (inlined std::mem::replace::>) { -+ scope 18 { ++ scope 18 (inlined Option::<()>::take) { ++ let mut _41: std::option::Option<()>; ++ scope 19 (inlined std::mem::replace::>) { ++ scope 20 { + } + } + } -+ scope 19 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _44: isize; -+ let mut _45: !; -+ scope 20 { ++ scope 21 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _42: isize; ++ let mut _43: !; ++ scope 22 { + } + } + } + } + scope 10 (inlined as IntoFuture>::into_future) { + } -+ scope 21 (inlined ready::<()>) { -+ let mut _46: std::option::Option<()>; ++ scope 23 (inlined ready::<()>) { ++ let mut _44: std::option::Option<()>; + } + } + } @@ -190,23 +192,18 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_38); -+ StorageLive(_40); -+ StorageLive(_45); ++ StorageLive(_43); + StorageLive(_35); + StorageLive(_36); ++ _38 = no_retag copy (_19.0: &mut std::future::Ready<()>); + StorageLive(_41); -+ _41 = &raw mut _19; -+ _40 = copy _41 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_41); -+ _38 = no_retag copy ((*_40).0: &mut std::future::Ready<()>); -+ StorageLive(_43); -+ _43 = Option::<()>::None; ++ _41 = Option::<()>::None; + _36 = copy ((*_38).0: std::option::Option<()>); -+ ((*_38).0: std::option::Option<()>) = move _43; -+ StorageDead(_43); -+ StorageLive(_44); -+ _44 = discriminant(_36); -+ switchInt(move _44) -> [0: bb16, 1: bb17, otherwise: bb6]; ++ ((*_38).0: std::option::Option<()>) = move _41; ++ StorageDead(_41); ++ StorageLive(_42); ++ _42 = discriminant(_36); ++ switchInt(move _42) -> [0: bb16, 1: bb17, otherwise: bb6]; } - bb5 (cleanup): { @@ -295,10 +292,10 @@ + StorageLive(_13); + StorageLive(_14); + _14 = (); -+ StorageLive(_46); -+ _46 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _46); -+ StorageDead(_46); ++ StorageLive(_44); ++ _44 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _44); ++ StorageDead(_44); + StorageDead(_14); + _12 = move _13; + StorageDead(_13); @@ -307,17 +304,16 @@ + } + + bb16: { -+ _45 = option::expect_failed(const "`Ready` polled after completion") -> bb10; ++ _43 = option::expect_failed(const "`Ready` polled after completion") -> bb10; + } + + bb17: { + _35 = move ((_36 as Some).0: ()); -+ StorageDead(_44); ++ StorageDead(_42); + StorageDead(_36); + _18 = Poll::<()>::Ready(move _35); + StorageDead(_35); -+ StorageDead(_45); -+ StorageDead(_40); ++ StorageDead(_43); + StorageDead(_38); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/rustdoc-html/inline_cross/auxiliary/dyn_trait.rs b/tests/rustdoc-html/inline_cross/auxiliary/dyn_trait.rs index 07a95af7b54e8..35bca80ce3f34 100644 --- a/tests/rustdoc-html/inline_cross/auxiliary/dyn_trait.rs +++ b/tests/rustdoc-html/inline_cross/auxiliary/dyn_trait.rs @@ -9,7 +9,7 @@ pub type Ty2 = dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>; pub type Ty3<'s> = &'s dyn ToString; pub trait Container<'r> { - type Item<'a, 'ctx>; + type Item<'a, 'ctx> where Self: Sized; } // Trait-object types inside of a container type that has lifetime bounds ("wrapped"). diff --git a/tests/ui/associated-inherent-types/issue-109789.rs b/tests/ui/associated-inherent-types/issue-109789.rs index e3c490b2dc842..d24e7dbd35ecc 100644 --- a/tests/ui/associated-inherent-types/issue-109789.rs +++ b/tests/ui/associated-inherent-types/issue-109789.rs @@ -18,6 +18,7 @@ impl Other for u32 {} fn bar(_: Foo fn(&'a ())>::Assoc) {} //~^ ERROR mismatched types //~| ERROR mismatched types +//~| ERROR mismatched types //~| ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr index db860a64826d6..b9d851d0cc4aa 100644 --- a/tests/ui/associated-inherent-types/issue-109789.stderr +++ b/tests/ui/associated-inherent-types/issue-109789.stderr @@ -17,6 +17,16 @@ LL | fn bar(_: Foo fn(&'a ())>::Assoc) {} found struct `Foo fn(&'a ())>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0308]: mismatched types + --> $DIR/issue-109789.rs:18:11 + | +LL | fn bar(_: Foo fn(&'a ())>::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo` + found struct `Foo fn(&'a ())>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: higher-ranked subtype error --> $DIR/issue-109789.rs:18:1 | @@ -39,6 +49,6 @@ LL | fn bar(_: Foo fn(&'a ())>::Assoc) {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index cad6d48b1c5af..0c20cd443aa2d 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -10,6 +10,7 @@ impl<'a> Foo { fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} //~^ ERROR mismatched types [E0308] //~| ERROR mismatched types [E0308] +//~| ERROR mismatched types [E0308] //~| ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error //~| ERROR higher-ranked subtype error diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index 9a5b69497c0cf..b2a64fac26030 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -17,6 +17,16 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} found struct `Foo fn(&'b ())>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0308]: mismatched types + --> $DIR/issue-111404-1.rs:10:11 + | +LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo` + found struct `Foo fn(&'b ())>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: higher-ranked subtype error --> $DIR/issue-111404-1.rs:10:1 | @@ -37,6 +47,6 @@ error: higher-ranked subtype error LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-inherent-types/regionck-2.rs b/tests/ui/associated-inherent-types/regionck-2.rs index 573dd359bf2b0..dcbc7139656d8 100644 --- a/tests/ui/associated-inherent-types/regionck-2.rs +++ b/tests/ui/associated-inherent-types/regionck-2.rs @@ -9,7 +9,9 @@ impl Lexer<'static> { type Cursor = (); } -fn test(_: Lexer::Cursor) {} //~ ERROR mismatched types -//~^ ERROR: lifetime may not live long enough +fn test(_: Lexer::Cursor) {} +//~^ ERROR: mismatched types +//~| ERROR: mismatched types +//~| ERROR: lifetime may not live long enough fn main() {} diff --git a/tests/ui/associated-inherent-types/regionck-2.stderr b/tests/ui/associated-inherent-types/regionck-2.stderr index 82f5c6a72c008..9beb34f822666 100644 --- a/tests/ui/associated-inherent-types/regionck-2.stderr +++ b/tests/ui/associated-inherent-types/regionck-2.stderr @@ -13,6 +13,22 @@ LL | fn test(_: Lexer::Cursor) {} | ^^^^^ = note: ...does not necessarily outlive the static lifetime +error[E0308]: mismatched types + --> $DIR/regionck-2.rs:12:12 + | +LL | fn test(_: Lexer::Cursor) {} + | ^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Lexer<'static>` + found struct `Lexer<'_>` +note: the anonymous lifetime defined here... + --> $DIR/regionck-2.rs:12:12 + | +LL | fn test(_: Lexer::Cursor) {} + | ^^^^^ + = note: ...does not necessarily outlive the static lifetime + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: lifetime may not live long enough --> $DIR/regionck-2.rs:12:1 | @@ -22,6 +38,6 @@ LL | fn test(_: Lexer::Cursor) {} | | has type `Lexer<'1>::Cursor` | requires that `'1` must outlive `'static` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.rs b/tests/ui/associated-type-bounds/duplicate-bound-err.rs index 56403fdf6630c..b0e9387ea227b 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.rs @@ -1,10 +1,6 @@ //@ edition: 2024 -#![feature( - min_generic_const_args, - type_alias_impl_trait, - return_type_notation -)] +#![feature(min_generic_const_args, type_alias_impl_trait, return_type_notation)] #![expect(incomplete_features)] #![allow(refining_impl_trait_internal)] @@ -74,12 +70,13 @@ impl Trait for u32 { } fn uncallable(_: impl Iterator) {} +//~^ ERROR type annotations needed fn uncallable_const(_: impl Trait) {} +//~^ ERROR type annotations needed -fn uncallable_rtn( - _: impl Trait, foo(..): Trait> -) {} +fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} +//~^ ERROR type annotations needed type MustFail = dyn Iterator; //~^ ERROR [E0719] diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr index f685b01cd8cc3..0b138adfd9103 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/duplicate-bound-err.rs:14:5 + --> $DIR/duplicate-bound-err.rs:10:5 | LL | iter::empty() | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` @@ -10,7 +10,7 @@ LL | iter::empty::() | ++++++++++++++ error[E0282]: type annotations needed - --> $DIR/duplicate-bound-err.rs:18:5 + --> $DIR/duplicate-bound-err.rs:14:5 | LL | iter::empty() | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` @@ -21,7 +21,7 @@ LL | iter::empty::() | ++++++++++++++ error[E0282]: type annotations needed - --> $DIR/duplicate-bound-err.rs:22:5 + --> $DIR/duplicate-bound-err.rs:18:5 | LL | iter::empty() | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` @@ -32,7 +32,7 @@ LL | iter::empty::() | ++++++++++++++ error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:26:51 + --> $DIR/duplicate-bound-err.rs:22:51 | LL | type Tait1> = impl Copy; | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | type Tait1> = impl Copy; = note: `Tait1` must be used in combination with a concrete type within the same crate error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:28:51 + --> $DIR/duplicate-bound-err.rs:24:51 | LL | type Tait2> = impl Copy; | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | type Tait2> = impl Copy; = note: `Tait2` must be used in combination with a concrete type within the same crate error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:30:57 + --> $DIR/duplicate-bound-err.rs:26:57 | LL | type Tait3> = impl Copy; | ^^^^^^^^^ @@ -56,7 +56,7 @@ LL | type Tait3> = impl Copy; = note: `Tait3` must be used in combination with a concrete type within the same crate error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:33:14 + --> $DIR/duplicate-bound-err.rs:29:14 | LL | type Tait4 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | type Tait4 = impl Iterator; = note: `Tait4` must be used in combination with a concrete type within the same crate error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:35:14 + --> $DIR/duplicate-bound-err.rs:31:14 | LL | type Tait5 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | type Tait5 = impl Iterator; = note: `Tait5` must be used in combination with a concrete type within the same crate error: unconstrained opaque type - --> $DIR/duplicate-bound-err.rs:37:14 + --> $DIR/duplicate-bound-err.rs:33:14 | LL | type Tait6 = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | type Tait6 = impl Iterator; = note: `Tait6` must be used in combination with a concrete type within the same crate error[E0277]: `*const ()` cannot be sent between threads safely - --> $DIR/duplicate-bound-err.rs:40:18 + --> $DIR/duplicate-bound-err.rs:36:18 | LL | fn mismatch() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely @@ -91,7 +91,7 @@ LL | iter::empty::<*const ()>() = help: the trait `Send` is not implemented for `*const ()` error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/duplicate-bound-err.rs:45:20 + --> $DIR/duplicate-bound-err.rs:41:20 | LL | fn mismatch_2() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` @@ -100,7 +100,7 @@ LL | iter::empty::() | ----------------------- return type was inferred to be `std::iter::Empty` here error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:107:17 + --> $DIR/duplicate-bound-err.rs:104:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -109,7 +109,7 @@ LL | [2u32].into_iter() | ------------------ return type was inferred to be `std::array::IntoIter` here | note: the method call chain might not have had the expected associated types - --> $DIR/duplicate-bound-err.rs:110:16 + --> $DIR/duplicate-bound-err.rs:107:16 | LL | [2u32].into_iter() | ------ ^^^^^^^^^^^ `Iterator::Item` is `u32` here @@ -117,19 +117,37 @@ LL | [2u32].into_iter() | this expression has type `[u32; 1]` error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:107:17 + --> $DIR/duplicate-bound-err.rs:104:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | note: required by a bound in `Trait3::foo::{anon_assoc#0}` - --> $DIR/duplicate-bound-err.rs:103:31 + --> $DIR/duplicate-bound-err.rs:100:31 | LL | fn foo() -> impl Iterator; | ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}` +error[E0284]: type annotations needed: cannot satisfy ` as Iterator>::Item == i32` + --> $DIR/duplicate-bound-err.rs:72:32 + | +LL | fn uncallable(_: impl Iterator) {} + | ^^^^^^^^^^ cannot satisfy ` as Iterator>::Item == i32` + +error[E0284]: type annotations needed: cannot satisfy ` as Trait>::ASSOC == 3` + --> $DIR/duplicate-bound-err.rs:75:35 + | +LL | fn uncallable_const(_: impl Trait) {} + | ^^^^^^^^^ cannot satisfy ` as Trait>::ASSOC == 3` + +error[E0284]: type annotations needed: cannot satisfy `, foo(..) : Trait> as Trait>::foo(..) } as Trait>::ASSOC == 3` + --> $DIR/duplicate-bound-err.rs:78:48 + | +LL | fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} + | ^^^^^^^^^ cannot satisfy `, foo(..) : Trait> as Trait>::foo(..) } as Trait>::ASSOC == 3` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:84:42 + --> $DIR/duplicate-bound-err.rs:81:42 | LL | type MustFail = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -137,7 +155,7 @@ LL | type MustFail = dyn Iterator; | `Item` bound here first error: conflicting associated type bindings for `Item` - --> $DIR/duplicate-bound-err.rs:84:17 + --> $DIR/duplicate-bound-err.rs:81:17 | LL | type MustFail = dyn Iterator; | ^^^^^^^^^^^^^----------^^----------^ @@ -146,7 +164,7 @@ LL | type MustFail = dyn Iterator; | `Item` is specified to be `i32` here error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:92:43 + --> $DIR/duplicate-bound-err.rs:89:43 | LL | type MustFail2 = dyn Trait2; | ------------ ^^^^^^^^^^^^ re-bound here @@ -154,7 +172,7 @@ LL | type MustFail2 = dyn Trait2; | `ASSOC` bound here first error: conflicting associated constant bindings for `ASSOC` - --> $DIR/duplicate-bound-err.rs:92:18 + --> $DIR/duplicate-bound-err.rs:89:18 | LL | type MustFail2 = dyn Trait2; | ^^^^^^^^^^^------------^^------------^ @@ -163,7 +181,7 @@ LL | type MustFail2 = dyn Trait2; | `ASSOC` is specified to be `3` here error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:96:43 + --> $DIR/duplicate-bound-err.rs:93:43 | LL | type MustFail3 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -171,7 +189,7 @@ LL | type MustFail3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:99:43 + --> $DIR/duplicate-bound-err.rs:96:43 | LL | type MustFail4 = dyn Trait2; | ------------ ^^^^^^^^^^^^ re-bound here @@ -179,7 +197,7 @@ LL | type MustFail4 = dyn Trait2; | `ASSOC` bound here first error[E0271]: expected `Empty` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:115:16 + --> $DIR/duplicate-bound-err.rs:112:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -187,13 +205,13 @@ LL | uncallable(iter::empty::()); | required by a bound introduced by this call | note: required by a bound in `uncallable` - --> $DIR/duplicate-bound-err.rs:76:32 + --> $DIR/duplicate-bound-err.rs:72:32 | LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: expected `Empty` to be an iterator that yields `u32`, but it yields `i32` - --> $DIR/duplicate-bound-err.rs:116:16 + --> $DIR/duplicate-bound-err.rs:113:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32` @@ -201,13 +219,13 @@ LL | uncallable(iter::empty::()); | required by a bound introduced by this call | note: required by a bound in `uncallable` - --> $DIR/duplicate-bound-err.rs:76:44 + --> $DIR/duplicate-bound-err.rs:72:44 | LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:117:22 + --> $DIR/duplicate-bound-err.rs:114:22 | LL | uncallable_const(()); | ---------------- ^^ expected `4`, found `3` @@ -217,13 +235,13 @@ LL | uncallable_const(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_const` - --> $DIR/duplicate-bound-err.rs:78:46 + --> $DIR/duplicate-bound-err.rs:75:46 | LL | fn uncallable_const(_: impl Trait) {} | ^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:118:22 + --> $DIR/duplicate-bound-err.rs:115:22 | LL | uncallable_const(4u32); | ---------------- ^^^^ expected `3`, found `4` @@ -233,13 +251,13 @@ LL | uncallable_const(4u32); = note: expected constant `3` found constant `4` note: required by a bound in `uncallable_const` - --> $DIR/duplicate-bound-err.rs:78:35 + --> $DIR/duplicate-bound-err.rs:75:35 | LL | fn uncallable_const(_: impl Trait) {} | ^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:119:20 + --> $DIR/duplicate-bound-err.rs:116:20 | LL | uncallable_rtn(()); | -------------- ^^ expected `4`, found `3` @@ -249,15 +267,13 @@ LL | uncallable_rtn(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:81:61 + --> $DIR/duplicate-bound-err.rs:78:75 | -LL | fn uncallable_rtn( - | -------------- required by a bound in this function -LL | _: impl Trait, foo(..): Trait> - | ^^^^^^^^^ required by this bound in `uncallable_rtn` +LL | fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} + | ^^^^^^^^^ required by this bound in `uncallable_rtn` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:120:20 + --> $DIR/duplicate-bound-err.rs:117:20 | LL | uncallable_rtn(17u32); | -------------- ^^^^^ expected `3`, found `4` @@ -267,14 +283,12 @@ LL | uncallable_rtn(17u32); = note: expected constant `3` found constant `4` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:81:34 + --> $DIR/duplicate-bound-err.rs:78:48 | -LL | fn uncallable_rtn( - | -------------- required by a bound in this function -LL | _: impl Trait, foo(..): Trait> - | ^^^^^^^^^ required by this bound in `uncallable_rtn` +LL | fn uncallable_rtn(_: impl Trait, foo(..): Trait>) {} + | ^^^^^^^^^ required by this bound in `uncallable_rtn` -error: aborting due to 25 previous errors +error: aborting due to 28 previous errors -Some errors have detailed explanations: E0271, E0277, E0282, E0719. +Some errors have detailed explanations: E0271, E0277, E0282, E0284, E0719. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/assoc-type-unsatisfied-bound.rs b/tests/ui/associated-types/assoc-type-unsatisfied-bound.rs index 76a93eed7b663..85b7c194e24bb 100644 --- a/tests/ui/associated-types/assoc-type-unsatisfied-bound.rs +++ b/tests/ui/associated-types/assoc-type-unsatisfied-bound.rs @@ -3,6 +3,7 @@ fn add_state(op: ::State) { //~^ ERROR `isize: HasState` is not satisfied //~| ERROR `isize: HasState` is not satisfied +//~| ERROR `isize: HasState` is not satisfied } trait HasState { diff --git a/tests/ui/associated-types/assoc-type-unsatisfied-bound.stderr b/tests/ui/associated-types/assoc-type-unsatisfied-bound.stderr index 3e318fcac503a..b79fdab9cd869 100644 --- a/tests/ui/associated-types/assoc-type-unsatisfied-bound.stderr +++ b/tests/ui/associated-types/assoc-type-unsatisfied-bound.stderr @@ -5,7 +5,7 @@ LL | fn add_state(op: ::State) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` | help: this trait has no implementations, consider adding one - --> $DIR/assoc-type-unsatisfied-bound.rs:8:1 + --> $DIR/assoc-type-unsatisfied-bound.rs:9:1 | LL | trait HasState { | ^^^^^^^^^^^^^^ @@ -17,12 +17,25 @@ LL | fn add_state(op: ::State) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` | help: this trait has no implementations, consider adding one - --> $DIR/assoc-type-unsatisfied-bound.rs:8:1 + --> $DIR/assoc-type-unsatisfied-bound.rs:9:1 | LL | trait HasState { | ^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `isize: HasState` is not satisfied + --> $DIR/assoc-type-unsatisfied-bound.rs:3:18 + | +LL | fn add_state(op: ::State) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` + | +help: this trait has no implementations, consider adding one + --> $DIR/assoc-type-unsatisfied-bound.rs:9:1 + | +LL | trait HasState { + | ^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs index f9b310f6f9b31..b8acd633427b7 100644 --- a/tests/ui/associated-types/issue-59324.rs +++ b/tests/ui/associated-types/issue-59324.rs @@ -22,6 +22,7 @@ pub trait ThriftService: fn with_factory(factory: dyn ThriftService<()>) {} //~^ ERROR the trait bound `(): Foo` is not satisfied //~| ERROR the trait bound `(): Foo` is not satisfied +//~| ERROR the trait bound `(): Foo` is not satisfied //~| ERROR cannot be known at compilation time fn main() {} diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index 929238dc29b15..7c92def535901 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -11,6 +11,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo` LL | pub trait ThriftService: | +++++ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/issue-59324.rs:22:29 + | +LL | fn with_factory(factory: dyn ThriftService<()>) {} + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-59324.rs:3:1 + | +LL | pub trait Foo: NotFoo { + | ^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:15:5 | @@ -32,6 +44,7 @@ help: this trait has no implementations, consider adding one | LL | pub trait Foo: NotFoo { | ^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:15:5 @@ -79,6 +92,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn with_factory(factory: &dyn ThriftService<()>) {} | + -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/projection-dyn-associated-type.rs b/tests/ui/associated-types/projection-dyn-associated-type.rs index 32328f8793c71..b446ff5b863b3 100644 --- a/tests/ui/associated-types/projection-dyn-associated-type.rs +++ b/tests/ui/associated-types/projection-dyn-associated-type.rs @@ -23,6 +23,7 @@ pub fn foo<'a>( ) -> &'a ::Assoc { //~^ ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277] //~| ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277] + //~| ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277] static } //~ ERROR expected identifier, found `}` diff --git a/tests/ui/associated-types/projection-dyn-associated-type.stderr b/tests/ui/associated-types/projection-dyn-associated-type.stderr index 58eb8cff163db..3c711c416bbc6 100644 --- a/tests/ui/associated-types/projection-dyn-associated-type.stderr +++ b/tests/ui/associated-types/projection-dyn-associated-type.stderr @@ -1,5 +1,5 @@ error: expected identifier, found `}` - --> $DIR/projection-dyn-associated-type.rs:27:1 + --> $DIR/projection-dyn-associated-type.rs:28:1 | LL | } | ^ expected identifier @@ -54,7 +54,20 @@ LL | impl Mirror for A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors; 1 warning emitted +error[E0277]: the trait bound `(dyn B + 'static): Mirror` is not satisfied + --> $DIR/projection-dyn-associated-type.rs:23:6 + | +LL | ) -> &'a ::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `(dyn B + 'static)` + | +help: the trait `Mirror` is implemented for `dyn A` + --> $DIR/projection-dyn-associated-type.rs:14:1 + | +LL | impl Mirror for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors; 1 warning emitted Some errors have detailed explanations: E0207, E0277. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.rs b/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.rs new file mode 100644 index 0000000000000..2828647348712 --- /dev/null +++ b/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.rs @@ -0,0 +1,32 @@ +//! Regression test for . On assignment statements, +//! borrowck's dataflow analysis kills borrows that it knows conflict with the assigment: a borrow +//! of a place can't be live anymore after that place is assigned over. Previously, this didn't +//! account for fake borrows being shallow: it would kill any shallow borrows that would have +//! conflicted if they were normal borrows. This made it possible to circumvent fake borrows for +//! match guards and indexing expressions. + +fn test_match_guard() { + let mut a = (Some(&42u64), 0u8); + let mut b = (None::<&u64>, 0u8); + let mut p = &mut a; + // Writing to `(*p).1` in the match guard previously killed the fake borrow of `p` in the guard, + // making it possible to mutate `p` despite `(*p).0` being matched on. This would reach the + // `Some(r)` branch with `(*p).0` being `None`, so the `r` binding was invalid. + match p.0 { + Some(_) if { p.1 = 1; p = &mut b; false } => unreachable!(), + //~^ ERROR: cannot assign `p` in match guard + Some(r) => println!("{r}"), + None => unreachable!(), + } +} + +fn test_indexing() { + let mut x: &mut [&mut [u32]] = &mut [&mut [0]]; + let y: &mut [&mut [u32]] = &mut []; + // Writing to `x[0][0]` previously killed the fake borrow of `x` in the index expression, making + // it possible to access `y[0]` without a bounds-check. + x[0][{ x[0][0] = 1; x = y; 0 }]; + //~^ ERROR: cannot assign `x` in indexing expression +} + +fn main() {} diff --git a/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.stderr b/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.stderr new file mode 100644 index 0000000000000..b45a75a9c6340 --- /dev/null +++ b/tests/ui/borrowck/dont-kill-shallow-borrows-on-child-writes.stderr @@ -0,0 +1,19 @@ +error[E0510]: cannot assign `p` in match guard + --> $DIR/dont-kill-shallow-borrows-on-child-writes.rs:16:31 + | +LL | match p.0 { + | --- value is immutable in match guard +LL | Some(_) if { p.1 = 1; p = &mut b; false } => unreachable!(), + | ^^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `x` in indexing expression + --> $DIR/dont-kill-shallow-borrows-on-child-writes.rs:28:25 + | +LL | x[0][{ x[0][0] = 1; x = y; 0 }]; + | ---- ^^^^^ cannot assign + | | + | value is immutable in indexing expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/borrowck/index-after-constantindex.rs b/tests/ui/borrowck/index-after-constantindex.rs new file mode 100644 index 0000000000000..5d78db4e411f5 --- /dev/null +++ b/tests/ui/borrowck/index-after-constantindex.rs @@ -0,0 +1,8 @@ +// test that an Index projection fails after a sibling ConstantIndex projection is moved out of +// regression test for #160525 + +fn main() { + let mut arr = [[Box::new(42)]]; + let alias = &mut arr[0][{ let [row] = arr; drop(row); 0 }]; //~ ERROR + println!("{}", **alias); // use-after-free of arr's dead stack slot +} diff --git a/tests/ui/borrowck/index-after-constantindex.stderr b/tests/ui/borrowck/index-after-constantindex.stderr new file mode 100644 index 0000000000000..d31a57df20a01 --- /dev/null +++ b/tests/ui/borrowck/index-after-constantindex.stderr @@ -0,0 +1,18 @@ +error[E0382]: borrow of moved value: `arr[..]` + --> $DIR/index-after-constantindex.rs:6:17 + | +LL | let alias = &mut arr[0][{ let [row] = arr; drop(row); 0 }]; + | ^^^^^^^^^^^^^^^^^^^---^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | value moved here + | value borrowed here after move + | + = note: move occurs because `arr[..]` has type `[Box; 1]`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let alias = &mut arr[0][{ let [ref row] = arr; drop(row); 0 }]; + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/coherence/anti-fundamental-foreign-type.rs b/tests/ui/coherence/anti-fundamental-foreign-type.rs new file mode 100644 index 0000000000000..bd9ca9542f939 --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-foreign-type.rs @@ -0,0 +1,85 @@ +//@ aux-build: anti_fundamental_trait_lib.rs + +// Test that `#[rustc_anti_fundamental]` prevents implementing the trait +// on non-local `#[fundamental]` types. + +#![feature(fundamental)] + +extern crate anti_fundamental_trait_lib; + +use anti_fundamental_trait_lib::{ + AntiFundamentalTrait, AntiFundamentalWithParam, FundamentalWrapper, NonFundamentalWrapper, +}; + +struct LocalType; + +#[fundamental] +struct LocalFundamental(T); + +// OK: implementing on a local type. +impl AntiFundamentalTrait for LocalType {} + +// ERROR: implementing on a non-fundamental foreign type wrapping a local type +impl AntiFundamentalTrait for NonFundamentalWrapper {} +//~^ ERROR only traits defined in the current crate + +// ERROR: implementing on a foreign fundamental type. +impl AntiFundamentalTrait for FundamentalWrapper {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: implementing on a reference to a foreign fundamental type. +impl AntiFundamentalTrait for &FundamentalWrapper {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: implementing on a mutable double-reference to a foreign fundamental type. +impl AntiFundamentalTrait for &mut &FundamentalWrapper {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// OK: outer type is local fundamental, so the Self type is local. +impl AntiFundamentalTrait for LocalFundamental> {} + +// ERROR: outer type is foreign fundamental. +impl AntiFundamentalTrait for FundamentalWrapper> {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// OK: Self is a local type, even if the trait parameter is a foreign fundamental type. +impl AntiFundamentalWithParam> for LocalType {} + +// ERROR: Self is a foreign fundamental type. +impl AntiFundamentalWithParam for FundamentalWrapper {} +//~^ ERROR cannot implement `AntiFundamentalWithParam` for the fundamental type + +// ERROR: projection normalizes to a foreign fundamental type. +struct LocalType2; +trait AssocHelper { + type Assoc; +} + +impl AssocHelper for LocalType2 { + type Assoc = FundamentalWrapper; +} + +impl AntiFundamentalTrait for ::Assoc {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: foreign fundamental type wrapping a generic local type. +struct LocalGeneric(T); + +impl AntiFundamentalTrait for FundamentalWrapper> {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: reference to a foreign fundamental type wrapping a generic local type. +impl AntiFundamentalTrait for &FundamentalWrapper> {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: single mutable reference to a foreign fundamental type. +impl AntiFundamentalTrait for &mut FundamentalWrapper {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +// ERROR: type alias expanding to a foreign fundamental type. +struct LocalType3; +type LocalAlias = FundamentalWrapper; +impl AntiFundamentalTrait for LocalAlias {} +//~^ ERROR cannot implement `AntiFundamentalTrait` for the fundamental type + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-foreign-type.stderr b/tests/ui/coherence/anti-fundamental-foreign-type.stderr new file mode 100644 index 0000000000000..f61788390510b --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-foreign-type.stderr @@ -0,0 +1,95 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/anti-fundamental-foreign-type.rs:23:1 + | +LL | impl AntiFundamentalTrait for NonFundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------- + | | + | `NonFundamentalWrapper` is not defined in the current crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:27:31 + | +LL | impl AntiFundamentalTrait for FundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `FundamentalWrapper` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:31:31 + | +LL | impl AntiFundamentalTrait for &FundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `&FundamentalWrapper` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:35:31 + | +LL | impl AntiFundamentalTrait for &mut &FundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `&mut &FundamentalWrapper` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper>` + --> $DIR/anti-fundamental-foreign-type.rs:42:31 + | +LL | impl AntiFundamentalTrait for FundamentalWrapper> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `FundamentalWrapper>` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:62:31 + | +LL | impl AntiFundamentalTrait for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `::Assoc` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper>` + --> $DIR/anti-fundamental-foreign-type.rs:68:34 + | +LL | impl AntiFundamentalTrait for FundamentalWrapper> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `FundamentalWrapper>` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper>` + --> $DIR/anti-fundamental-foreign-type.rs:72:34 + | +LL | impl AntiFundamentalTrait for &FundamentalWrapper> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `&FundamentalWrapper>` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:76:31 + | +LL | impl AntiFundamentalTrait for &mut FundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `&mut FundamentalWrapper` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalTrait` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:82:31 + | +LL | impl AntiFundamentalTrait for LocalAlias {} + | ^^^^^^^^^^ impl of `AntiFundamentalTrait` not allowed for `FundamentalWrapper` + | + = note: `AntiFundamentalTrait` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `AntiFundamentalWithParam` for the fundamental type `FundamentalWrapper` + --> $DIR/anti-fundamental-foreign-type.rs:49:46 + | +LL | impl AntiFundamentalWithParam for FundamentalWrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `AntiFundamentalWithParam` not allowed for `FundamentalWrapper` + | + = note: `AntiFundamentalWithParam` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/anti-fundamental-generic-projection.rs b/tests/ui/coherence/anti-fundamental-generic-projection.rs new file mode 100644 index 0000000000000..26e22f771d3e4 --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-generic-projection.rs @@ -0,0 +1,77 @@ +//@ aux-build: anti_fundamental_trait_lib.rs + +// Test that generic projections cannot bypass #[rustc_anti_fundamental] +// due to normalization failure or compat mode. + +extern crate anti_fundamental_trait_lib; + +use anti_fundamental_trait_lib::{ + AntiFundamentalTrait, AntiFundamentalWithParam, FundamentalWrapper, +}; + +struct LocalGeneric(T); +struct LocalGeneric2(T); + +trait GenericAssocHelper { + type Assoc; +} + +impl GenericAssocHelper for LocalGeneric { + type Assoc = FundamentalWrapper>; +} + +// ERROR: Generic projections normalize at coherence time, but +// we reject as a hard error because Compat mode is disallowed for anti-fundamental traits. +impl AntiFundamentalWithParam> +//~^ ERROR type parameter `T` must be covered by another type + for as GenericAssocHelper>::Assoc +{ +} + +// ERROR: Generic projection with bounds is similarly hard rejected. +trait BoundedHelper { + type Assoc; +} + +impl BoundedHelper for LocalGeneric2 { + type Assoc = FundamentalWrapper>; +} + +impl AntiFundamentalWithParam> +//~^ ERROR type parameter `T` must be covered by another type + for as BoundedHelper>::Assoc +{ +} + +// Blanket implementation attempting to implement an anti-fundamental trait +// on a projection where the type parameter is constrained by the trait: +// rejected by the orphan rule (E0210) because T is not behind a local type. +trait Helper2 { + type T; +} + +impl AntiFundamentalWithParam for ::T { + //~^ ERROR type parameter `T` must be used as an argument to some local type +} + +impl Helper2 for FundamentalWrapper { + type T = T; +} + +// Blanket implementation of a parameterless anti-fundamental trait (like `Deref`) +// on an associated type projection: rejected both by the orphan rule (E0210) +// and because T is unconstrained (E0207). +trait Helper3 { + type T; +} + +impl AntiFundamentalTrait for ::T { + //~^ ERROR type parameter `T` must be used as an argument to some local type + //~| ERROR the type parameter `T` is not constrained +} + +impl Helper3 for FundamentalWrapper { + type T = T; +} + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-generic-projection.stderr b/tests/ui/coherence/anti-fundamental-generic-projection.stderr new file mode 100644 index 0000000000000..b91ae4307149c --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-generic-projection.stderr @@ -0,0 +1,50 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalGeneric<_>`) + --> $DIR/anti-fundamental-generic-projection.rs:25:6 + | +LL | impl AntiFundamentalWithParam> + | ^ uncovered type parameter + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, + and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, + where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`LocalGeneric2<_>`) + --> $DIR/anti-fundamental-generic-projection.rs:40:6 + | +LL | impl AntiFundamentalWithParam> + | ^ uncovered type parameter + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, + and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, + where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct`) + --> $DIR/anti-fundamental-generic-projection.rs:53:6 + | +LL | impl AntiFundamentalWithParam for ::T { + | ^ uncovered type parameter + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct`) + --> $DIR/anti-fundamental-generic-projection.rs:68:6 + | +LL | impl AntiFundamentalTrait for ::T { + | ^ uncovered type parameter + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/anti-fundamental-generic-projection.rs:68:6 + | +LL | impl AntiFundamentalTrait for ::T { + | ^ unconstrained type parameter + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0207, E0210. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/coherence/anti-fundamental-invalid-target.rs b/tests/ui/coherence/anti-fundamental-invalid-target.rs new file mode 100644 index 0000000000000..49f7f7508ac7d --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-invalid-target.rs @@ -0,0 +1,18 @@ +// Test that `#[rustc_anti_fundamental]` can only be applied to traits. +// The target restriction is enforced declaratively by `ALLOWED_TARGETS` +// in the attribute parser, so applying it to a non-trait is an error. + +#![feature(rustc_attrs)] + +#[rustc_anti_fundamental] +//~^ ERROR attribute cannot be used on +struct NotATrait; + +#[rustc_anti_fundamental] +//~^ ERROR attribute cannot be used on +fn also_not_a_trait() {} + +#[rustc_anti_fundamental] +trait Ok {} + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-invalid-target.stderr b/tests/ui/coherence/anti-fundamental-invalid-target.stderr new file mode 100644 index 0000000000000..26438d465a81a --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-invalid-target.stderr @@ -0,0 +1,18 @@ +error: the `rustc_anti_fundamental` attribute cannot be used on structs + --> $DIR/anti-fundamental-invalid-target.rs:7:3 + | +LL | #[rustc_anti_fundamental] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `rustc_anti_fundamental` attribute can only be applied to traits + +error: the `rustc_anti_fundamental` attribute cannot be used on functions + --> $DIR/anti-fundamental-invalid-target.rs:11:3 + | +LL | #[rustc_anti_fundamental] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `rustc_anti_fundamental` attribute can only be applied to traits + +error: aborting due to 2 previous errors + diff --git a/tests/ui/coherence/anti-fundamental-local-trait.rs b/tests/ui/coherence/anti-fundamental-local-trait.rs new file mode 100644 index 0000000000000..33c81e50494f8 --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-local-trait.rs @@ -0,0 +1,23 @@ +//@ check-pass + +// Test that `#[rustc_anti_fundamental]` does NOT block local traits. +// If the trait itself is local, orphan rules pass even on fundamental types. + +#![feature(fundamental)] +#![feature(rustc_attrs)] + +#[fundamental] +struct LocalFundamental(T); + +#[rustc_anti_fundamental] +trait AntiFundamentalTrait {} + +struct LocalType; + +// OK: both trait and fundamental type are local. +impl AntiFundamentalTrait for LocalFundamental {} + +// OK: implementing on a local non-fundamental type. +impl AntiFundamentalTrait for LocalType {} + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-overlap.rs b/tests/ui/coherence/anti-fundamental-overlap.rs new file mode 100644 index 0000000000000..08e983fba9802 --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-overlap.rs @@ -0,0 +1,19 @@ +//@ aux-build: anti_fundamental_trait_lib.rs +//@ dont-require-annotations: NOTE + +// Test that `#[rustc_anti_fundamental]` prevents reporting +// "downstream crates may implement trait" ambiguity notes, +// and instead reports that only upstream crates can add such an impl. + +extern crate anti_fundamental_trait_lib; + +use anti_fundamental_trait_lib::{AntiFundamentalTrait, FundamentalWrapper}; + +trait Trait1 {} +impl Trait1 for T {} +impl Trait1 for FundamentalWrapper { + //~^ ERROR conflicting implementations of trait `Trait1` for type `FundamentalWrapper<_>` + //~| NOTE upstream crates may add a new impl of trait `anti_fundamental_trait_lib::AntiFundamentalTrait` for type `anti_fundamental_trait_lib::FundamentalWrapper<_>` in future versions +} + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-overlap.stderr b/tests/ui/coherence/anti-fundamental-overlap.stderr new file mode 100644 index 0000000000000..8d35e7a17d932 --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-overlap.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait1` for type `FundamentalWrapper<_>` + --> $DIR/anti-fundamental-overlap.rs:14:1 + | +LL | impl Trait1 for T {} + | ------------------------------------------ first implementation here +LL | impl Trait1 for FundamentalWrapper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FundamentalWrapper<_>` + | + = note: upstream crates may add a new impl of trait `anti_fundamental_trait_lib::AntiFundamentalTrait` for type `anti_fundamental_trait_lib::FundamentalWrapper<_>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/anti-fundamental-std-traits.rs b/tests/ui/coherence/anti-fundamental-std-traits.rs new file mode 100644 index 0000000000000..20d0c0b219b9e --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-std-traits.rs @@ -0,0 +1,81 @@ +//@ check-fail + +// Test that `#[rustc_anti_fundamental]` on std traits (Deref, Receiver, +// CoerceUnsized, DispatchFromDyn) prevents implementing them for foreign +// fundamental types like `Pin`. + +#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn)] + +use std::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; +use std::pin::Pin; + +struct LocalType; +struct LocalType2; + +// ERROR: cannot implement Deref for Pin +impl Deref for Pin { + type Target = LocalType; + fn deref(&self) -> &LocalType { + unimplemented!() + } +} +//~^^^^^^ ERROR cannot implement `Deref` for the fundamental type + +// ERROR: cannot implement DerefMut for Pin +impl DerefMut for Pin { + fn deref_mut(&mut self) -> &mut LocalType { + unimplemented!() + } +} +//~^^^^^ ERROR cannot implement `DerefMut` for the fundamental type + +// ERROR: cannot implement Receiver for Pin +impl Receiver for Pin { + type Target = LocalType; +} +//~^^^ ERROR cannot implement `std::ops::Receiver` for the fundamental type + +// ERROR: cannot implement CoerceUnsized for Pin +impl CoerceUnsized> for Pin {} +//~^ ERROR cannot implement `CoerceUnsized` for the fundamental type +//~| ERROR the trait bound `LocalType: CoerceUnsized` is not satisfied + +// ERROR: cannot implement DispatchFromDyn for Pin +impl DispatchFromDyn> for Pin {} +//~^ ERROR cannot implement `DispatchFromDyn` for the fundamental type + +struct LocalBoxType; + +// ERROR: cannot implement Deref for Box +impl Deref for Box { + type Target = LocalBoxType; + fn deref(&self) -> &LocalBoxType { + unimplemented!() + } +} +//~^^^^^^ ERROR cannot implement `Deref` for the fundamental type + +// ERROR: cannot implement DerefMut for Box +impl DerefMut for Box { + fn deref_mut(&mut self) -> &mut LocalBoxType { + unimplemented!() + } +} +//~^^^^^ ERROR cannot implement `DerefMut` for the fundamental type + +// ERROR: cannot implement Deref for &Pin +impl Deref for &Pin { + type Target = LocalType; + fn deref(&self) -> &LocalType { + unimplemented!() + } +} +//~^^^^^^ ERROR cannot implement `Deref` for the fundamental type + +// ERROR: cannot implement Receiver for Box +impl Receiver for Box { + type Target = LocalBoxType; +} +//~^^^ ERROR cannot implement `std::ops::Receiver` for the fundamental type + +fn main() {} diff --git a/tests/ui/coherence/anti-fundamental-std-traits.stderr b/tests/ui/coherence/anti-fundamental-std-traits.stderr new file mode 100644 index 0000000000000..3aa6ad742b7bc --- /dev/null +++ b/tests/ui/coherence/anti-fundamental-std-traits.stderr @@ -0,0 +1,87 @@ +error: cannot implement `Deref` for the fundamental type `Box` + --> $DIR/anti-fundamental-std-traits.rs:50:16 + | +LL | impl Deref for Box { + | ^^^^^^^^^^^^^^^^^ impl of `Deref` not allowed for `Box` + | + = note: `Deref` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `Deref` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:67:16 + | +LL | impl Deref for &Pin { + | ^^^^^^^^^^^^^^^ impl of `Deref` not allowed for `&Pin` + | + = note: `Deref` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `Deref` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:16:16 + | +LL | impl Deref for Pin { + | ^^^^^^^^^^^^^^ impl of `Deref` not allowed for `Pin` + | + = note: `Deref` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `DerefMut` for the fundamental type `Box` + --> $DIR/anti-fundamental-std-traits.rs:59:19 + | +LL | impl DerefMut for Box { + | ^^^^^^^^^^^^^^^^^ impl of `DerefMut` not allowed for `Box` + | + = note: `DerefMut` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `DerefMut` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:25:19 + | +LL | impl DerefMut for Pin { + | ^^^^^^^^^^^^^^ impl of `DerefMut` not allowed for `Pin` + | + = note: `DerefMut` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `std::ops::Receiver` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:33:19 + | +LL | impl Receiver for Pin { + | ^^^^^^^^^^^^^^ impl of `std::ops::Receiver` not allowed for `Pin` + | + = note: `std::ops::Receiver` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `std::ops::Receiver` for the fundamental type `Box` + --> $DIR/anti-fundamental-std-traits.rs:76:19 + | +LL | impl Receiver for Box { + | ^^^^^^^^^^^^^^^^^ impl of `std::ops::Receiver` not allowed for `Box` + | + = note: `std::ops::Receiver` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: cannot implement `CoerceUnsized` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:39:41 + | +LL | impl CoerceUnsized> for Pin {} + | ^^^^^^^^^^^^^^ impl of `CoerceUnsized` not allowed for `Pin` + | + = note: `CoerceUnsized` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error[E0277]: the trait bound `LocalType: CoerceUnsized` is not satisfied + --> $DIR/anti-fundamental-std-traits.rs:39:1 + | +LL | impl CoerceUnsized> for Pin {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the nightly-only, unstable trait `CoerceUnsized` is not implemented for `LocalType` + --> $DIR/anti-fundamental-std-traits.rs:12:1 + | +LL | struct LocalType; + | ^^^^^^^^^^^^^^^^ + +error: cannot implement `DispatchFromDyn` for the fundamental type `Pin` + --> $DIR/anti-fundamental-std-traits.rs:44:43 + | +LL | impl DispatchFromDyn> for Pin {} + | ^^^^^^^^^^^^^^ impl of `DispatchFromDyn` not allowed for `Pin` + | + = note: `DispatchFromDyn` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coherence/auxiliary/anti_fundamental_trait_lib.rs b/tests/ui/coherence/auxiliary/anti_fundamental_trait_lib.rs new file mode 100644 index 0000000000000..177874d30432b --- /dev/null +++ b/tests/ui/coherence/auxiliary/anti_fundamental_trait_lib.rs @@ -0,0 +1,15 @@ +// Auxiliary crate for anti-fundamental coherence tests. + +#![feature(fundamental)] +#![feature(rustc_attrs)] + +#[fundamental] +pub struct FundamentalWrapper(pub T); + +pub struct NonFundamentalWrapper(pub T); + +#[rustc_anti_fundamental] +pub trait AntiFundamentalTrait {} + +#[rustc_anti_fundamental] +pub trait AntiFundamentalWithParam {} diff --git a/tests/ui/conditional-compilation/cfg-generic-params.rs b/tests/ui/conditional-compilation/cfg-generic-params.rs index 6480a0f24794c..9044fd65ac978 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.rs +++ b/tests/ui/conditional-compilation/cfg-generic-params.rs @@ -7,8 +7,8 @@ type FnGood = for<#[cfg(yes)] 'a, #[cfg(false)] T> fn(); // OK type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn(); //~^ ERROR only lifetime parameters can be used in this context -type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(false)] T> Copy; // OK -type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy; +type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(false)] T> std::any::Any; // OK +type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> std::any::Any; //~^ ERROR only lifetime parameters can be used in this context struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(false)] T> u8: Copy; // OK @@ -26,8 +26,8 @@ type FnNo = for<#[cfg_attr(FALSE, unknown)] 'a> fn(); // OK type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); //~^ ERROR cannot find attribute `unknown` in this scope -type PolyNo = dyn for<#[cfg_attr(FALSE, unknown)] 'a> Copy; // OK -type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; +type PolyNo = dyn for<#[cfg_attr(FALSE, unknown)] 'a> std::any::Any; // OK +type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> std::any::Any; //~^ ERROR cannot find attribute `unknown` in this scope struct WhereNo where for<#[cfg_attr(FALSE, unknown)] 'a> u8: Copy; // OK diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr index bae75dd0deb03..572ff815e351e 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.stderr +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -19,7 +19,7 @@ LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); error: cannot find attribute `unknown` in this scope --> $DIR/cfg-generic-params.rs:30:40 | -LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; +LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> std::any::Any; | ^^^^^^^ error: cannot find attribute `unknown` in this scope @@ -41,7 +41,7 @@ LL | type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn(); error[E0658]: only lifetime parameters can be used in this context --> $DIR/cfg-generic-params.rs:11:54 | -LL | type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy; +LL | type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> std::any::Any; | ^ | = note: see issue #108185 for more information diff --git a/tests/ui/deref/pin-impl-deref.rs b/tests/ui/deref/pin-impl-deref.rs index ccd8d0dfc72ae..b1dc8dea3f248 100644 --- a/tests/ui/deref/pin-impl-deref.rs +++ b/tests/ui/deref/pin-impl-deref.rs @@ -22,7 +22,7 @@ impl MyPinType { fn impl_deref_mut(_: impl DerefMut) {} fn unpin_impl_ref(r_unpin: Pin<&MyUnpinType>) { impl_deref_mut(r_unpin) - //~^ ERROR: the trait bound `&MyUnpinType: DerefMut` is not satisfied + //~^ ERROR: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied } fn unpin_impl_mut(r_unpin: Pin<&mut MyUnpinType>) { impl_deref_mut(r_unpin) @@ -30,7 +30,7 @@ fn unpin_impl_mut(r_unpin: Pin<&mut MyUnpinType>) { fn pin_impl_ref(r_pin: Pin<&MyPinType>) { impl_deref_mut(r_pin) //~^ ERROR: `PhantomPinned` cannot be unpinned - //~| ERROR: the trait bound `&MyPinType: DerefMut` is not satisfied + //~| ERROR: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied } fn pin_impl_mut(r_pin: Pin<&mut MyPinType>) { impl_deref_mut(r_pin) diff --git a/tests/ui/deref/pin-impl-deref.stderr b/tests/ui/deref/pin-impl-deref.stderr index 4143d66f42723..106654641a117 100644 --- a/tests/ui/deref/pin-impl-deref.stderr +++ b/tests/ui/deref/pin-impl-deref.stderr @@ -1,34 +1,40 @@ -error[E0277]: the trait bound `&MyUnpinType: DerefMut` is not satisfied +error[E0277]: the trait bound `Pin<&MyUnpinType>: DerefMut` is not satisfied --> $DIR/pin-impl-deref.rs:24:20 | LL | impl_deref_mut(r_unpin) - | -------------- ^^^^^^^ the trait `DerefMut` is not implemented for `&MyUnpinType` + | -------------- ^^^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyUnpinType>` | | | required by a bound introduced by this call | - = note: `DerefMut` is implemented for `&mut MyUnpinType`, but not for `&MyUnpinType` = note: required for `Pin<&MyUnpinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 | LL | fn impl_deref_mut(_: impl DerefMut) {} | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_unpin) + | ++++ -error[E0277]: the trait bound `&MyPinType: DerefMut` is not satisfied +error[E0277]: the trait bound `Pin<&MyPinType>: DerefMut` is not satisfied --> $DIR/pin-impl-deref.rs:31:20 | LL | impl_deref_mut(r_pin) - | -------------- ^^^^^ the trait `DerefMut` is not implemented for `&MyPinType` + | -------------- ^^^^^ the trait `DerefMut` is not implemented for `Pin<&MyPinType>` | | | required by a bound introduced by this call | - = note: `DerefMut` is implemented for `&mut MyPinType`, but not for `&MyPinType` = note: required for `Pin<&MyPinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 | LL | fn impl_deref_mut(_: impl DerefMut) {} | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_pin) + | ++++ error[E0277]: `PhantomPinned` cannot be unpinned --> $DIR/pin-impl-deref.rs:31:20 diff --git a/tests/ui/dyn-compatibility/in-unchecked-type-alias.rs b/tests/ui/dyn-compatibility/in-unchecked-type-alias.rs new file mode 100644 index 0000000000000..8a83b6a4de68a --- /dev/null +++ b/tests/ui/dyn-compatibility/in-unchecked-type-alias.rs @@ -0,0 +1,15 @@ +// FIXME(fmease): Write a description. + +type DynIncompat0 = dyn Sized; //~ ERROR not dyn compatible + +// FIXME(fmease): Well, if this breakage got accepted linking to this issue +// would be moot / nonsensical. Remove the link. +// issue: +type DynIncompat1 = dyn HasAssocConst; //~ ERROR not dyn compatible + +type DynIncompat2<'a> = dyn HasGenericAssocType = ()>; //~ ERROR not dyn compatible + +trait HasAssocConst { const N: usize; } +trait HasGenericAssocType { type Type; } + +fn main() {} diff --git a/tests/ui/dyn-compatibility/in-unchecked-type-alias.stderr b/tests/ui/dyn-compatibility/in-unchecked-type-alias.stderr new file mode 100644 index 0000000000000..edcc748e0d192 --- /dev/null +++ b/tests/ui/dyn-compatibility/in-unchecked-type-alias.stderr @@ -0,0 +1,45 @@ +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/in-unchecked-type-alias.rs:3:1 + | +LL | type DynIncompat0 = dyn Sized; + | ^^^^^^^^^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error[E0038]: the trait `HasAssocConst` is not dyn compatible + --> $DIR/in-unchecked-type-alias.rs:8:1 + | +LL | type DynIncompat1 = dyn HasAssocConst; + | ^^^^^^^^^^^^^^^^^ `HasAssocConst` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/in-unchecked-type-alias.rs:12:29 + | +LL | trait HasAssocConst { const N: usize; } + | ------------- ^ ...because it contains associated const `N` + | | + | this trait is not dyn compatible... + = help: consider moving `N` to another trait + +error[E0038]: the trait `HasGenericAssocType` is not dyn compatible + --> $DIR/in-unchecked-type-alias.rs:10:1 + | +LL | type DynIncompat2<'a> = dyn HasGenericAssocType = ()>; + | ^^^^^^^^^^^^^^^^^^^^^ `HasGenericAssocType` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/in-unchecked-type-alias.rs:13:34 + | +LL | trait HasGenericAssocType { type Type; } + | ------------------- ^^^^ ...because it contains generic associated type `Type` + | | + | this trait is not dyn compatible... + = help: consider moving `Type` to another trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/hygiene/assoc_ty_bindings.rs b/tests/ui/hygiene/assoc_ty_bindings.rs index 5e42e27062fbd..f548b892a7049 100644 --- a/tests/ui/hygiene/assoc_ty_bindings.rs +++ b/tests/ui/hygiene/assoc_ty_bindings.rs @@ -4,10 +4,10 @@ trait Base { type AssocTy; - fn f(); + fn f(self); } trait Derived: Base { - fn g(); + fn g(self); } macro mac() { @@ -16,12 +16,12 @@ macro mac() { impl Base for u8 { type AssocTy = u8; - fn f() { + fn f(self) { let _: Self::AssocTy; } } impl Derived for u8 { - fn g() { + fn g(self) { let _: Self::AssocTy; } } diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr index dc566ad50153a..54ea4882c4669 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr @@ -1,16 +1,11 @@ -error[E0277]: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:7:13 | LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `!` + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` ... -LL | todo!() - | ------- return type was inferred to be `!` here - | -help: `!` can be coerced to any type; consider casting it to a concrete type that implements the trait - | -LL | todo!() as /* Type */ - | +++++++++++++ +LL | () + | -- return type was inferred to be `()` here error: aborting due to 1 previous error 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 64311a474cade..6c538e8c8ee16 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,10 +5,10 @@ #![allow(warnings)] fn ice() -> impl AsRef { - //[pre2021]~^ ERROR: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[pre2021]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] //[edition2021]~| ERROR: expected a type, found a trait [E0782] - todo!() + () } fn main() {} diff --git a/tests/ui/resolve/issue-3907-2.rs b/tests/ui/resolve/issue-3907-2.rs index f261de5f4025a..33bfd03237862 100644 --- a/tests/ui/resolve/issue-3907-2.rs +++ b/tests/ui/resolve/issue-3907-2.rs @@ -2,14 +2,14 @@ extern crate issue_3907; -type Foo = dyn issue_3907::Foo + 'static; +type Foo = dyn issue_3907::Foo + 'static; //~ ERROR not dyn compatible [E0038] struct S { name: isize } fn bar(_x: Foo) {} -//~^ ERROR E0038 -//~| ERROR E0277 +//~^ ERROR not dyn compatible [E0038] +//~| ERROR cannot be known at compilation time [E0277] fn main() {} diff --git a/tests/ui/resolve/issue-3907-2.stderr b/tests/ui/resolve/issue-3907-2.stderr index 40cdfb7a30255..64ed3d88b3fdc 100644 --- a/tests/ui/resolve/issue-3907-2.stderr +++ b/tests/ui/resolve/issue-3907-2.stderr @@ -1,3 +1,16 @@ +error[E0038]: the trait `issue_3907::Foo` is not dyn compatible + --> $DIR/issue-3907-2.rs:5:1 + | +LL | type Foo = dyn issue_3907::Foo + 'static; + | ^^^^^^^^ `issue_3907::Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/auxiliary/issue-3907.rs:2:8 + | +LL | fn bar(); + | ^^^ the trait is not dyn compatible because associated function `bar` has no `self` parameter + error[E0038]: the trait `issue_3907::Foo` is not dyn compatible --> $DIR/issue-3907-2.rs:11:12 | @@ -24,7 +37,7 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn bar(_x: &Foo) {} | + -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0277. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/resolve/issue-3907.rs b/tests/ui/resolve/issue-3907.rs index fd08c360d3627..19d83515066eb 100644 --- a/tests/ui/resolve/issue-3907.rs +++ b/tests/ui/resolve/issue-3907.rs @@ -2,7 +2,7 @@ extern crate issue_3907; -type Foo = dyn issue_3907::Foo; +type Foo = dyn issue_3907::Foo; //~ ERROR not dyn compatible struct S { name: isize diff --git a/tests/ui/resolve/issue-3907.stderr b/tests/ui/resolve/issue-3907.stderr index 0dc85829160bf..7999fd0c9eddf 100644 --- a/tests/ui/resolve/issue-3907.stderr +++ b/tests/ui/resolve/issue-3907.stderr @@ -14,6 +14,20 @@ help: consider importing this trait instead LL + use issue_3907::Foo; | -error: aborting due to 1 previous error +error[E0038]: the trait `issue_3907::Foo` is not dyn compatible + --> $DIR/issue-3907.rs:5:1 + | +LL | type Foo = dyn issue_3907::Foo; + | ^^^^^^^^ `issue_3907::Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/auxiliary/issue-3907.rs:2:8 + | +LL | fn bar(); + | ^^^ the trait is not dyn compatible because associated function `bar` has no `self` parameter + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0038, E0404. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/sized-hierarchy/trait-alias-elaboration.rs b/tests/ui/sized-hierarchy/trait-alias-elaboration.rs index a5b4443ffddd3..0f65e80590ddd 100644 --- a/tests/ui/sized-hierarchy/trait-alias-elaboration.rs +++ b/tests/ui/sized-hierarchy/trait-alias-elaboration.rs @@ -6,7 +6,7 @@ use std::marker::MetaSized; // wrote `MetaSized` in the `dyn Trait` then that should still be an error so as not to accidentally // accept this going forwards. -trait Qux = Clone; +trait Qux = std::fmt::Debug; type Foo = dyn Qux + MetaSized; //~^ ERROR: only auto traits can be used as additional traits in a trait object diff --git a/tests/ui/sized-hierarchy/trait-alias-elaboration.stderr b/tests/ui/sized-hierarchy/trait-alias-elaboration.stderr index 394aae6f8e32f..815fd7da2771a 100644 --- a/tests/ui/sized-hierarchy/trait-alias-elaboration.stderr +++ b/tests/ui/sized-hierarchy/trait-alias-elaboration.stderr @@ -1,15 +1,15 @@ error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-elaboration.rs:11:16 | -LL | trait Qux = Clone; - | ------------------ additional non-auto trait +LL | trait Qux = std::fmt::Debug; + | ---------------------------- additional non-auto trait LL | LL | type Foo = dyn Qux + MetaSized; | ^^^ --------- first non-auto trait | | | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: MetaSized + MetaSized + Clone {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: MetaSized + MetaSized + Debug {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 1 previous error diff --git a/tests/ui/trait-bounds/check-fn-clauses-issue-151319.rs b/tests/ui/trait-bounds/check-fn-clauses-issue-151319.rs new file mode 100644 index 0000000000000..d2ad7e38fb29a --- /dev/null +++ b/tests/ui/trait-bounds/check-fn-clauses-issue-151319.rs @@ -0,0 +1,9 @@ +//@compile-flags: -Znext-solver=globally --crate-type=lib +pub trait Trait { + type Assoc; +} + +pub fn foo + Trait>() { + //~^ ERROR type annotations needed: cannot satisfy `::Assoc == u32` [E0284] + const {} +} diff --git a/tests/ui/trait-bounds/check-fn-clauses-issue-151319.stderr b/tests/ui/trait-bounds/check-fn-clauses-issue-151319.stderr new file mode 100644 index 0000000000000..f201eae959ec6 --- /dev/null +++ b/tests/ui/trait-bounds/check-fn-clauses-issue-151319.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `::Assoc == u32` + --> $DIR/check-fn-clauses-issue-151319.rs:6:21 + | +LL | pub fn foo + Trait>() { + | ^^^^^^^^^^^ cannot satisfy `::Assoc == u32` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs b/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs deleted file mode 100644 index 58bc4daedfcc1..0000000000000 --- a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Demonstrate that generic const arguments in GAT constraints are rejected at -// the definition site of an eager type alias. - -//@ compile-flags: -Znext-solver=globally - -#![feature(generic_const_args, min_generic_const_args)] -#![expect(incomplete_features)] - -// * dyn incompatible due to GAT -// * `'a: 'static`, `String: Copy` and `[u8]: Sized` unsatisfied, `loop {}` diverging -type Several<'a> = dyn HasGenericAssocType = [u8]>; -//~^ ERROR - -trait HasGenericAssocType { - type Type<'a: 'static, T: Copy, const N: usize>; -} - -fn main() { - let _: &Several<'_>; - //~^ ERROR the trait `HasGenericAssocType` is not dyn compatible -} diff --git a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.stderr b/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.stderr deleted file mode 100644 index 6b06ba9cb14fe..0000000000000 --- a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: constant evaluation is taking a long time - --> $DIR/lack-of-wfcheck-gat-generic-const-args.rs:11:63 - | -LL | type Several<'a> = dyn HasGenericAssocType = [u8]>; - | ^^^^^^^ - | - = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint -help: the constant being evaluated - --> $DIR/lack-of-wfcheck-gat-generic-const-args.rs:11:61 - | -LL | type Several<'a> = dyn HasGenericAssocType = [u8]>; - | ^^^^^^^^^^^ - = note: `#[deny(long_running_const_eval)]` on by default - -error[E0038]: the trait `HasGenericAssocType` is not dyn compatible - --> $DIR/lack-of-wfcheck-gat-generic-const-args.rs:19:12 - | -LL | let _: &Several<'_>; - | ^^^^^^^^^^^^ `HasGenericAssocType` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/lack-of-wfcheck-gat-generic-const-args.rs:15:10 - | -LL | trait HasGenericAssocType { - | ------------------- this trait is not dyn compatible... -LL | type Type<'a: 'static, T: Copy, const N: usize>; - | ^^^^ ...because it contains generic associated type `Type` - = help: consider moving `Type` to another trait - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.gca.stderr b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.gca.stderr index 52edd50aaaaad..4f1b284821041 100644 --- a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.gca.stderr +++ b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.gca.stderr @@ -1,16 +1,16 @@ -error[E0191]: the value of the associated constant `N` in `HasAssocConst` must be specified - --> $DIR/lack-of-wfcheck-generic-const-args.rs:19:25 +error[E0191]: the value of the associated constant `N` in `HasNonTypeAssocConst` must be specified + --> $DIR/lack-of-wfcheck-generic-const-args.rs:13:20 | -LL | type DynIncompat1 = dyn HasAssocConst; - | ^^^^^^^^^^^^^ +LL | type TyAlias = dyn HasNonTypeAssocConst; + | ^^^^^^^^^^^^^^^^^^^^ ... -LL | const N: usize; - | -------------- `N` defined here +LL | /*non-type */const N: usize; + | -------------- `N` defined here | help: specify the associated constant | -LL | type DynIncompat1 = dyn HasAssocConst; - | +++++++++++++++++ +LL | type TyAlias = dyn HasNonTypeAssocConst; + | +++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.no_gca.stderr b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.no_gca.stderr new file mode 100644 index 0000000000000..c41a2f91763b0 --- /dev/null +++ b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.no_gca.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `HasNonTypeAssocConst` is not dyn compatible + --> $DIR/lack-of-wfcheck-generic-const-args.rs:13:1 + | +LL | type TyAlias = dyn HasNonTypeAssocConst; + | ^^^^^^^^^^^^ `HasNonTypeAssocConst` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/lack-of-wfcheck-generic-const-args.rs:17:24 + | +LL | trait HasNonTypeAssocConst { + | -------------------- this trait is not dyn compatible... +LL | /*non-type */const N: usize; + | ^ ...because it contains associated const `N` + = help: consider moving `N` to another trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs index afca550944ffc..d995cb7989ab8 100644 --- a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs +++ b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs @@ -1,26 +1,20 @@ -// Demonstrate that generic_const_args changes the behavior for dyn trait aliases -// with non-type associated consts: the associated const must be specified. +// FIXME(fmease): Re-audit this test! Rewrite its description! Probably rename the entire file, too! + +// Demonstrate that enabling `generic_const_args` changes the behavior for trait object types in +// (unchecked) type aliases where the corresponding trait has non-type associated consts: +// The associated const must be specified. //@ revisions: no_gca gca //@ compile-flags: -Znext-solver=globally -//@ [no_gca] check-pass #![cfg_attr(gca, feature(generic_const_args, min_generic_const_args))] -#![cfg_attr(gca, expect(incomplete_features))] - -type UnsatTraitBound0 = [str]; // `str: Sized` unsatisfied -type UnsatTraitBound1> = T; // `str: Sized` unsatisfied -type UnsatOutlivesBound<'a> = &'static &'a (); // `'a: 'static` unsatisfied - -type Diverging = [(); panic!()]; // `panic!()` diverging -type DynIncompat0 = dyn Sized; // `Sized` axiomatically dyn incompatible -// issue: -type DynIncompat1 = dyn HasAssocConst; -//[gca]~^ ERROR the value of the associated constant `N` in `HasAssocConst` must be specified +//[no_gca]~v ERROR not dyn compatible +type TyAlias = dyn HasNonTypeAssocConst; +//[gca]~^ ERROR the value of the associated constant `N` in `HasNonTypeAssocConst` must be specified -trait HasAssocConst { - const N: usize; +trait HasNonTypeAssocConst { + /*non-type */const N: usize; } fn main() {} diff --git a/tests/ui/type-alias/lack-of-wfcheck.rs b/tests/ui/type-alias/lack-of-wfcheck.rs index 91fbee8d3f198..4935eff8b2dfe 100644 --- a/tests/ui/type-alias/lack-of-wfcheck.rs +++ b/tests/ui/type-alias/lack-of-wfcheck.rs @@ -1,11 +1,14 @@ -// Demonstrate that we don't check the definition site of (eager) type aliases for well-formedness. +// Demonstrate that we don't check the def site of (unchecked) type aliases for well-formedness. // // Listed below are ill-formed type system entities which we don't reject since they appear inside -// the definition of (eager) type aliases. These type aliases are intentionally not referenced from -// anywhere to prevent the eagerly expanded / instantiated aliased types from getting wfchecked +// the definition of (unchecked) type aliases. These type aliases are intentionally not referenced +// from anywhere to prevent the eagerly expanded / instantiated aliased types from getting wfchecked // since that's not what we're testing here. //@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver type UnsatTraitBound0 = [str]; // `str: Sized` unsatisfied type UnsatTraitBound1> = T; // `str: Sized` unsatisfied @@ -13,15 +16,14 @@ type UnsatOutlivesBound<'a> = &'static &'a (); // `'a: 'static` unsatisfied type Diverging = [(); panic!()]; // `panic!()` diverging -type DynIncompat0 = dyn Sized; // `Sized` axiomatically dyn incompatible -// issue: -type DynIncompat1 = dyn HasAssocConst; // dyn incompatible due to (non-type-level) assoc const - -// * dyn incompatible due to GAT // * `'a: 'static`, `String: Copy` and `[u8]: Sized` unsatisfied, `loop {}` diverging -type Several<'a> = dyn HasGenericAssocType = [u8]>; +#[expect(unused_associated_type_bounds)] +type Several<'a> = dyn Trait = [u8]>; -trait HasAssocConst { const N: usize; } -trait HasGenericAssocType { type Type<'a: 'static, T: Copy, const N: usize>; } +trait Trait { + type Type<'a: 'static, T: Copy, const N: usize> + where + Self: Sized; +} fn main() {} diff --git a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs index e8c3bbba1e458..a32a61b767d4e 100644 --- a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs +++ b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs @@ -42,7 +42,7 @@ impl<'a, Fut: Future> SomeTrait<'a, Fut> for Fut { } impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> { -//~^ ERROR: conflicting implementations of trait `DerefMut` +//~^ ERROR: cannot implement `DerefMut` for the fundamental type fn deref_mut<'c>( self: &'c mut Pin<&'b dyn SomeTrait<'a, Fut>>, ) -> &'c mut (dyn SomeTrait<'a, Fut> + 'b) { diff --git a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr index 2bcd92b76a09d..3e413d9ef9e1b 100644 --- a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr +++ b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr @@ -1,14 +1,10 @@ -error[E0119]: conflicting implementations of trait `DerefMut` for type `Pin<&dyn SomeTrait<'_, _>>` - --> $DIR/pin-unsound-issue-85099-derefmut.rs:44:1 +error: cannot implement `DerefMut` for the fundamental type `Pin<&dyn SomeTrait<'_, Fut>>` + --> $DIR/pin-unsound-issue-85099-derefmut.rs:44:32 | LL | impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `DerefMut` not allowed for `Pin<&dyn SomeTrait<'_, Fut>>` | - = note: conflicting implementation in crate `core`: - - impl DerefMut for Pin - where as pin::helper::PinDerefMutHelper>::Target == as Deref>::Target, Ptr: Deref, pin::helper::PinHelper: pin::helper::PinDerefMutHelper, pin::helper::PinHelper: ?Sized; - = note: upstream crates may add a new impl of trait `std::pin::helper::PinDerefMutHelper` for type `std::pin::helper::PinHelper<&dyn SomeTrait<'_, _>>` in future versions + = note: `DerefMut` is `#[rustc_anti_fundamental]` and cannot be implemented for `#[fundamental]` types from another crate error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0119`.