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.rs | 210 |
1 files changed, 132 insertions, 78 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 23b15087e3..0c68891fe4 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -8,7 +8,6 @@ use std::{ cell::{Cell, RefCell, RefMut}, iter, - sync::Arc, }; use base_db::CrateId; @@ -18,19 +17,20 @@ use chalk_ir::{ use either::Either; use hir_def::{ - adt::StructKind, - body::{Expander, LowerCtx}, builtin_type::BuiltinType, + data::adt::StructKind, + expander::Expander, generics::{ TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, }, lang_item::{lang_attr, LangItem}, - path::{GenericArg, ModPath, Path, PathKind, PathSegment, PathSegments}, + nameres::MacroSubNs, + path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{ConstRefOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef}, - AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, - HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StaticId, StructId, - TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId, + AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, + GenericDefId, HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StaticId, + StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId, }; use hir_expand::{name::Name, ExpandResult}; use intern::Interned; @@ -39,6 +39,7 @@ use rustc_hash::FxHashSet; use smallvec::SmallVec; use stdx::{impl_from, never}; use syntax::ast; +use triomphe::Arc; use crate::{ all_super_traits, @@ -103,7 +104,7 @@ impl ImplTraitLoweringState { #[derive(Debug)] pub struct TyLoweringContext<'a> { pub db: &'a dyn HirDatabase, - pub resolver: &'a Resolver, + resolver: &'a Resolver, in_binders: DebruijnIndex, /// Note: Conceptually, it's thinkable that we could be in a location where /// some type params should be represented as placeholders, and others @@ -378,10 +379,19 @@ impl<'a> TyLoweringContext<'a> { }; let ty = { let macro_call = macro_call.to_node(self.db.upcast()); - match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call) { + let resolver = |path| { + self.resolver.resolve_path_as_macro( + self.db.upcast(), + &path, + Some(MacroSubNs::Bang), + ) + }; + match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver) + { Ok(ExpandResult { value: Some((mark, expanded)), .. }) => { - let ctx = LowerCtx::new(self.db.upcast(), expander.current_file_id()); - let type_ref = TypeRef::from_ast(&ctx, expanded); + let ctx = expander.ctx(self.db.upcast()); + // FIXME: Report syntax errors in expansion here + let type_ref = TypeRef::from_ast(&ctx, expanded.tree()); drop(expander); let ty = self.lower_ty(&type_ref); @@ -425,11 +435,10 @@ impl<'a> TyLoweringContext<'a> { if path.segments().len() > 1 { return None; } - let resolution = - match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { - Some((it, None)) => it, - _ => return None, - }; + let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { + Some((it, None)) => it, + _ => return None, + }; match resolution { TypeNs::GenericParam(param_id) => Some(param_id.into()), _ => None, @@ -608,7 +617,7 @@ impl<'a> TyLoweringContext<'a> { } let (resolution, remaining_index) = - match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { + match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { Some(it) => it, None => return (TyKind::Error.intern(Interner), None), }; @@ -716,7 +725,7 @@ impl<'a> TyLoweringContext<'a> { resolved: ValueTyDefId, infer_args: bool, ) -> Substitution { - let last = path.segments().last().expect("path should have at least one segment"); + let last = path.segments().last(); let (segment, generic_def) = match resolved { ValueTyDefId::FunctionId(it) => (last, Some(it.into())), ValueTyDefId::StructId(it) => (last, Some(it.into())), @@ -732,13 +741,20 @@ impl<'a> TyLoweringContext<'a> { let len = path.segments().len(); let penultimate = len.checked_sub(2).and_then(|idx| path.segments().get(idx)); let segment = match penultimate { - Some(segment) if segment.args_and_bindings.is_some() => segment, + Some(segment) if segment.args_and_bindings.is_some() => Some(segment), _ => last, }; (segment, Some(var.parent.into())) } }; - self.substs_from_path_segment(segment, generic_def, infer_args, None) + if let Some(segment) = segment { + self.substs_from_path_segment(segment, generic_def, infer_args, None) + } else if let Some(generic_def) = generic_def { + // lang item + self.substs_from_args_and_bindings(None, Some(generic_def), infer_args, None) + } else { + Substitution::empty(Interner) + } } fn substs_from_path_segment( @@ -748,6 +764,21 @@ impl<'a> TyLoweringContext<'a> { infer_args: bool, explicit_self_ty: Option<Ty>, ) -> Substitution { + self.substs_from_args_and_bindings( + segment.args_and_bindings, + def, + infer_args, + explicit_self_ty, + ) + } + + fn substs_from_args_and_bindings( + &self, + args_and_bindings: Option<&GenericArgs>, + def: Option<GenericDefId>, + infer_args: bool, + explicit_self_ty: Option<Ty>, + ) -> Substitution { // Remember that the item's own generic args come before its parent's. let mut substs = Vec::new(); let def = if let Some(d) = def { @@ -780,7 +811,7 @@ impl<'a> TyLoweringContext<'a> { }; let mut had_explicit_args = false; - if let Some(generic_args) = &segment.args_and_bindings { + if let Some(generic_args) = &args_and_bindings { if !generic_args.has_self_type { fill_self_params(); } @@ -879,12 +910,11 @@ impl<'a> TyLoweringContext<'a> { path: &Path, explicit_self_ty: Option<Ty>, ) -> Option<TraitRef> { - let resolved = - match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path.mod_path())? { - // FIXME(trait_alias): We need to handle trait alias here. - TypeNs::TraitId(tr) => tr, - _ => return None, - }; + let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? { + // FIXME(trait_alias): We need to handle trait alias here. + TypeNs::TraitId(tr) => tr, + _ => return None, + }; let segment = path.segments().last().expect("path should have at least one segment"); Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty)) } @@ -968,7 +998,7 @@ impl<'a> TyLoweringContext<'a> { // ignore `T: Drop` or `T: Destruct` bounds. // - `T: ~const Drop` has a special meaning in Rust 1.61 that we don't implement. // (So ideally, we'd only ignore `~const Drop` here) - // - `Destruct` impls are built-in in 1.62 (current nightlies as of 08-04-2022), so until + // - `Destruct` impls are built-in in 1.62 (current nightly as of 08-04-2022), so until // the builtin impls are supported by Chalk, we ignore them here. if let Some(lang) = lang_attr(self.db.upcast(), tr.hir_trait_id()) { if matches!(lang, LangItem::Drop | LangItem::Destruct) { @@ -1062,23 +1092,23 @@ impl<'a> TyLoweringContext<'a> { associated_ty_id: to_assoc_type_id(associated_ty), substitution, }; - let mut preds: SmallVec<[_; 1]> = SmallVec::with_capacity( + let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity( binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), ); if let Some(type_ref) = &binding.type_ref { let ty = self.lower_ty(type_ref); let alias_eq = AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; - preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); + predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); } for bound in binding.bounds.iter() { - preds.extend(self.lower_type_bound( + predicates.extend(self.lower_type_bound( bound, TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner), false, )); } - preds + predicates }) } @@ -1145,7 +1175,7 @@ impl<'a> TyLoweringContext<'a> { return None; } - // As multiple occurrences of the same auto traits *are* permitted, we dedulicate the + // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the // bounds. We shouldn't have repeated elements besides auto traits at this point. bounds.dedup(); @@ -1381,9 +1411,7 @@ pub(crate) fn generic_predicates_for_param_query( Some(it) => it, None => return true, }; - let tr = match resolver - .resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()) - { + let tr = match resolver.resolve_path_in_type_ns_fully(db.upcast(), path) { Some(TypeNs::TraitId(tr)) => tr, _ => return false, }; @@ -1420,7 +1448,19 @@ pub(crate) fn generic_predicates_for_param_recover( _param_id: &TypeOrConstParamId, _assoc_name: &Option<Name>, ) -> Arc<[Binders<QuantifiedWhereClause>]> { - Arc::new([]) + // FIXME: use `Arc::from_iter` when it becomes available + Arc::from(vec![]) +} + +pub(crate) fn trait_environment_for_body_query( + db: &dyn HirDatabase, + def: DefWithBodyId, +) -> Arc<TraitEnvironment> { + let Some(def) = def.as_generic_def_id() else { + let krate = def.module(db.upcast()).krate(); + return Arc::new(TraitEnvironment::empty(krate)); + }; + db.trait_environment(def) } pub(crate) fn trait_environment_query( @@ -1478,7 +1518,7 @@ pub(crate) fn trait_environment_query( let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses); - Arc::new(TraitEnvironment { krate, traits_from_clauses: traits_in_scope, env }) + Arc::new(TraitEnvironment { krate, block: None, traits_from_clauses: traits_in_scope, env }) } /// Resolve the where clause(s) of an item with generics. @@ -1547,30 +1587,33 @@ pub(crate) fn generic_defaults_query( let generic_params = generics(db.upcast(), def); let parent_start_idx = generic_params.len_self(); - let defaults = generic_params - .iter() - .enumerate() - .map(|(idx, (id, p))| { - let p = match p { - TypeOrConstParamData::TypeParamData(p) => p, - TypeOrConstParamData::ConstParamData(_) => { - // FIXME: implement const generic defaults - let val = unknown_const_as_generic( - db.const_param_ty(ConstParamId::from_unchecked(id)), - ); - return make_binders(db, &generic_params, val); - } - }; - let mut ty = - p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); - - // Each default can only refer to previous parameters. - // Type variable default referring to parameter coming - // after it is forbidden (FIXME: report diagnostic) - ty = fallback_bound_vars(ty, idx, parent_start_idx); - crate::make_binders(db, &generic_params, ty.cast(Interner)) - }) - .collect(); + let defaults = Arc::from( + generic_params + .iter() + .enumerate() + .map(|(idx, (id, p))| { + let p = match p { + TypeOrConstParamData::TypeParamData(p) => p, + TypeOrConstParamData::ConstParamData(_) => { + // FIXME: implement const generic defaults + let val = unknown_const_as_generic( + db.const_param_ty(ConstParamId::from_unchecked(id)), + ); + return make_binders(db, &generic_params, val); + } + }; + let mut ty = + p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); + + // Each default can only refer to previous parameters. + // Type variable default referring to parameter coming + // after it is forbidden (FIXME: report diagnostic) + ty = fallback_bound_vars(ty, idx, parent_start_idx); + crate::make_binders(db, &generic_params, ty.cast(Interner)) + }) + // FIXME: use `Arc::from_iter` when it becomes available + .collect::<Vec<_>>(), + ); defaults } @@ -1583,18 +1626,21 @@ pub(crate) fn generic_defaults_recover( let generic_params = generics(db.upcast(), *def); // FIXME: this code is not covered in tests. // we still need one default per parameter - let defaults = generic_params - .iter_id() - .map(|id| { - let val = match id { - Either::Left(_) => { - GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner) - } - Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)), - }; - crate::make_binders(db, &generic_params, val) - }) - .collect(); + let defaults = Arc::from( + generic_params + .iter_id() + .map(|id| { + let val = match id { + Either::Left(_) => { + GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner) + } + Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)), + }; + crate::make_binders(db, &generic_params, val) + }) + // FIXME: use `Arc::from_iter` when it becomes available + .collect::<Vec<_>>(), + ); defaults } @@ -1605,7 +1651,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { let ctx_params = TyLoweringContext::new(db, &resolver) .with_impl_trait_mode(ImplTraitLoweringMode::Variable) .with_type_param_mode(ParamLoweringMode::Variable); - let params = data.params.iter().map(|(_, tr)| ctx_params.lower_ty(tr)).collect::<Vec<_>>(); + let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)).collect::<Vec<_>>(); let ctx_ret = TyLoweringContext::new(db, &resolver) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); @@ -1948,7 +1994,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>( // as types. Maybe here is not the best place to do it, but // it works. if let TypeRef::Path(p) = t { - let p = p.mod_path(); + let p = p.mod_path()?; if p.kind == PathKind::Plain { if let [n] = p.segments() { let c = ConstRefOrPath::Path(n.clone()); @@ -1977,8 +2023,16 @@ pub(crate) fn const_or_path_to_chalk( ConstRefOrPath::Scalar(s) => intern_const_ref(db, s, expected_ty, resolver.krate()), ConstRefOrPath::Path(n) => { let path = ModPath::from_segments(PathKind::Plain, Some(n.clone())); - path_to_const(db, resolver, &path, mode, args, debruijn) - .unwrap_or_else(|| unknown_const(expected_ty)) + path_to_const( + db, + resolver, + &Path::from_known_path_with_no_generic(path), + mode, + args, + debruijn, + expected_ty.clone(), + ) + .unwrap_or_else(|| unknown_const(expected_ty)) } } } |