diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
12 files changed, 323 insertions, 81 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 617bc87a9d2..d4502be6ccf 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -128,8 +128,7 @@ fn sized_trait_bound_spans<'tcx>( } fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> { - tcx.hir() - .get_if_local(trait_def_id) + tcx.hir_get_if_local(trait_def_id) .and_then(|node| match node { hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., generics, bounds, _), @@ -187,7 +186,10 @@ fn predicates_reference_self( fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> { tcx.associated_items(trait_def_id) .in_definition_order() + // We're only looking at associated type bounds .filter(|item| item.kind == ty::AssocKind::Type) + // Ignore GATs with `Self: Sized` + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied()) .filter_map(|(clause, sp)| { // Item bounds *can* have self projections, since they never get @@ -301,7 +303,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item) .into_iter() .map(|v| { - let node = tcx.hir().get_if_local(item.def_id); + let node = tcx.hir_get_if_local(item.def_id); // Get an accurate span depending on the violation. let span = match (&v, node) { (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span, @@ -346,7 +348,7 @@ fn virtual_call_violations_for_method<'tcx>( generics, kind: hir::TraitItemKind::Fn(sig, _), .. - })) = tcx.hir().get_if_local(method.def_id).as_ref() + })) = tcx.hir_get_if_local(method.def_id).as_ref() { let sm = tcx.sess.source_map(); Some(( @@ -380,7 +382,7 @@ fn virtual_call_violations_for_method<'tcx>( let span = if let Some(hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), .. - })) = tcx.hir().get_if_local(method.def_id).as_ref() + })) = tcx.hir_get_if_local(method.def_id).as_ref() { Some(sig.decl.inputs[i].span) } else { @@ -418,7 +420,7 @@ fn virtual_call_violations_for_method<'tcx>( let span = if let Some(hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), .. - })) = tcx.hir().get_if_local(method.def_id).as_ref() + })) = tcx.hir_get_if_local(method.def_id).as_ref() { Some(sig.decl.inputs[0].span) } else { @@ -536,10 +538,10 @@ fn receiver_for_self_ty<'tcx>( /// a pointer. /// /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in -/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch -/// is stabilized, see tracking issue <https://github.com/rust-lang/rust/issues/43561>). -/// Instead, we fudge a little by introducing a new type parameter `U` such that +/// a new check that `Trait` is dyn-compatible, creating a cycle. +/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that /// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. +/// /// Written as a chalk-style query: /// ```ignore (not-rust) /// forall (U: Trait + ?Sized) { @@ -570,8 +572,6 @@ fn receiver_is_dispatchable<'tcx>( // the type `U` in the query // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can - // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome); @@ -696,11 +696,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> { ControlFlow::Continue(()) } } - ty::Alias(ty::Projection, ref data) if self.tcx.is_impl_trait_in_trait(data.def_id) => { + ty::Alias(ty::Projection, data) if self.tcx.is_impl_trait_in_trait(data.def_id) => { // We'll deny these later in their own pass ControlFlow::Continue(()) } - ty::Alias(ty::Projection, ref data) => { + ty::Alias(ty::Projection, data) => { match self.allow_self_projections { AllowSelfProjections::Yes => { // This is a projected type `<Foo as SomeTrait>::X`. diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f2d2dd2f3ce..e39f8e673db 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -1,6 +1,5 @@ use std::marker::PhantomData; -use rustc_data_structures::captures::Captures; use rustc_data_structures::obligation_forest::{ Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult, }; @@ -900,10 +899,10 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } /// Returns the set of inference variables contained in `args`. -fn args_infer_vars<'a, 'tcx>( - selcx: &SelectionContext<'a, 'tcx>, +fn args_infer_vars<'tcx>( + selcx: &SelectionContext<'_, 'tcx>, args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, -) -> impl Iterator<Item = TyOrConstInferVar> + Captures<'tcx> { +) -> impl Iterator<Item = TyOrConstInferVar> { selcx .infcx .resolve_vars_if_possible(args) diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 79e178150de..a4b6f330b9d 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -208,7 +208,7 @@ pub fn all_fields_implement_trait<'tcx>( } let field_span = tcx.def_span(field.did); - let field_ty_span = match tcx.hir().get_if_local(field.did) { + let field_ty_span = match tcx.hir_get_if_local(field.did) { Some(hir::Node::Field(field_def)) => field_def.ty.span, _ => field_span, }; diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 92098e20448..f04a5feba30 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_infer::traits::query::type_op::DropckOutlives; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; use tracing::{debug, instrument}; +use crate::solve::NextSolverError; use crate::traits::query::NoSolution; use crate::traits::query::normalize::QueryNormalizeExt; -use crate::traits::{Normalized, ObligationCause, ObligationCtxt}; +use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt}; /// This returns true if the type `ty` is "trivial" for /// dropck-outlives -- that is, if it doesn't require any types to @@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>( goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>, span: Span, ) -> Result<DropckOutlivesResult<'tcx>, NoSolution> { + match compute_dropck_outlives_with_errors(ocx, goal, span) { + Ok(r) => Ok(r), + Err(_) => Err(NoSolution), + } +} + +pub fn compute_dropck_outlives_with_errors<'tcx, E>( + ocx: &ObligationCtxt<'_, 'tcx, E>, + goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>, + span: Span, +) -> Result<DropckOutlivesResult<'tcx>, Vec<E>> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +{ let tcx = ocx.infcx.tcx; let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal; @@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>( dtorck_constraint_for_ty_inner( tcx, ocx.infcx.typing_env(param_env), - DUMMY_SP, + span, depth, ty, &mut constraints, - )?; + ); // "outlives" represent types/regions that may be touched // by a destructor. @@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>( // do not themselves define a destructor", more or less. We have // to push them onto the stack to be expanded. for ty in constraints.dtorck_types.drain(..) { - let Normalized { value: ty, obligations } = - ocx.infcx.at(&cause, param_env).query_normalize(ty)?; - ocx.register_obligations(obligations); + let ty = if let Ok(Normalized { value: ty, obligations }) = + ocx.infcx.at(&cause, param_env).query_normalize(ty) + { + ocx.register_obligations(obligations); + + debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + ty + } else { + ocx.deeply_normalize(&cause, param_env, ty)?; - debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + let errors = ocx.select_where_possible(); + debug!("normalize errors: {ty} ~> {errors:#?}"); + return Err(errors); + }; match ty.kind() { // All parameters live for the duration of the @@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( depth: usize, ty: Ty<'tcx>, constraints: &mut DropckConstraint<'tcx>, -) -> Result<(), NoSolution> { +) { if !tcx.recursion_limit().value_within_limit(depth) { constraints.overflows.push(ty); - return Ok(()); + return; } if trivial_dropck_outlives(tcx, ty) { - return Ok(()); + return; } match ty.kind() { @@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints) - })?; + }); } ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints); } - Ok::<_, NoSolution>(()) - })?, + }), ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in args.as_closure().upvar_tys() { - dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?; + dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints); } - Ok::<_, NoSolution>(()) - })?, + }), ty::CoroutineClosure(_, args) => { rustc_data_structures::stack::ensure_sufficient_stack(|| { @@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( depth + 1, ty, constraints, - )?; + ); } - Ok::<_, NoSolution>(()) - })? + }) } ty::Coroutine(_, args) => { @@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Adt(def, args) => { let DropckConstraint { dtorck_types, outlives, overflows } = - tcx.at(span).adt_dtorck_constraint(def.did())?; + tcx.at(span).adt_dtorck_constraint(def.did()); // FIXME: we can try to recursively `dtorck_constraint_on_ty` // there, but that needs some way to handle cycles. constraints @@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => { // By the time this code runs, all type variables ought to // be fully resolved. - return Err(NoSolution); + tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty)); } } - - Ok(()) } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index e8c2528aa6e..2f6bbd7f4cf 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; -pub use rustc_middle::traits::query::type_op::Normalize; +pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; @@ -28,12 +28,53 @@ where } fn perform_locally_with_next_solver( + _ocx: &ObligationCtxt<'_, 'tcx>, + key: ParamEnvAnd<'tcx, Self>, + _span: Span, + ) -> Result<Self::QueryResponse, NoSolution> { + Ok(key.value.value) + } +} + +impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize<T> +where + T: Normalizable<'tcx> + 'tcx, +{ + type QueryResponse = T; + + fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> { + if !key.value.value.has_aliases() { Some(key.value.value) } else { None } + } + + fn perform_query( + tcx: TyCtxt<'tcx>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>, + ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> { + T::type_op_method( + tcx, + CanonicalQueryInput { + typing_mode: canonicalized.typing_mode, + canonical: canonicalized.canonical.unchecked_map( + |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd { + param_env, + value: Normalize { value: value.value }, + }, + ), + }, + ) + } + + fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, span: Span, ) -> Result<Self::QueryResponse, NoSolution> { - // FIXME(-Znext-solver): shouldn't be using old normalizer - Ok(ocx.normalize(&ObligationCause::dummy_with_span(span), key.param_env, key.value.value)) + ocx.deeply_normalize( + &ObligationCause::dummy_with_span(span), + key.param_env, + key.value.value, + ) + .map_err(|_| NoSolution) } } @@ -81,3 +122,14 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { tcx.type_op_normalize_fn_sig(canonicalized) } } + +/// This impl is not needed, since we never normalize type outlives predicates +/// in the old solver, but is required by trait bounds to be happy. +impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> { + fn type_op_method( + _tcx: TyCtxt<'tcx>, + _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, + ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> { + unreachable!("we never normalize PolyTypeOutlivesPredicate") + } +} diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e495bdbf782..11b6b826efe 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -102,6 +102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_candidate_for_tuple(obligation, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) { self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates); + } else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) { + self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait( + obligation, + &mut candidates, + ); } else { if tcx.is_lang_item(def_id, LangItem::Clone) { // Same builtin conditions as `Copy`, i.e., every type which has builtin support @@ -854,13 +859,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().dyn_compatible_for_dispatch() { - principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().is_dyn_compatible(principal.def_id()) { - principal.with_self_ty(self.tcx(), self_ty) - } else { - return; - } + principal.with_self_ty(self.tcx(), self_ty) } else { // Only auto trait bounds exist. return; @@ -920,11 +919,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // T: Trait // so it seems ok if we (conservatively) fail to accept that `Unsize` // obligation above. Should be possible to extend this in the future. - let Some(source) = obligation.self_ty().no_bound_vars() else { + let Some(trait_pred) = obligation.predicate.no_bound_vars() else { // Don't add any candidates if there are bound regions. return; }; - let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1); + let source = trait_pred.self_ty(); + let target = trait_pred.trait_ref.args.type_at(1); debug!(?source, ?target, "assemble_candidates_for_unsizing"); @@ -1183,4 +1183,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } + + fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + match obligation.predicate.self_ty().skip_binder().kind() { + ty::Ref(..) + | ty::Adt(..) + | ty::Tuple(_) + | ty::Array(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Error(_) + | ty::Uint(_) + | ty::Int(_) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Bool + | ty::Float(_) + | ty::Char + | ty::RawPtr(..) + | ty::Never + | ty::Pat(..) + | ty::Dynamic(..) + | ty::Str + | ty::Slice(_) + | ty::Foreign(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::UnsafeBinder(_) + | ty::CoroutineWitness(..) + | ty::Bound(..) => { + candidates.vec.push(BikeshedGuaranteedNoDropCandidate); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + candidates.ambiguous = true; + } + } + } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index eb4adde716a..32cbb97e314 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_type_ir::elaborate; +use thin_vec::thin_vec; use tracing::{debug, instrument}; use super::SelectionCandidate::{self, *}; @@ -130,6 +131,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TraitUpcastingUnsizeCandidate(idx) => { self.confirm_trait_upcasting_unsize_candidate(obligation, idx)? } + + BikeshedGuaranteedNoDropCandidate => { + self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation) + } }; // The obligations returned by confirmation are recursively evaluated @@ -1346,6 +1351,93 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("source: {source}, target: {target}"), }) } + + fn confirm_bikeshed_guaranteed_no_drop_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + ) -> ImplSource<'tcx, PredicateObligation<'tcx>> { + let mut obligations = thin_vec![]; + + let tcx = self.tcx(); + let self_ty = obligation.predicate.self_ty(); + match *self_ty.skip_binder().kind() { + // `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`. + ty::Ref(..) => {} + // `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`. + ty::Adt(def, _) if def.is_manually_drop() => {} + // Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if + // their constituent types implement `BikeshedGuaranteedNoDrop`. + ty::Tuple(tys) => { + obligations.extend(tys.iter().map(|elem_ty| { + obligation.with( + tcx, + self_ty.rebind(ty::TraitRef::new( + tcx, + obligation.predicate.def_id(), + [elem_ty], + )), + ) + })); + } + ty::Array(elem_ty, _) => { + obligations.push(obligation.with( + tcx, + self_ty.rebind(ty::TraitRef::new( + tcx, + obligation.predicate.def_id(), + [elem_ty], + )), + )); + } + + // All other types implement `BikeshedGuaranteedNoDrop` only if + // they implement `Copy`. We could be smart here and short-circuit + // some trivially `Copy`/`!Copy` types, but there's no benefit. + ty::FnDef(..) + | ty::FnPtr(..) + | ty::Error(_) + | ty::Uint(_) + | ty::Int(_) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Bool + | ty::Float(_) + | ty::Char + | ty::RawPtr(..) + | ty::Never + | ty::Pat(..) + | ty::Dynamic(..) + | ty::Str + | ty::Slice(_) + | ty::Foreign(..) + | ty::Adt(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::UnsafeBinder(_) + | ty::CoroutineWitness(..) + | ty::Bound(..) => { + obligations.push(obligation.with( + tcx, + self_ty.map_bound(|ty| { + ty::TraitRef::new( + tcx, + tcx.require_lang_item(LangItem::Copy, Some(obligation.cause.span)), + [ty], + ) + }), + )); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("unexpected type `{self_ty:?}`") + } + } + + ImplSource::Builtin(BuiltinImplSource::Misc, obligations) + } } /// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6b1e1774f03..436ce3dddd9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1949,7 +1949,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitAliasCandidate | TraitUpcastingUnsizeCandidate(_) | BuiltinObjectCandidate - | BuiltinUnsizeCandidate => false, + | BuiltinUnsizeCandidate + | BikeshedGuaranteedNoDropCandidate => false, // Non-global param candidates have already been handled, global // where-bounds get ignored. ParamCandidate(_) | ImplCandidate(_) => true, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index f39c611d19f..19d3561dd59 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -200,15 +200,12 @@ impl<'tcx> Children { } } -fn iter_children(children: &Children) -> impl Iterator<Item = DefId> + '_ { +fn iter_children(children: &Children) -> impl Iterator<Item = DefId> { let nonblanket = children.non_blanket_impls.iter().flat_map(|(_, v)| v.iter()); children.blanket_impls.iter().chain(nonblanket).cloned() } -fn filtered_children( - children: &mut Children, - st: SimplifiedType, -) -> impl Iterator<Item = DefId> + '_ { +fn filtered_children(children: &mut Children, st: SimplifiedType) -> impl Iterator<Item = DefId> { let nonblanket = children.non_blanket_impls.entry(st).or_default().iter(); children.blanket_impls.iter().chain(nonblanket).cloned() } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index d30363ec158..15f5cf916a4 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -47,11 +47,11 @@ pub fn expand_trait_aliases<'tcx>( queue.extend( tcx.explicit_super_predicates_of(trait_pred.def_id()) .iter_identity_copied() - .map(|(clause, span)| { + .map(|(super_clause, span)| { let mut spans = spans.clone(); spans.push(span); ( - clause.instantiate_supertrait( + super_clause.instantiate_supertrait( tcx, clause.kind().rebind(trait_pred.trait_ref), ), diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 0024316b877..165174c0bcc 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -196,7 +196,7 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def fn own_existential_vtable_entries_iter( tcx: TyCtxt<'_>, trait_def_id: DefId, -) -> impl Iterator<Item = DefId> + '_ { +) -> impl Iterator<Item = DefId> { let trait_methods = tcx .associated_items(trait_def_id) .in_definition_order() diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 96051ad0aa5..18906a6a8ce 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -8,8 +8,9 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::Span; +use rustc_session::parse::feature_err; use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::{Span, sym}; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -288,7 +289,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( && let Some(impl_item) = items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id) { - Some(tcx.hir().impl_item(impl_item.id).expect_type().span) + Some(tcx.hir_impl_item(impl_item.id).expect_type().span) } else { None } @@ -704,8 +705,47 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> { )); } - ty::Pat(subty, _) => { + ty::Pat(subty, pat) => { self.require_sized(subty, ObligationCauseCode::Misc); + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + let mut check = |c| { + let cause = self.cause(ObligationCauseCode::Misc); + self.out.push(traits::Obligation::with_depth( + tcx, + cause.clone(), + self.recursion_depth, + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Clause( + ty::ClauseKind::ConstArgHasType(c, subty), + )), + )); + if !tcx.features().generic_pattern_types() { + if c.has_param() { + if self.span.is_dummy() { + self.tcx().dcx().delayed_bug( + "feature error should be reported elsewhere, too", + ); + } else { + feature_err( + &self.tcx().sess, + sym::generic_pattern_types, + self.span, + "wraparound pattern type ranges cause monomorphization time errors", + ) + .emit(); + } + } + } + }; + if let Some(start) = start { + check(start) + } + if let Some(end) = end { + check(end) + } + } + } } ty::Tuple(tys) => { @@ -841,7 +881,10 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> { ty.map_bound(|ty| { ty::TraitRef::new( self.tcx(), - self.tcx().require_lang_item(LangItem::Copy, Some(self.span)), + self.tcx().require_lang_item( + LangItem::BikeshedGuaranteedNoDrop, + Some(self.span), + ), [ty], ) }), @@ -861,19 +904,14 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> { // FIXME(#27579) RFC also considers adding trait // obligations that don't refer to Self and // checking those - - let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch(); - - if !defer_to_coercion { - if let Some(principal) = data.principal_def_id() { - self.out.push(traits::Obligation::with_depth( - tcx, - self.cause(ObligationCauseCode::WellFormed(None)), - self.recursion_depth, - self.param_env, - ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), - )); - } + if let Some(principal) = data.principal_def_id() { + self.out.push(traits::Obligation::with_depth( + tcx, + self.cause(ObligationCauseCode::WellFormed(None)), + self.recursion_depth, + self.param_env, + ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), + )); } } |
