From d674d7185d761c643f05888fce42c31119588814 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 8 Jul 2021 21:19:53 +0200 Subject: [PATCH] Represent opaque types with TyKind::OpaqueType ... instead of using `AliasTy`. Chalk turns the alias type into the placeholder during unification anyway, which confuses our method resolution logic. Fixes #9530. --- crates/hir_ty/src/chalk_ext.rs | 11 +++++++++-- crates/hir_ty/src/display.rs | 3 ++- crates/hir_ty/src/interner.rs | 10 ++++++++-- crates/hir_ty/src/lower.rs | 8 ++------ crates/hir_ty/src/tests/regression.rs | 19 +++++++++++++++++++ crates/hir_ty/src/tls.rs | 14 +------------- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs index df340a6ca17..dcf16bdb1f2 100644 --- a/crates/hir_ty/src/chalk_ext.rs +++ b/crates/hir_ty/src/chalk_ext.rs @@ -183,7 +183,7 @@ impl TyExt for Ty { fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option> { match self.kind(&Interner) { - TyKind::OpaqueType(opaque_ty_id, ..) => { + TyKind::OpaqueType(opaque_ty_id, subst) => { match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { let krate = def.module(db.upcast()).krate(); @@ -206,7 +206,14 @@ impl TyExt for Ty { None } } - ImplTraitId::ReturnTypeImplTrait(..) => None, + ImplTraitId::ReturnTypeImplTrait(func, idx) => { + db.return_type_impl_traits(func).map(|it| { + let data = (*it) + .as_ref() + .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); + data.substitute(&Interner, &subst).into_value_and_skipped_binders().0 + }) + } } } TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 2748faa6f84..55a566a33d9 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -384,7 +384,8 @@ impl HirDisplay for Ty { &TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: ref parameters, - })) => { + })) + | &TyKind::OpaqueType(opaque_ty_id, ref parameters) => { let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into()); if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { datas = diff --git a/crates/hir_ty/src/interner.rs b/crates/hir_ty/src/interner.rs index 5fef878e899..b8fca9a578b 100644 --- a/crates/hir_ty/src/interner.rs +++ b/crates/hir_ty/src/interner.rs @@ -93,7 +93,13 @@ impl chalk_ir::interner::Interner for Interner { alias: &chalk_ir::AliasTy, fmt: &mut fmt::Formatter<'_>, ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) + use std::fmt::Debug; + match alias { + chalk_ir::AliasTy::Projection(projection_ty) => { + Interner::debug_projection_ty(projection_ty, fmt) + } + chalk_ir::AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)), + } } fn debug_projection_ty( @@ -114,7 +120,7 @@ impl chalk_ir::interner::Interner for Interner { opaque_ty_id: chalk_ir::OpaqueTyId, fmt: &mut fmt::Formatter<'_>, ) -> Option { - Some(fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish()) + Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0)) } fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 239ac3786e7..92b376c4402 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -38,7 +38,7 @@ use crate::{ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, - FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, + FnSubst, ImplTraitId, Interner, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; @@ -250,11 +250,7 @@ impl<'a> TyLoweringContext<'a> { let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); let generics = generics(self.db.upcast(), func.into()); let parameters = generics.bound_vars_subst(self.in_binders); - TyKind::Alias(AliasTy::Opaque(OpaqueTy { - opaque_ty_id, - substitution: parameters, - })) - .intern(&Interner) + TyKind::OpaqueType(opaque_ty_id, parameters).intern(&Interner) } ImplTraitLoweringMode::Param => { let idx = self.impl_trait_counter.get(); diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 915dfbbc0d4..1e40ff24e3a 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -1058,3 +1058,22 @@ fn cfg_tail() { "#]], ) } + +#[test] +fn impl_trait_in_option_9530() { + check_types( + r#" +struct Option; +impl Option { + fn unwrap(self) -> T { loop {} } +} +fn make() -> Option { Option } +trait Copy {} +fn test() { + let o = make(); + o.unwrap(); + //^^^^^^^^^^ impl Copy +} + "#, + ) +} diff --git a/crates/hir_ty/src/tls.rs b/crates/hir_ty/src/tls.rs index 708797c4772..6a662dcf7bd 100644 --- a/crates/hir_ty/src/tls.rs +++ b/crates/hir_ty/src/tls.rs @@ -1,7 +1,6 @@ //! Implementation of Chalk debug helper functions using TLS. -use std::fmt::{self, Debug}; +use std::fmt; -use chalk_ir::AliasTy; use itertools::Itertools; use crate::{ @@ -53,17 +52,6 @@ impl DebugContext<'_> { write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) } - pub(crate) fn debug_alias( - &self, - alias_ty: &AliasTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - match alias_ty { - AliasTy::Projection(projection_ty) => self.debug_projection_ty(projection_ty, fmt), - AliasTy::Opaque(opaque_ty) => opaque_ty.fmt(fmt), - } - } - pub(crate) fn debug_projection_ty( &self, projection_ty: &chalk_ir::ProjectionTy,