diff options
Diffstat (limited to 'compiler/rustc_trait_selection')
4 files changed, 70 insertions, 34 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 614a5e04809..390381752f9 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1569,7 +1569,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::ConstDrop(_) => { + | super::ImplSource::ConstDestruct(_) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -1644,7 +1644,7 @@ fn confirm_select_candidate<'cx, 'tcx>( | super::ImplSource::Builtin(..) | super::ImplSource::TraitUpcasting(_) | super::ImplSource::TraitAlias(..) - | super::ImplSource::ConstDrop(_) => { + | super::ImplSource::ConstDestruct(_) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, 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 d76bcf6807f..c0a283d2eda 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -5,6 +5,7 @@ //! candidates. See the [rustc dev guide] for more details. //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly +use hir::LangItem; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::traits::TraitEngine; @@ -307,7 +308,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.drop_trait() == Some(def_id) && obligation.predicate.is_const_if_const() { - self.assemble_const_drop_candidates(obligation, &mut candidates); + // holds to make it easier to transition + // FIXME(fee1-dead): add a note for selection error of `~const Drop` + // when beta is bumped + // FIXME: remove this when beta is bumped + #[cfg(bootstrap)] + {} + + candidates.vec.push(SelectionCandidate::ConstDestructCandidate(None)) + } else if lang_items.destruct_trait() == Some(def_id) { + self.assemble_const_destruct_candidates(obligation, &mut candidates); } else { if lang_items.clone_trait() == Some(def_id) { // Same builtin conditions as `Copy`, i.e., every type which has builtin support @@ -906,15 +916,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_const_drop_candidates( + fn assemble_const_destruct_candidates( &mut self, obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - // If the predicate is `~const Drop` in a non-const environment, we don't actually need + // If the predicate is `~const Destruct` in a non-const environment, we don't actually need // to check anything. We'll short-circuit checking any obligations in confirmation, too. - if obligation.param_env.constness() == hir::Constness::NotConst { - candidates.vec.push(ConstDropCandidate(None)); + if !obligation.is_const() { + candidates.vec.push(ConstDestructCandidate(None)); return; } @@ -927,7 +937,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Param(_) | ty::Placeholder(_) | ty::Projection(_) => { - // We don't know if these are `~const Drop`, at least + // We don't know if these are `~const Destruct`, at least // not structurally... so don't push a candidate. } @@ -951,14 +961,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Generator(..) | ty::Tuple(_) | ty::GeneratorWitness(_) => { - // These are built-in, and cannot have a custom `impl const Drop`. - candidates.vec.push(ConstDropCandidate(None)); + // These are built-in, and cannot have a custom `impl const Destruct`. + candidates.vec.push(ConstDestructCandidate(None)); } ty::Adt(..) => { // Find a custom `impl Drop` impl, if it exists let relevant_impl = self.tcx().find_map_relevant_impl( - obligation.predicate.def_id(), + self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), Some, ); @@ -966,11 +976,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Some(impl_def_id) = relevant_impl { // Check that `impl Drop` is actually const, if there is a custom impl if self.tcx().impl_constness(impl_def_id) == hir::Constness::Const { - candidates.vec.push(ConstDropCandidate(Some(impl_def_id))); + candidates.vec.push(ConstDestructCandidate(Some(impl_def_id))); } } else { // Otherwise check the ADT like a built-in type (structurally) - candidates.vec.push(ConstDropCandidate(None)); + candidates.vec.push(ConstDestructCandidate(None)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 05479899f3a..3c980af5121 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,7 +8,6 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; @@ -29,9 +28,9 @@ use crate::traits::TraitNotObjectSafe; use crate::traits::VtblSegment; use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation}; use crate::traits::{ - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData, - ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, - ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, + ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, + ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, + ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, }; use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation}; @@ -156,9 +155,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSource::TraitUpcasting(data)) } - ConstDropCandidate(def_id) => { - let data = self.confirm_const_drop_candidate(obligation, def_id)?; - Ok(ImplSource::ConstDrop(data)) + ConstDestructCandidate(def_id) => { + let data = self.confirm_const_destruct_candidate(obligation, def_id)?; + Ok(ImplSource::ConstDestruct(data)) } } } @@ -1037,14 +1036,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceBuiltinData { nested }) } - fn confirm_const_drop_candidate( + fn confirm_const_destruct_candidate( &mut self, obligation: &TraitObligation<'tcx>, impl_def_id: Option<DefId>, - ) -> Result<ImplSourceConstDropData<PredicateObligation<'tcx>>, SelectionError<'tcx>> { - // `~const Drop` in a non-const environment is always trivially true, since our type is `Drop` - if obligation.param_env.constness() == Constness::NotConst { - return Ok(ImplSourceConstDropData { nested: vec![] }); + ) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> { + // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` + if !obligation.is_const() { + return Ok(ImplSourceConstDestructData { nested: vec![] }); + } + + let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); + // FIXME: remove if statement below when beta is bumped + #[cfg(bootstrap)] + {} + + if obligation.predicate.skip_binder().def_id() == drop_trait + { + return Ok(ImplSourceConstDestructData { nested: vec![] }); } let tcx = self.tcx(); @@ -1054,9 +1063,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); // If we have a custom `impl const Drop`, then - // first check it like a regular impl candidate + // first check it like a regular impl candidate. + // This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand. if let Some(impl_def_id) = impl_def_id { - nested.extend(self.confirm_impl_candidate(obligation, impl_def_id).nested); + let obligations = self.infcx.commit_unconditionally(|_| { + let mut new_obligation = obligation.clone(); + new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| { trait_pred.trait_ref.def_id = drop_trait; trait_pred }); + let substs = self.rematch_impl(impl_def_id, &new_obligation); + debug!(?substs, "impl substs"); + let cause = obligation.derived_cause(ImplDerivedObligation); + ensure_sufficient_stack(|| { + self.vtable_impl( + impl_def_id, + substs, + cause, + new_obligation.recursion_depth + 1, + new_obligation.param_env, + ) + }) + }); + nested.extend(obligations.nested); } // We want to confirm the ADT's fields if we have an ADT @@ -1114,7 +1140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self_ty .rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Drop, None), + def_id: self.tcx().require_lang_item(LangItem::Destruct, None), substs: self.tcx().mk_substs_trait(nested_ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, @@ -1140,7 +1166,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let predicate = self_ty .rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Drop, None), + def_id: self.tcx().require_lang_item(LangItem::Destruct, None), substs: self.tcx().mk_substs_trait(nested_ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, @@ -1158,6 +1184,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - Ok(ImplSourceConstDropData { nested }) + Ok(ImplSourceConstDestructData { nested }) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a1a8497859d..5d07139e87b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1179,7 +1179,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { GeneratorCandidate => {} // FnDef where the function is const FnPointerCandidate { is_const: true } => {} - ConstDropCandidate(_) => {} + ConstDestructCandidate(_) => {} _ => { // reject all other types of candidates continue; @@ -1589,7 +1589,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, - // `DiscriminantKindCandidate`, and `ConstDropCandidate` to anything else. + // `DiscriminantKindCandidate`, and `ConstDestructCandidate` to anything else. // // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. @@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate | PointeeCandidate - | ConstDropCandidate(_), + | ConstDestructCandidate(_), _, ) => true, ( @@ -1614,7 +1614,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate | PointeeCandidate - | ConstDropCandidate(_), + | ConstDestructCandidate(_), ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { |
