Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/dyn_compatibility.rs')
| -rw-r--r-- | crates/hir-ty/src/dyn_compatibility.rs | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index ba63343d49..34858212cb 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -6,8 +6,8 @@ use hir_def::{ AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, hir::generics::{GenericParams, LocalTypeOrConstParamId}, - nameres::crate_def_map, signatures::{FunctionSignature, TraitFlags, TraitSignature}, + unstable_features::UnstableFeatures, }; use rustc_hash::FxHashSet; use rustc_type_ir::{ @@ -21,11 +21,14 @@ use crate::{ db::{HirDatabase, InternedOpaqueTyId}, lower::{GenericPredicates, associated_ty_item_bounds}, next_solver::{ - AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv, - ParamTy, SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt, + AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv, ParamTy, + SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, Unnormalized, + infer::{ + DbInternerInferExt, + traits::{Obligation, ObligationCause}, + }, mk_param, }, - traits::next_trait_solve_in_ctxt, }; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -111,8 +114,9 @@ where // rustc checks for non-lifetime binders here, but we don't support HRTB yet let trait_data = trait_.trait_items(db); + let mut features = None; for (_, assoc_item) in &trait_data.items { - dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; + dyn_compatibility_violation_for_assoc_item(db, &mut features, trait_, *assoc_item, cb)?; } ControlFlow::Continue(()) @@ -142,8 +146,8 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b // FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to // rust-analyzer yet // https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490 - elaborate::elaborate(interner, predicates.iter_identity()).any(|pred| { - match pred.kind().skip_binder() { + elaborate::elaborate(interner, predicates.iter_identity().map(Unnormalized::skip_norm_wip)).any( + |pred| match pred.kind().skip_binder() { ClauseKind::Trait(trait_pred) => { if sized == trait_pred.def_id().0 && let rustc_type_ir::TyKind::Param(param_ty) = @@ -156,17 +160,17 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b } } _ => false, - } - }) + }, + ) } // rustc gathers all the spans that references `Self` for error rendering, // but we don't have good way to render such locations. // So, just return single boolean value for existence of such `Self` reference fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { - GenericPredicates::query_explicit(db, trait_.into()) - .iter_identity() - .any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No)) + GenericPredicates::query_explicit(db, trait_.into()).iter_identity().any(|pred| { + predicate_references_self(db, trait_, pred.skip_norm_wip(), AllowSelfProjection::No) + }) } // Same as the above, `predicates_reference_self` @@ -244,11 +248,7 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI proj @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }, ) => match self.allow_self_projection { AllowSelfProjection::Yes => { - let trait_ = proj.trait_def_id(interner); - let trait_ = match trait_ { - SolverDefId::TraitId(id) => id, - _ => unreachable!(), - }; + let trait_ = proj.trait_def_id(interner).0; if self.super_traits.is_none() { self.super_traits = Some( elaborate::supertrait_def_ids(interner, self.trait_.into()) @@ -274,8 +274,9 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI t.visit_with(&mut visitor).is_break() } -fn dyn_compatibility_violation_for_assoc_item<F>( - db: &dyn HirDatabase, +fn dyn_compatibility_violation_for_assoc_item<'db, F>( + db: &'db dyn HirDatabase, + features: &mut Option<&'db UnstableFeatures>, trait_: TraitId, item: AssocItemId, cb: &mut F, @@ -297,8 +298,10 @@ where }) } AssocItemId::TypeAliasId(it) => { - let def_map = crate_def_map(db, trait_.krate(db)); - if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) { + if features + .get_or_insert_with(|| UnstableFeatures::query(db, trait_.krate(db))) + .generic_associated_type_extended + { ControlFlow::Continue(()) } else { let generic_params = GenericParams::of(db, item.into()); @@ -397,7 +400,7 @@ fn receiver_is_dispatchable<'db>( func: FunctionId, sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>>, ) -> bool { - let sig = sig.instantiate_identity(); + let sig = sig.instantiate_identity().skip_norm_wip(); let module = trait_.module(db); let interner = DbInterner::new_with(db, module.krate(db)); @@ -461,6 +464,7 @@ fn receiver_is_dispatchable<'db>( interner, generic_predicates .iter_identity() + .map(Unnormalized::skip_norm_wip) .chain([unsize_predicate.upcast(interner), trait_predicate.upcast(interner)]) .chain(meta_sized_predicate), ), @@ -470,12 +474,11 @@ fn receiver_is_dispatchable<'db>( // Receiver: DispatchFromDyn<Receiver[Self => U]> let predicate = TraitRef::new(interner, dispatch_from_dyn_did.into(), [receiver_ty, unsized_receiver_ty]); - let goal = Goal::new(interner, param_env, predicate); + let obligation = Obligation::new(interner, ObligationCause::dummy(), param_env, predicate); let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); // the receiver is dispatchable iff the obligation holds - let res = next_trait_solve_in_ctxt(&infcx, goal); - res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes)) + infcx.predicate_must_hold_modulo_regions(&obligation) } fn receiver_for_self_ty<'db>( @@ -488,7 +491,7 @@ fn receiver_for_self_ty<'db>( if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) } }); - EarlyBinder::bind(receiver_ty).instantiate(interner, args) + EarlyBinder::bind(receiver_ty).instantiate(interner, args).skip_norm_wip() } fn contains_illegal_impl_trait_in_trait<'db>( @@ -509,11 +512,7 @@ fn contains_illegal_impl_trait_in_trait<'db>( .. }) = ty.kind() { - let id = match def_id { - SolverDefId::InternedOpaqueTyId(id) => id, - _ => unreachable!(), - }; - self.0.insert(id); + self.0.insert(def_id.0); } ty.super_visit_with(self) } @@ -526,7 +525,7 @@ fn contains_illegal_impl_trait_in_trait<'db>( // Since we haven't implemented RPITIT in proper way like rustc yet, // just check whether `ret` contains RPIT for now for opaque_ty in visitor.0 { - let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty); + let impl_trait_id = opaque_ty.loc(db); if matches!(impl_trait_id, ImplTraitId::ReturnTypeImplTrait(..)) { return Some(MethodViolationCode::ReferencesImplTraitInTrait); } |