Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
-rw-r--r--crates/hir-ty/src/lower.rs213
1 files changed, 150 insertions, 63 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index b73967be71..b23f2749ab 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -48,7 +48,7 @@ use rustc_pattern_analysis::Captures;
use smallvec::SmallVec;
use stdx::{impl_from, never};
use syntax::ast;
-use triomphe::Arc;
+use triomphe::{Arc, ThinArc};
use crate::{
all_super_traits,
@@ -1652,11 +1652,24 @@ fn named_associated_type_shorthand_candidates<R>(
}
}
-/// Build the type of all specific fields of a struct or enum variant.
+pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
+
+fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
+ (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
+}
+
pub(crate) fn field_types_query(
db: &dyn HirDatabase,
variant_id: VariantId,
) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
+ db.field_types_with_diagnostics(variant_id).0
+}
+
+/// Build the type of all specific fields of a struct or enum variant.
+pub(crate) fn field_types_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ variant_id: VariantId,
+) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
let var_data = variant_id.variant_data(db.upcast());
let (resolver, def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
@@ -1672,7 +1685,7 @@ pub(crate) fn field_types_query(
for (field_id, field_data) in var_data.fields().iter() {
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
}
- Arc::new(res)
+ (Arc::new(res), create_diagnostics(ctx.diagnostics))
}
/// This query exists only to be used when resolving short-hand associated types
@@ -1873,15 +1886,22 @@ pub(crate) fn generic_predicates_query(
db: &dyn HirDatabase,
def: GenericDefId,
) -> GenericPredicates {
- generic_predicates_filtered_by(db, def, |_, _| true)
+ generic_predicates_filtered_by(db, def, |_, _| true).0
}
-/// Resolve the where clause(s) of an item with generics,
-/// except the ones inherited from the parent
pub(crate) fn generic_predicates_without_parent_query(
db: &dyn HirDatabase,
def: GenericDefId,
) -> GenericPredicates {
+ db.generic_predicates_without_parent_with_diagnostics(def).0
+}
+
+/// Resolve the where clause(s) of an item with generics,
+/// except the ones inherited from the parent
+pub(crate) fn generic_predicates_without_parent_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> (GenericPredicates, Diagnostics) {
generic_predicates_filtered_by(db, def, |_, d| *d == def)
}
@@ -1891,7 +1911,7 @@ fn generic_predicates_filtered_by<F>(
db: &dyn HirDatabase,
def: GenericDefId,
filter: F,
-) -> GenericPredicates
+) -> (GenericPredicates, Diagnostics)
where
F: Fn(&WherePredicate, &GenericDefId) -> bool,
{
@@ -1932,7 +1952,10 @@ where
);
};
}
- GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
+ (
+ GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
+ create_diagnostics(ctx.diagnostics),
+ )
}
/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
@@ -1985,75 +2008,110 @@ impl ops::Deref for GenericDefaults {
}
}
-/// Resolve the default type params from generics
pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
+ db.generic_defaults_with_diagnostics(def).0
+}
+
+/// Resolve the default type params from generics.
+///
+/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents).
+pub(crate) fn generic_defaults_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> (GenericDefaults, Diagnostics) {
let generic_params = generics(db.upcast(), def);
if generic_params.len() == 0 {
- return GenericDefaults(None);
+ return (GenericDefaults(None), None);
}
let resolver = def.resolver(db.upcast());
let parent_start_idx = generic_params.len_self();
- let mut ctx = TyLoweringContext::new(db, &resolver, TypesMap::EMPTY, def.into())
- .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
- .with_type_param_mode(ParamLoweringMode::Variable);
- GenericDefaults(Some(Arc::from_iter(generic_params.iter_with_types_map().enumerate().map(
- |(idx, ((id, p), types_map))| {
- ctx.types_map = types_map;
- match p {
- GenericParamDataRef::TypeParamData(p) => {
- let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| {
- // Each default can only refer to previous parameters.
- // Type variable default referring to parameter coming
- // after it is forbidden (FIXME: report diagnostic)
- fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx)
- });
- crate::make_binders(db, &generic_params, ty.cast(Interner))
- }
- GenericParamDataRef::ConstParamData(p) => {
- let GenericParamId::ConstParamId(id) = id else {
- unreachable!("Unexpected lifetime or type argument")
- };
+ let mut ctx =
+ TyLoweringContext::new(db, &resolver, generic_params.self_types_map(), def.into())
+ .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
+ .with_type_param_mode(ParamLoweringMode::Variable);
+ let mut idx = 0;
+ let mut defaults = generic_params
+ .iter_self()
+ .map(|(id, p)| {
+ let result =
+ handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+ idx += 1;
+ result
+ })
+ .collect::<Vec<_>>();
+ let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
+ defaults.extend(generic_params.iter_parents_with_types_map().map(|((id, p), types_map)| {
+ ctx.types_map = types_map;
+ let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+ idx += 1;
+ result
+ }));
+ let defaults = GenericDefaults(Some(Arc::from_iter(defaults)));
+ return (defaults, diagnostics);
+
+ fn handle_generic_param(
+ ctx: &mut TyLoweringContext<'_>,
+ idx: usize,
+ id: GenericParamId,
+ p: GenericParamDataRef<'_>,
+ parent_start_idx: usize,
+ generic_params: &Generics,
+ ) -> Binders<crate::GenericArg> {
+ match p {
+ GenericParamDataRef::TypeParamData(p) => {
+ let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| {
+ // Each default can only refer to previous parameters.
+ // Type variable default referring to parameter coming
+ // after it is forbidden (FIXME: report diagnostic)
+ fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx)
+ });
+ crate::make_binders(ctx.db, generic_params, ty.cast(Interner))
+ }
+ GenericParamDataRef::ConstParamData(p) => {
+ let GenericParamId::ConstParamId(id) = id else {
+ unreachable!("Unexpected lifetime or type argument")
+ };
- let mut val = p.default.as_ref().map_or_else(
- || unknown_const_as_generic(db.const_param_ty(id)),
- |c| {
- let param_ty = ctx.lower_ty(p.ty);
- let c = ctx.lower_const(c, param_ty);
- c.cast(Interner)
- },
- );
- // Each default can only refer to previous parameters, see above.
- val = fallback_bound_vars(val, idx, parent_start_idx);
- make_binders(db, &generic_params, val)
- }
- GenericParamDataRef::LifetimeParamData(_) => {
- make_binders(db, &generic_params, error_lifetime().cast(Interner))
- }
+ let mut val = p.default.as_ref().map_or_else(
+ || unknown_const_as_generic(ctx.db.const_param_ty(id)),
+ |c| {
+ let param_ty = ctx.lower_ty(p.ty);
+ let c = ctx.lower_const(c, param_ty);
+ c.cast(Interner)
+ },
+ );
+ // Each default can only refer to previous parameters, see above.
+ val = fallback_bound_vars(val, idx, parent_start_idx);
+ make_binders(ctx.db, generic_params, val)
}
- },
- ))))
+ GenericParamDataRef::LifetimeParamData(_) => {
+ make_binders(ctx.db, generic_params, error_lifetime().cast(Interner))
+ }
+ }
+ }
}
-pub(crate) fn generic_defaults_recover(
+pub(crate) fn generic_defaults_with_diagnostics_recover(
db: &dyn HirDatabase,
_cycle: &Cycle,
def: &GenericDefId,
-) -> GenericDefaults {
+) -> (GenericDefaults, Diagnostics) {
let generic_params = generics(db.upcast(), *def);
if generic_params.len() == 0 {
- return GenericDefaults(None);
+ return (GenericDefaults(None), None);
}
// FIXME: this code is not covered in tests.
// we still need one default per parameter
- GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| {
+ let defaults = GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| {
let val = match id {
GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
};
crate::make_binders(db, &generic_params, val)
- }))))
+ }))));
+ (defaults, None)
}
fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
@@ -2196,7 +2254,10 @@ fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
make_binders(db, &generics, ty)
}
-fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
+pub(crate) fn type_for_type_alias_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ t: TypeAliasId,
+) -> (Binders<Ty>, Diagnostics) {
let generics = generics(db.upcast(), t.into());
let resolver = t.resolver(db.upcast());
let type_alias_data = db.type_alias_data(t);
@@ -2211,7 +2272,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
.map(|type_ref| ctx.lower_ty(type_ref))
.unwrap_or_else(|| TyKind::Error.intern(Interner))
};
- make_binders(db, &generics, inner)
+ (make_binders(db, &generics, inner), create_diagnostics(ctx.diagnostics))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -2254,7 +2315,7 @@ pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
match def {
TyDefId::BuiltinType(it) => Binders::empty(Interner, TyBuilder::builtin(it)),
TyDefId::AdtId(it) => type_for_adt(db, it),
- TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
+ TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
}
}
@@ -2279,47 +2340,73 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option<
}
pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
+ db.impl_self_ty_with_diagnostics(impl_id).0
+}
+
+pub(crate) fn impl_self_ty_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ impl_id: ImplId,
+) -> (Binders<Ty>, Diagnostics) {
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
let generics = generics(db.upcast(), impl_id.into());
let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
.with_type_param_mode(ParamLoweringMode::Variable);
- make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty))
+ (
+ make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty)),
+ create_diagnostics(ctx.diagnostics),
+ )
}
-// returns None if def is a type arg
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
+ db.const_param_ty_with_diagnostics(def).0
+}
+
+// returns None if def is a type arg
+pub(crate) fn const_param_ty_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ def: ConstParamId,
+) -> (Ty, Diagnostics) {
let parent_data = db.generic_params(def.parent());
let data = &parent_data[def.local_id()];
let resolver = def.parent().resolver(db.upcast());
let mut ctx =
TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into());
- match data {
+ let ty = match data {
TypeOrConstParamData::TypeParamData(_) => {
never!();
Ty::new(Interner, TyKind::Error)
}
TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
- }
+ };
+ (ty, create_diagnostics(ctx.diagnostics))
}
-pub(crate) fn impl_self_ty_recover(
+pub(crate) fn impl_self_ty_with_diagnostics_recover(
db: &dyn HirDatabase,
_cycle: &Cycle,
impl_id: &ImplId,
-) -> Binders<Ty> {
+) -> (Binders<Ty>, Diagnostics) {
let generics = generics(db.upcast(), (*impl_id).into());
- make_binders(db, &generics, TyKind::Error.intern(Interner))
+ (make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
}
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
+ db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
+}
+
+pub(crate) fn impl_trait_with_diagnostics_query(
+ db: &dyn HirDatabase,
+ impl_id: ImplId,
+) -> Option<(Binders<TraitRef>, Diagnostics)> {
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast());
let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
.with_type_param_mode(ParamLoweringMode::Variable);
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
let target_trait = impl_data.target_trait.as_ref()?;
- Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?))
+ let trait_ref = Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?);
+ Some((trait_ref, create_diagnostics(ctx.diagnostics)))
}
pub(crate) fn return_type_impl_traits(