From 02962b374ecefd6f2a75956f4fb18806531d1d51 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 4 Mar 2020 23:00:44 +0100 Subject: Implement return position impl trait / opaque type support This is working, but I'm not that happy with how the lowering works. We might need an additional representation between `TypeRef` and `Ty` where names are resolved and `impl Trait` bounds are separated out, but things like inference variables don't exist and `impl Trait` is always represented the same way. Also note that this doesn't implement correct handling of RPIT *inside* the function (which involves turning the `impl Trait`s into variables and creating obligations for them). That intermediate representation might help there as well. --- crates/ra_hir_ty/src/traits/chalk.rs | 52 +++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'crates/ra_hir_ty/src/traits/chalk.rs') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 61de3cc30..a72a82f5a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use log::debug; use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; -use chalk_solve::rust_ir::{self, WellKnownTrait}; +use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; use hir_def::{ lang_item::{lang_attr, LangItemTarget}, @@ -100,6 +100,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate, id) } + fn custom_clauses(&self) -> Vec> { vec![] } @@ -130,11 +131,34 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) } - fn opaque_ty_data( - &self, - _id: chalk_ir::OpaqueTyId, - ) -> Arc> { - unimplemented!() + fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId) -> Arc { + let interned_id = crate::db::InternedOpaqueTyId::from(id); + let full_id = self.db.lookup_intern_impl_trait_id(interned_id); + let (func, idx) = match full_id { + crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx), + }; + let datas = + self.db.return_type_impl_traits(func).expect("impl trait id without impl traits"); + let data = &datas.value.impl_traits[idx as usize]; + let bound = OpaqueTyDatumBound { + bounds: make_binders( + data.bounds + .value + .iter() + .cloned() + .filter(|b| !b.is_error()) + .map(|b| b.to_chalk(self.db)) + .collect(), + 1, + ), + }; + let num_vars = datas.num_binders; + Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) + } + + fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { + // FIXME: actually provide the hidden type; it is relevant for auto traits + Ty::Unknown.to_chalk(self.db) } fn force_impl_for( @@ -150,10 +174,6 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { // FIXME: implement actual object safety true } - - fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { - Ty::Unknown.to_chalk(self.db) - } } pub(crate) fn program_clauses_for_chalk_env_query( @@ -460,6 +480,18 @@ impl From for ImplId { } } +impl From for crate::db::InternedOpaqueTyId { + fn from(id: OpaqueTyId) -> Self { + InternKey::from_intern_id(id.0) + } +} + +impl From for OpaqueTyId { + fn from(id: crate::db::InternedOpaqueTyId) -> Self { + chalk_ir::OpaqueTyId(id.as_intern_id()) + } +} + impl From> for crate::traits::AssocTyValueId { fn from(id: rust_ir::AssociatedTyValueId) -> Self { Self::from_intern_id(id.0) -- cgit v1.2.3