diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
7 files changed, 123 insertions, 7 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 8b5c029428c..68b0db21141 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -240,6 +240,11 @@ pub(super) trait GoalKind<'tcx>: goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + fn consider_builtin_async_destruct_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; + fn consider_builtin_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -520,6 +525,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_coroutine_candidate(self, goal) } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) { G::consider_builtin_discriminant_kind_candidate(self, goal) + } else if lang_items.async_destruct_trait() == Some(trait_def_id) { + G::consider_builtin_async_destruct_candidate(self, goal) } else if lang_items.destruct_trait() == Some(trait_def_id) { G::consider_builtin_destruct_candidate(self, goal) } else if lang_items.transmute_trait() == Some(trait_def_id) { diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index ebf2a0d9621..c662ab23c53 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -814,6 +814,59 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { }) } + fn consider_builtin_async_destruct_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let self_ty = goal.predicate.self_ty(); + let async_destructor_ty = match *self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Array(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) + | ty::Never + | ty::Adt(_, _) + | ty::Str + | ty::Slice(_) + | ty::Tuple(_) + | ty::Error(_) => self_ty.async_destructor_ty(ecx.tcx(), goal.param_env), + + // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder + // types, which return `<self_ty as AsyncDestruct>::AsyncDestructor` + // (or ICE in the case of placeholders). Projecting a type to itself + // is never really productive. + ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { + return Err(NoSolution); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Foreign(..) + | ty::Bound(..) => bug!( + "unexpected self ty `{:?}` when normalizing `<T as AsyncDestruct>::AsyncDestructor`", + goal.predicate.self_ty() + ), + + ty::Pat(..) | ty::Dynamic(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => bug!( + "`consider_builtin_async_destruct_candidate` is not yet implemented for type: {self_ty:?}" + ), + }; + + ecx.probe_misc_candidate("builtin async destruct").enter(|ecx| { + ecx.eq(goal.param_env, goal.predicate.term, async_destructor_ty.into()) + .expect("expected goal term to be fully unconstrained"); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + } + fn consider_builtin_destruct_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index e522339358a..ed76ea74f08 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -544,6 +544,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } + fn consider_builtin_async_destruct_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::PredicatePolarity::Positive { + return Err(NoSolution); + } + + // `AsyncDestruct` is automatically implemented for every type. + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + fn consider_builtin_destruct_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index db3794c1c40..9d3caaa01ab 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -124,7 +124,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( msg: &str, err: &mut Diag<'_, G>, fn_sig: Option<&hir::FnSig<'_>>, - projection: Option<&ty::AliasTy<'_>>, + projection: Option<ty::AliasTy<'_>>, trait_pred: ty::PolyTraitPredicate<'tcx>, // When we are dealing with a trait, `super_traits` will be `Some`: // Given `trait T: A + B + C {}` @@ -142,7 +142,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( let generics = tcx.generics_of(item_id); // Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`... if let Some((param, bound_str, fn_sig)) = - fn_sig.zip(projection).and_then(|(sig, p)| match p.self_ty().kind() { + fn_sig.zip(projection).and_then(|(sig, p)| match *p.self_ty().kind() { // Shenanigans to get the `Trait` from the `impl Trait`. ty::Param(param) => { let param_def = generics.type_param(param, tcx); @@ -252,7 +252,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let trait_pred = self.resolve_numeric_literals_with_default(trait_pred); let self_ty = trait_pred.skip_binder().self_ty(); - let (param_ty, projection) = match self_ty.kind() { + let (param_ty, projection) = match *self_ty.kind() { ty::Param(_) => (true, None), ty::Alias(ty::Projection, projection) => (false, Some(projection)), _ => (false, None), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 8f5a30c436d..88ebf8754d3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -482,7 +482,7 @@ fn is_impossible_associated_item( type Result = ControlFlow<()>; fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { // If this is a parameter from the trait item's own generics, then bail - if let ty::Param(param) = t.kind() + if let ty::Param(param) = *t.kind() && let param_def_id = self.generics.type_param(param, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id { @@ -492,7 +492,7 @@ fn is_impossible_associated_item( } fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { if let ty::ReEarlyParam(param) = r.kind() - && let param_def_id = self.generics.region_param(¶m, self.tcx).def_id + && let param_def_id = self.generics.region_param(param, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id { return ControlFlow::Break(()); @@ -501,7 +501,7 @@ fn is_impossible_associated_item( } fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = ct.kind() - && let param_def_id = self.generics.const_param(¶m, self.tcx).def_id + && let param_def_id = self.generics.const_param(param, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id { return ControlFlow::Break(()); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ca0b50864a8..116e17c7e43 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1074,6 +1074,42 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Infer(..) | ty::Error(_) => false, } + } else if lang_items.async_destruct_trait() == Some(trait_ref.def_id) { + match self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(..) + | ty::Str + | ty::Array(..) + | ty::Slice(_) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Pat(..) + | ty::Never + | ty::Tuple(..) + | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, + + // type parameters, opaques, and unnormalized projections don't have + // a known async destructor and may need to be normalized further or rely + // on param env for async destructor projections + ty::Param(_) + | ty::Foreign(_) + | ty::Alias(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(_) + | ty::Error(_) => false, + } } else if lang_items.pointee_trait() == Some(trait_ref.def_id) { let tail = selcx.tcx().struct_tail_with_normalize( self_ty, @@ -1488,15 +1524,20 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); - let args = tcx.mk_args(&[self_ty.into()]); let lang_items = tcx.lang_items(); let item_def_id = obligation.predicate.def_id; let trait_def_id = tcx.trait_of_item(item_def_id).unwrap(); + let args = tcx.mk_args(&[self_ty.into()]); let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) { let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); assert_eq!(discriminant_def_id, item_def_id); (self_ty.discriminant_ty(tcx).into(), Vec::new()) + } else if lang_items.async_destruct_trait() == Some(trait_def_id) { + let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0]; + assert_eq!(destructor_def_id, item_def_id); + + (self_ty.async_destructor_ty(tcx, obligation.param_env).into(), Vec::new()) } else if lang_items.pointee_trait() == Some(trait_def_id) { let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, item_def_id); 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 c415d288b8f..40d206b92b8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -81,6 +81,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.discriminant_kind_trait() == Some(def_id) { // `DiscriminantKind` is automatically implemented for every type. candidates.vec.push(BuiltinCandidate { has_nested: false }); + } else if lang_items.async_destruct_trait() == Some(def_id) { + // `AsyncDestruct` is automatically implemented for every type. + candidates.vec.push(BuiltinCandidate { has_nested: false }); } else if lang_items.pointee_trait() == Some(def_id) { // `Pointee` is automatically implemented for every type. candidates.vec.push(BuiltinCandidate { has_nested: false }); |
