Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 493 |
1 files changed, 290 insertions, 203 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index d24e2c0cb5..63b834a8d1 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -75,6 +75,7 @@ use hir_def::{ TypeAliasSignature, UnionSignature, VariantFields, }, src::HasSource as _, + unstable_features::UnstableFeatures, visibility::visibility_from_ast, }; use hir_expand::{ @@ -82,16 +83,14 @@ use hir_expand::{ proc_macro::ProcMacroKind, }; use hir_ty::{ - GenericPredicates, InferenceResult, ParamEnvAndCrate, TyDefId, TyLoweringDiagnostic, - ValueTyDefId, all_super_traits, autoderef, check_orphan_rules, + GenericPredicates, InferBodyId, InferenceResult, ParamEnvAndCrate, TyDefId, + TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, check_orphan_rules, consteval::try_const_usize, - db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId}, + db::{AnonConstId, InternedClosure, InternedClosureId, InternedCoroutineClosureId}, diagnostics::BodyValidationDiagnostic, direct_super_traits, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, - method_resolution::{ - self, InherentImpls, MethodResolutionContext, MethodResolutionUnstableFeatures, - }, + method_resolution::{self, InherentImpls, MethodResolutionContext}, mir::interpret_mir, next_solver::{ AliasTy, AnyImplId, ClauseKind, ConstKind, DbInterner, EarlyBinder, EarlyParamRegion, @@ -106,7 +105,7 @@ use rustc_hash::FxHashSet; use rustc_type_ir::{ AliasTyKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, fast_reject, - inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _}, + inherent::{GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _}, }; use span::{AstIdNode, Edition, FileId}; use stdx::{format_to, impl_from, never}; @@ -115,7 +114,7 @@ use syntax::{ ast::{self, HasName as _, HasVisibility as _}, format_smolstr, }; -use triomphe::{Arc, ThinArc}; +use triomphe::Arc; use crate::db::{DefDatabase, HirDatabase}; @@ -174,7 +173,7 @@ pub use { // FIXME: Properly encapsulate mir hir_ty::mir, hir_ty::{ - CastError, FnAbi, PointerCast, attach_db, attach_db_allow_change, + CastError, PointerCast, attach_db, attach_db_allow_change, consteval::ConstEvalError, diagnostics::UnsafetyReason, display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, @@ -197,7 +196,7 @@ use { hir_def::expr_store::path::Path, hir_expand::{ name::AsName, - span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, + span_map::{ExpansionSpanMap, RealSpanMap, SpanMap}, }, }; @@ -343,7 +342,7 @@ impl Crate { } pub fn is_unstable_feature_enabled(self, db: &dyn HirDatabase, feature: &Symbol) -> bool { - crate_def_map(db, self.id).is_unstable_feature_enabled(feature) + UnstableFeatures::query(db, self.id).is_enabled(feature) } } @@ -760,7 +759,7 @@ impl Module { push_ty_diagnostics( db, acc, - db.field_types_with_diagnostics(s.id.into()).1.clone(), + db.field_types_with_diagnostics(s.id.into()).diagnostics(), source_map, ); } @@ -772,7 +771,7 @@ impl Module { push_ty_diagnostics( db, acc, - db.field_types_with_diagnostics(u.id.into()).1.clone(), + db.field_types_with_diagnostics(u.id.into()).diagnostics(), source_map, ); } @@ -802,7 +801,7 @@ impl Module { push_ty_diagnostics( db, acc, - db.field_types_with_diagnostics(v.into()).1.clone(), + db.field_types_with_diagnostics(v.into()).diagnostics(), source_map, ); expr_store_diagnostics(db, acc, source_map); @@ -818,7 +817,7 @@ impl Module { push_ty_diagnostics( db, acc, - db.type_for_type_alias_with_diagnostics(type_alias.id).1, + db.type_for_type_alias_with_diagnostics(type_alias.id).diagnostics(), source_map, ); acc.extend(def.diagnostics(db, style_lints)); @@ -881,7 +880,6 @@ impl Module { } let drop_maybe_dangle = (|| { - // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper let trait_ = trait_?; let drop_trait = interner.lang_items().Drop?; if drop_trait != trait_.into() { @@ -948,7 +946,7 @@ impl Module { .collect(); if !missing.is_empty() { - let self_ty = db.impl_self_ty(impl_id).instantiate_identity(); + let self_ty = db.impl_self_ty(impl_id).instantiate_identity().skip_norm_wip(); let self_ty = structurally_normalize_ty( &infcx, self_ty, @@ -984,10 +982,8 @@ impl Module { // relationship here would be significantly more expensive. if !missing.is_empty() { let krate = self.krate(db).id; - let def_map = crate_def_map(db, krate); - if def_map.is_unstable_feature_enabled(&sym::specialization) - || def_map.is_unstable_feature_enabled(&sym::min_specialization) - { + let features = UnstableFeatures::query(db, krate); + if features.specialization || features.min_specialization { missing.retain(|(assoc_name, assoc_item)| { let AssocItem::Function(_) = assoc_item else { return true; @@ -1031,11 +1027,19 @@ impl Module { impl_assoc_items_scratch.clear(); } - push_ty_diagnostics(db, acc, db.impl_self_ty_with_diagnostics(impl_id).1, source_map); push_ty_diagnostics( db, acc, - db.impl_trait_with_diagnostics(impl_id).and_then(|it| it.1), + db.impl_self_ty_with_diagnostics(impl_id).diagnostics(), + source_map, + ); + push_ty_diagnostics( + db, + acc, + db.impl_trait_with_diagnostics(impl_id) + .as_ref() + .map(|it| it.diagnostics()) + .unwrap_or_default(), source_map, ); @@ -1124,9 +1128,9 @@ fn macro_call_diagnostics<'db>( let Some(e) = db.parse_macro_expansion_error(macro_call_id) else { return; }; - let ValueResult { value: parse_errors, err } = &*e; + let ValueResult { value: parse_errors, err } = e; if let Some(err) = err { - let loc = db.lookup_intern_macro_call(macro_call_id); + let loc = macro_call_id.loc(db); let file_id = loc.kind.file_id(); let mut range = precise_macro_call_location(&loc.kind, db, loc.krate); let RenderedExpandError { message, error, kind } = err.render_to_string(db); @@ -1138,7 +1142,7 @@ fn macro_call_diagnostics<'db>( } if !parse_errors.is_empty() { - let loc = db.lookup_intern_macro_call(macro_call_id); + let loc = macro_call_id.loc(db); let range = precise_macro_call_location(&loc.kind, db, loc.krate); acc.push(MacroExpansionParseError { range, errors: parse_errors.clone() }.into()) } @@ -1341,14 +1345,14 @@ impl<'db> InstantiatedField<'db> { let var_id = self.inner.parent.into(); let field = db.field_types(var_id)[self.inner.id].get(); - let ty = field.instantiate(interner, self.args); + let ty = field.instantiate(interner, self.args).skip_norm_wip(); TypeNs::new(db, var_id, ty) } } #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub struct TupleField { - pub owner: ExpressionStoreOwnerId, + pub owner: InferBodyId, pub tuple: TupleId, pub index: u32, } @@ -1366,7 +1370,7 @@ impl TupleField { .get(self.index as usize) .copied() .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)); - Type { env: body_param_env_from_has_crate(db, self.owner), ty } + Type { env: body_param_env_from_has_crate(db, self.owner.expression_store_owner(db)), ty } } } @@ -1436,11 +1440,11 @@ impl Field { }; let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty)); - let ty = db.field_types(var_id)[self.id].get().instantiate(interner, args); + let ty = db.field_types(var_id)[self.id].get().instantiate(interner, args).skip_norm_wip(); Type::new(db, var_id, ty) } - pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + pub fn layout<'db>(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> { db.layout_of_ty( self.ty(db).ty.store(), param_env_from_has_crate( @@ -1529,7 +1533,7 @@ impl Struct { } pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedStruct<'db> { - let args = infer_ctxt.fresh_args_for_item(self.id.into()); + let args = infer_ctxt.fresh_args_for_item(hir_ty::Span::Dummy, self.id.into()); InstantiatedStruct { inner: self, args } } } @@ -1566,7 +1570,7 @@ impl<'db> InstantiatedStruct<'db> { let interner = DbInterner::new_no_crate(db); let ty = db.ty(self.inner.id.into()); - TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) + TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args).skip_norm_wip()) } } @@ -1700,7 +1704,7 @@ impl Enum { self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit)) } - pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + pub fn layout<'db>(self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> { Adt::from(self).layout(db) } @@ -1728,7 +1732,7 @@ impl<'db> InstantiatedEnum<'db> { let interner = DbInterner::new_no_crate(db); let ty = db.ty(self.inner.id.into()); - TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) + TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args).skip_norm_wip()) } } @@ -1787,7 +1791,7 @@ impl EnumVariant { db.const_eval_discriminant(self.into()) } - pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + pub fn layout<'db>(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> { let parent_enum = self.parent_enum(db); let parent_layout = parent_enum.layout(db)?; Ok(match &parent_layout.0.variants { @@ -1808,8 +1812,10 @@ impl EnumVariant { } pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedVariant<'db> { - let args = - infer_ctxt.fresh_args_for_item(self.parent_enum(infer_ctxt.interner.db()).id.into()); + let args = infer_ctxt.fresh_args_for_item( + hir_ty::Span::Dummy, + self.parent_enum(infer_ctxt.interner.db()).id.into(), + ); InstantiatedVariant { inner: self, args } } } @@ -1868,7 +1874,7 @@ impl Adt { has_non_default_type_params(db, self.into()) } - pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { + pub fn layout<'db>(self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> { let interner = DbInterner::new_no_crate(db); let adt_id = AdtId::from(self); let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| { @@ -1988,6 +1994,47 @@ impl Variant { Variant::EnumVariant(e) => (*e).name(db), } } + + pub fn adt(&self, db: &dyn HirDatabase) -> Adt { + match *self { + Variant::Struct(it) => it.into(), + Variant::Union(it) => it.into(), + Variant::EnumVariant(it) => it.parent_enum(db).into(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct AnonConst { + id: AnonConstId, +} + +impl AnonConst { + pub fn owner(self, db: &dyn HirDatabase) -> ExpressionStoreOwner { + self.id.loc(db).owner.into() + } + + pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { + let loc = self.id.loc(db); + let env = body_param_env_from_has_crate(db, loc.owner); + Type { env, ty: loc.ty.get().instantiate_identity().skip_norm_wip() } + } + + pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> { + let interner = DbInterner::new_no_crate(db); + let ty = self.id.loc(db).ty.get().instantiate_identity().skip_norm_wip(); + db.anon_const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { + allocation: it, + def: self.id.into(), + ty, + }) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum InferBody { + Body(DefWithBody), + AnonConst(AnonConst), } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -2084,6 +2131,12 @@ impl DefWithBody { }) } + #[deprecated = "you should really not use this, this is exported for analysis-stats only"] + pub fn run_mir_body(self, db: &dyn HirDatabase) -> Result<(), MirLowerError> { + let Some(id) = self.id() else { return Ok(()) }; + db.mir_body(id.into()).map(drop) + } + /// A textual representation of the HIR of this def's body for debugging purposes. pub fn debug_hir(self, db: &dyn HirDatabase) -> String { let Some(id) = self.id() else { @@ -2098,7 +2151,7 @@ impl DefWithBody { let Some(id) = self.id() else { return String::new(); }; - let body = db.mir_body(id); + let body = db.mir_body(id.into()); match body { Ok(body) => body.pretty_print(db, self.module(db).krate(db).to_display_target(db)), Err(e) => format!("error:\n{e:?}"), @@ -2115,6 +2168,7 @@ impl DefWithBody { return; }; let krate = self.module(db).id.krate(db); + let env = body_param_env_from_has_crate(db, id); let (body, source_map) = Body::with_source_map(db, id); let sig_source_map = match self { @@ -2138,34 +2192,14 @@ impl DefWithBody { let infer = InferenceResult::of(db, id); for d in infer.diagnostics() { - acc.extend(AnyDiagnostic::inference_diagnostic(db, id, d, source_map, sig_source_map)); - } - - for (pat_or_expr, mismatch) in infer.type_mismatches() { - let expr_or_pat = match pat_or_expr { - ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left), - ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), - }; - let expr_or_pat = match expr_or_pat { - Ok(Either::Left(expr)) => expr, - Ok(Either::Right(InFile { file_id, value: pat })) => { - // cast from Either<Pat, SelfParam> -> Either<_, Pat> - let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { - continue; - }; - InFile { file_id, value: ptr } - } - Err(SyntheticSyntax) => continue, - }; - - acc.push( - TypeMismatch { - expr_or_pat, - expected: Type::new(db, id, mismatch.expected.as_ref()), - actual: Type::new(db, id, mismatch.actual.as_ref()), - } - .into(), - ); + acc.extend(AnyDiagnostic::inference_diagnostic( + db, + id, + d, + source_map, + sig_source_map, + env, + )); } let missing_unsafe = hir_ty::diagnostics::missing_unsafe(db, id); @@ -2203,9 +2237,9 @@ impl DefWithBody { } } - if let Ok(borrowck_results) = db.borrowck(id) { + if let Ok(borrowck_results) = db.borrowck(id.into()) { for borrowck_result in borrowck_results.iter() { - let mir_body = &borrowck_result.mir_body; + let mir_body = borrowck_result.mir_body(db); for moof in &borrowck_result.moved_out_of_ref { let span: InFile<SyntaxNodePtr> = match moof.span { mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) { @@ -2260,7 +2294,8 @@ impl DefWithBody { { need_mut = &mir::MutabilityReason::Not; } - let local = Local { parent: id.into(), binding_id }; + let local = + Local { parent: id.into(), parent_infer: mir_body.owner, binding_id }; let is_mut = body[binding_id].mode == BindingAnnotation::Mutable; match (need_mut, is_mut) { @@ -2382,6 +2417,9 @@ fn expr_store_diagnostics<'db>( ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => { UndeclaredLabel { node: *node, name: name.clone() }.into() } + ExpressionStoreDiagnostics::PatternArgInExternFn { node } => { + PatternArgInExternFn { node: *node }.into() + } }); } @@ -2448,7 +2486,8 @@ impl Function { let resolver = id.resolver(db); let interner = DbInterner::new_no_crate(db); // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. - let callable_sig = db.callable_item_signature(id.into()).instantiate_identity(); + let callable_sig = + db.callable_item_signature(id.into()).instantiate_identity().skip_norm_wip(); let ty = Ty::new_fn_ptr(interner, callable_sig); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -2525,10 +2564,13 @@ impl Function { // `impl_generics_len - impl_trait_ref.args.len()`. let trait_method_fn_ptr = Ty::new_fn_ptr( interner, - db.callable_item_signature(trait_method.into()).instantiate_identity(), + db.callable_item_signature(trait_method.into()) + .instantiate_identity() + .skip_norm_wip(), ); - let impl_trait_ref = - hir_ty::builtin_derive::impl_trait(interner, impl_).instantiate_identity(); + let impl_trait_ref = hir_ty::builtin_derive::impl_trait(interner, impl_) + .instantiate_identity() + .skip_norm_wip(); let trait_method_args = GenericArgs::identity_for_item(interner, trait_method.into()); let trait_method_own_args = GenericArgs::new_from_iter( @@ -2543,8 +2585,9 @@ impl Function { interner, impl_trait_ref.args.iter().chain(shifted_trait_method_own_args), ); - let impl_method_fn_ptr = - EarlyBinder::bind(trait_method_fn_ptr).instantiate(interner, impl_method_args); + let impl_method_fn_ptr = EarlyBinder::bind(trait_method_fn_ptr) + .instantiate(interner, impl_method_args) + .skip_norm_wip(); Type { env, ty: impl_method_fn_ptr } } } @@ -2575,7 +2618,7 @@ impl Function { let ret_type = self.ret_type(db); let interner = DbInterner::new_no_crate(db); let args = self.adapt_generic_args(interner, generics); - ret_type.derived(EarlyBinder::bind(ret_type.ty).instantiate(interner, args)) + ret_type.derived(EarlyBinder::bind(ret_type.ty).instantiate(interner, args).skip_norm_wip()) } fn adapt_generic_args<'db>( @@ -2690,7 +2733,7 @@ impl Function { idx: param.idx, ty: Type { env: param.ty.env, - ty: EarlyBinder::bind(param.ty.ty).instantiate(interner, args), + ty: EarlyBinder::bind(param.ty.ty).instantiate(interner, args).skip_norm_wip(), }, }) .collect() @@ -2957,25 +3000,38 @@ impl<'db> Param<'db> { Callee::Def(CallableDefId::FunctionId(it)) => { let parent = DefWithBodyId::FunctionId(it); let body = Body::of(db, parent); - if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) { - Some(Local { parent: parent.into(), binding_id: self_param }) + if let Some(self_param) = body.self_param().filter(|_| self.idx == 0) { + Some(Local { + parent: parent.into(), + parent_infer: parent.into(), + binding_id: self_param, + }) } else if let Pat::Bind { id, .. } = - &body[body.params[self.idx - body.self_param.is_some() as usize]] + &body[body.params[self.idx - body.self_param().is_some() as usize]] { - Some(Local { parent: parent.into(), binding_id: *id }) + Some(Local { + parent: parent.into(), + parent_infer: parent.into(), + binding_id: *id, + }) } else { None } } Callee::Closure(closure, _) => { let c = closure.loc(db); - let body_owner = c.0; - let store = ExpressionStore::of(db, c.0); + let body_infer_owner = c.owner; + let body_owner = c.owner.expression_store_owner(db); + let store = ExpressionStore::of(db, body_owner); - if let Expr::Closure { args, .. } = &store[c.1] + if let Expr::Closure { args, .. } = &store[c.expr] && let Pat::Bind { id, .. } = &store[args[self.idx]] { - return Some(Local { parent: body_owner, binding_id: *id }); + return Some(Local { + parent: body_owner, + parent_infer: body_infer_owner, + binding_id: *id, + }); } None } @@ -3042,7 +3098,7 @@ impl SelfParam { let interner = DbInterner::new_no_crate(db); let args = self.func.adapt_generic_args(interner, generics); let Type { env, ty } = self.ty(db); - Type { env, ty: EarlyBinder::bind(ty).instantiate(interner, args) } + Type { env, ty: EarlyBinder::bind(ty).instantiate(interner, args).skip_norm_wip() } } } @@ -3140,7 +3196,7 @@ impl Const { /// Evaluate the constant. pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> { let interner = DbInterner::new_no_crate(db); - let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); + let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip(); db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), @@ -3156,7 +3212,7 @@ impl HasVisibility for Const { } pub struct EvaluatedConst<'db> { - def: DefWithBodyId, + def: InferBodyId, allocation: hir_ty::next_solver::Allocation<'db>, ty: Ty<'db>, } @@ -3220,7 +3276,7 @@ impl Static { /// Evaluate the static initializer. pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError> { - let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); + let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip(); db.const_eval_static(self.id).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), @@ -4018,7 +4074,7 @@ impl AssocItem { push_ty_diagnostics( db, acc, - db.type_for_type_alias_with_diagnostics(type_alias.id).1, + db.type_for_type_alias_with_diagnostics(type_alias.id).diagnostics(), &TypeAliasSignature::with_source_map(db, type_alias.id).1, ); for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) { @@ -4182,26 +4238,24 @@ impl GenericDef { }; expr_store_diagnostics(db, acc, source_map); - push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, source_map); push_ty_diagnostics( db, acc, - GenericPredicates::query_with_diagnostics(db, def).1.clone(), + db.generic_defaults_with_diagnostics(def).diagnostics(), + source_map, + ); + push_ty_diagnostics( + db, + acc, + GenericPredicates::query_with_diagnostics(db, def).diagnostics(), + source_map, + ); + push_ty_diagnostics( + db, + acc, + db.const_param_types_with_diagnostics(def).diagnostics(), source_map, ); - for (param_id, param) in generics.iter_type_or_consts() { - if let TypeOrConstParamData::ConstParamData(_) = param { - push_ty_diagnostics( - db, - acc, - db.const_param_ty_with_diagnostics(ConstParamId::from_unchecked( - TypeOrConstParamId { parent: def, local_id: param_id }, - )) - .1, - source_map, - ); - } - } } /// Returns a string describing the kind of this type. @@ -4296,6 +4350,7 @@ impl<'db> GenericSubstitution<'db> { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Local { pub(crate) parent: ExpressionStoreOwnerId, + pub(crate) parent_infer: InferBodyId, pub(crate) binding_id: BindingId, } @@ -4397,7 +4452,7 @@ impl Local { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let def = self.parent; - let infer = InferenceResult::of(db, def); + let infer = InferenceResult::of(db, self.parent_infer); let ty = infer.binding_ty(self.binding_id); Type::new(db, def, ty) } @@ -4411,8 +4466,8 @@ impl Local { } ExpressionStoreOwnerId::Body(def_with_body_id) => { b = Body::with_source_map(db, def_with_body_id); - if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax()) - && param == self.binding_id + if b.0.self_params.contains(&self.binding_id) + && let Some(source) = b.1.self_param_syntax() { let root = source.file_syntax(db); return vec![LocalSource { @@ -4452,8 +4507,8 @@ impl Local { } ExpressionStoreOwnerId::Body(def_with_body_id) => { b = Body::with_source_map(db, def_with_body_id); - if let Some((param, source)) = b.0.self_param.zip(b.1.self_param_syntax()) - && param == self.binding_id + if b.0.self_params.contains(&self.binding_id) + && let Some(source) = b.1.self_param_syntax() { let root = source.file_syntax(db); return LocalSource { @@ -4624,13 +4679,12 @@ impl GenericParam { GenericParam::ConstParam(_) => return None, GenericParam::LifetimeParam(it) => it.id.parent, }; - let generics = hir_ty::generics::generics(db, parent); let index = match self { - GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?, + GenericParam::TypeParam(it) => hir_ty::type_or_const_param_idx(db, it.id.into()), GenericParam::ConstParam(_) => return None, - GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?, + GenericParam::LifetimeParam(it) => hir_ty::lifetime_param_idx(db, it.id), }; - db.variances_of(parent).get(index).map(Into::into) + db.variances_of(parent).get(index as usize).map(Into::into) } } @@ -4702,8 +4756,8 @@ impl TypeParam { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); let interner = DbInterner::new_no_crate(db); - let index = hir_ty::param_idx(db, self.id.into()).unwrap(); - let ty = Ty::new_param(interner, self.id, index as u32); + let index = hir_ty::type_or_const_param_idx(db, self.id.into()); + let ty = Ty::new_param(interner, self.id, index); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -4789,25 +4843,30 @@ impl ConstParam { } pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { - Type::new(db, self.id.parent(), db.const_param_ty_ns(self.id)) + Type::new(db, self.id.parent(), db.const_param_ty(self.id)) + } + + pub fn default(self, db: &dyn HirDatabase, display_target: DisplayTarget) -> Option<String> { + let arg = generic_arg_from_param(db, self.id.into())?; + Some(arg.display(db, display_target).to_string()) } - pub fn default( + pub fn default_source_code( self, db: &dyn HirDatabase, - display_target: DisplayTarget, + target_module: Module, ) -> Option<ast::ConstArg> { let arg = generic_arg_from_param(db, self.id.into())?; - known_const_to_ast(arg.konst()?, db, display_target) + known_const_to_ast(arg.konst()?, db, target_module.id) } } fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> { - let local_idx = hir_ty::param_idx(db, id)?; + let local_idx = hir_ty::type_or_const_param_idx(db, id); let defaults = db.generic_defaults(id.parent); - let ty = defaults.get(local_idx)?; + let ty = defaults.get(local_idx as usize)?; // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. - Some(ty.instantiate_identity()) + Some(ty.instantiate_identity().skip_norm_wip()) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -4982,7 +5041,7 @@ impl Impl { pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> { match self.id { AnyImplId::ImplId(id) => { - let trait_ref = db.impl_trait(id)?.instantiate_identity(); + let trait_ref = db.impl_trait(id)?.instantiate_identity().skip_norm_wip(); let resolver = id.resolver(db); Some(TraitRef::new_with_resolver(db, &resolver, trait_ref)) } @@ -4994,8 +5053,9 @@ impl Impl { param_env: hir_ty::builtin_derive::param_env(interner, id), krate, }; - let trait_ref = - hir_ty::builtin_derive::impl_trait(interner, id).instantiate_identity(); + let trait_ref = hir_ty::builtin_derive::impl_trait(interner, id) + .instantiate_identity() + .skip_norm_wip(); Some(TraitRef { env, trait_ref }) } } @@ -5006,7 +5066,7 @@ impl Impl { AnyImplId::ImplId(id) => { let resolver = id.resolver(db); // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. - let ty = db.impl_self_ty(id).instantiate_identity(); + let ty = db.impl_self_ty(id).instantiate_identity().skip_norm_wip(); Type::new_with_resolver_inner(db, &resolver, ty) } AnyImplId::BuiltinDeriveImplId(id) => { @@ -5019,6 +5079,7 @@ impl Impl { }; let ty = hir_ty::builtin_derive::impl_trait(interner, id) .instantiate_identity() + .skip_norm_wip() .self_ty(); Type { env, ty } } @@ -5159,14 +5220,15 @@ impl<'db> Closure<'db> { AnyClosureId::ClosureId(it) => it.loc(db), AnyClosureId::CoroutineClosureId(it) => it.loc(db), }; - let InternedClosure(owner, closure) = closure; - let infer = InferenceResult::of(db, owner); + let InternedClosure { owner: infer_owner, expr: closure, .. } = closure; + let infer = InferenceResult::of(db, infer_owner); + let owner = infer_owner.expression_store_owner(db); let param_env = body_param_env_from_has_crate(db, owner); infer.closures_data[&closure] .min_captures .values() .flatten() - .map(|capture| ClosureCapture { owner, closure, capture, param_env }) + .map(|capture| ClosureCapture { owner, infer_owner, closure, capture, param_env }) .collect() } @@ -5254,6 +5316,7 @@ impl FnTrait { #[derive(Clone, Debug, PartialEq, Eq)] pub struct ClosureCapture<'db> { owner: ExpressionStoreOwnerId, + infer_owner: InferBodyId, closure: ExprId, capture: &'db hir_ty::closure_analysis::CapturedPlace, param_env: ParamEnvAndCrate<'db>, @@ -5261,7 +5324,11 @@ pub struct ClosureCapture<'db> { impl<'db> ClosureCapture<'db> { pub fn local(&self) -> Local { - Local { parent: self.owner, binding_id: self.capture.captured_local() } + Local { + parent: self.owner, + parent_infer: self.infer_owner, + binding_id: self.capture.captured_local(), + } } /// Returns whether this place has any field (aka. non-deref) projections. @@ -5304,7 +5371,7 @@ impl<'db> ClosureCapture<'db> { match ty.kind() { TyKind::Tuple(_) => format_to!(result, "_{field_idx}"), TyKind::Adt(adt_def, _) => { - let variant = match adt_def.def_id().0 { + let variant = match adt_def.def_id() { AdtId::StructId(id) => VariantId::from(id), AdtId::UnionId(id) => id.into(), AdtId::EnumId(id) => { @@ -5338,7 +5405,7 @@ impl<'db> ClosureCapture<'db> { match ty.kind() { TyKind::Tuple(_) => format_to!(result, ".{field_idx}"), TyKind::Adt(adt_def, _) => { - let variant = match adt_def.def_id().0 { + let variant = match adt_def.def_id() { AdtId::StructId(id) => VariantId::from(id), AdtId::UnionId(id) => id.into(), AdtId::EnumId(id) => { @@ -5488,13 +5555,13 @@ impl<'db> Type<'db> { } }; let args = GenericArgs::error_for_item(interner, def.into()); - Type::new(db, def, ty.instantiate(interner, args)) + Type::new(db, def, ty.instantiate(interner, args).skip_norm_wip()) } // FIXME: We shouldn't leak `TyKind::Param`s. fn from_def_params(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self { let ty = db.ty(def.into()); - Type::new(db, def, ty.instantiate_identity()) + Type::new(db, def, ty.instantiate_identity().skip_norm_wip()) } fn from_value_def( @@ -5518,7 +5585,7 @@ impl<'db> Type<'db> { } }; let args = GenericArgs::error_for_item(interner, def.into()); - Type::new(db, def, ty.instantiate(interner, args)) + Type::new(db, def, ty.instantiate(interner, args).skip_norm_wip()) } pub fn new_slice(ty: Self) -> Self { @@ -5584,7 +5651,7 @@ impl<'db> Type<'db> { // For non-phantom_data adts we check variants/fields as well as generic parameters TyKind::Adt(adt_def, args) - if !is_phantom_data(self.interner.db(), adt_def.def_id().0) => + if !is_phantom_data(self.interner.db(), adt_def.def_id()) => { let _variant_id_to_fields = |id: VariantId| { let variant_data = &id.fields(self.interner.db()); @@ -5596,7 +5663,10 @@ impl<'db> Type<'db> { .fields() .iter() .map(|(idx, _)| { - field_types[idx].get().instantiate(self.interner, args) + field_types[idx] + .get() + .instantiate(self.interner, args) + .skip_norm_wip() }) .filter(|it| !it.references_non_lt_error()) .collect() @@ -5604,7 +5674,7 @@ impl<'db> Type<'db> { }; let variant_id_to_fields = |_: VariantId| vec![]; - let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id().0 { + let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id() { AdtId::StructId(id) => { vec![variant_id_to_fields(id.into())] } @@ -5710,21 +5780,15 @@ impl<'db> Type<'db> { /// This function is used in `.await` syntax completion. pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> { let lang_items = hir_def::lang_item::lang_items(db, self.env.krate); - let trait_ = lang_items - .IntoFutureIntoFuture - .and_then(|into_future_fn| { - let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?; - let into_future_trait = assoc_item.container_or_implemented_trait(db)?; - Some(into_future_trait.id) - }) - .or(lang_items.Future)?; + let (trait_, output_assoc_type) = lang_items + .IntoFuture + .zip(lang_items.IntoFutureOutput) + .or(lang_items.Future.zip(lang_items.FutureOutput))?; if !traits::implements_trait_unique(self.ty, db, self.env, trait_) { return None; } - let output_assoc_type = - trait_.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Output))?; self.normalize_trait_assoc_type(db, &[], output_assoc_type.into()) } @@ -5738,10 +5802,7 @@ impl<'db> Type<'db> { /// This does **not** resolve `IntoIterator`, only `Iterator`. pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> { let lang_items = hir_def::lang_item::lang_items(db, self.env.krate); - let iterator_trait = lang_items.Iterator?; - let iterator_item = iterator_trait - .trait_items(db) - .associated_type_by_name(&Name::new_symbol_root(sym::Item))?; + let iterator_item = lang_items.IteratorItem?; self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } @@ -5756,19 +5817,13 @@ impl<'db> Type<'db> { /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> { let lang_items = hir_def::lang_item::lang_items(db, self.env.krate); - let trait_ = lang_items.IntoIterIntoIter.and_then(|into_iter_fn| { - let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?; - let into_iter_trait = assoc_item.container_or_implemented_trait(db)?; - Some(into_iter_trait.id) - })?; + let trait_ = lang_items.IntoIterator?; if !traits::implements_trait_unique(self.ty, db, self.env, trait_) { return None; } - let into_iter_assoc_type = trait_ - .trait_items(db) - .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?; + let into_iter_assoc_type = lang_items.IntoIterIntoIterType?; self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into()) } @@ -5882,7 +5937,7 @@ impl<'db> Type<'db> { pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool { let adt_id = match self.ty.kind() { - TyKind::Adt(adt_def, ..) => adt_def.def_id().0, + TyKind::Adt(adt_def, ..) => adt_def.def_id(), _ => return false, }; @@ -5921,7 +5976,7 @@ impl<'db> Type<'db> { let interner = DbInterner::new_no_crate(db); let (variant_id, substs) = match self.ty.kind() { TyKind::Adt(adt_def, substs) => { - let id = match adt_def.def_id().0 { + let id = match adt_def.def_id() { AdtId::StructId(id) => id.into(), AdtId::UnionId(id) => id.into(), AdtId::EnumId(_) => return Vec::new(), @@ -5935,7 +5990,7 @@ impl<'db> Type<'db> { .iter() .map(|(local_id, ty)| { let def = Field { parent: variant_id.into(), id: local_id }; - let ty = ty.get().instantiate(interner, substs); + let ty = ty.get().instantiate(interner, substs).skip_norm_wip(); (def, self.derived(ty)) }) .collect() @@ -6178,8 +6233,7 @@ impl<'db> Type<'db> { TypingMode::non_body_analysis() }; let infcx = interner.infer_ctxt().build(typing_mode); - let unstable_features = - MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map()); + let features = resolver.top_level_def_map().features(); let environment = param_env_from_resolver(db, resolver); let ctx = MethodResolutionContext { infcx: &infcx, @@ -6187,7 +6241,9 @@ impl<'db> Type<'db> { param_env: environment.param_env, traits_in_scope, edition: resolver.krate().data(db).edition, - unstable_features: &unstable_features, + features, + call_span: hir_ty::Span::Dummy, + receiver_span: hir_ty::Span::Dummy, }; f(&ctx) } @@ -6214,7 +6270,7 @@ impl<'db> Type<'db> { self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| { // There should be no inference vars in types passed here let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty); - let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical); + let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical); match name { Some(name) => { @@ -6322,7 +6378,7 @@ impl<'db> Type<'db> { self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| { // There should be no inference vars in types passed here let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty); - let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical); + let (self_ty, _) = ctx.infcx.instantiate_canonical(hir_ty::Span::Dummy, &canonical); match name { Some(name) => { @@ -6437,7 +6493,7 @@ impl<'db> Type<'db> { else { return None; }; - match def_id.expect_type_alias().loc(db).container { + match def_id.0.loc(db).container { ItemContainerId::TraitId(id) => Some(Trait { id }), _ => None, } @@ -6521,7 +6577,7 @@ impl<'db> Type<'db> { .collect() } - pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> { + pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout<'db>, LayoutError> { db.layout_of_ty(self.ty.store(), self.env.store()) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } @@ -6558,21 +6614,13 @@ impl<'db> TypeNs<'db> { ); let trait_ref = hir_ty::next_solver::TraitRef::new_from_args(infcx.interner, trait_.id.into(), args); - - let pred_kind = rustc_type_ir::Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(rustc_type_ir::TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )); - let predicate = hir_ty::next_solver::Predicate::new(infcx.interner, pred_kind); - let goal = hir_ty::next_solver::Goal::new( + let obligation = hir_ty::next_solver::infer::traits::Obligation::new( infcx.interner, - hir_ty::next_solver::ParamEnv::empty(), - predicate, + hir_ty::next_solver::infer::traits::ObligationCause::dummy(), + self.env.param_env, + trait_ref, ); - let res = hir_ty::traits::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) } pub fn is_bool(&self) -> bool { @@ -6701,9 +6749,9 @@ impl<'db> Callable<'db> { } #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>); +pub struct Layout<'db>(Arc<TyLayout>, &'db TargetDataLayout); -impl Layout { +impl<'db> Layout<'db> { pub fn size(&self) -> u64 { self.0.size.bytes() } @@ -6713,7 +6761,7 @@ impl Layout { } pub fn niches(&self) -> Option<u128> { - Some(self.0.largest_niche?.available(&*self.1)) + Some(self.0.largest_niche?.available(self.1)) } pub fn field_offset(&self, field: Field) -> Option<u64> { @@ -6802,7 +6850,7 @@ impl Layout { let tag_size = if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants { match tag_encoding { - TagEncoding::Direct => tag.size(&*self.1).bytes_usize(), + TagEncoding::Direct => tag.size(self.1).bytes_usize(), TagEncoding::Niche { .. } => 0, } } else { @@ -6934,6 +6982,33 @@ pub trait HasVisibility { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum PredicatePolarity { + /// `T: Trait` + Positive, + /// `T: !Trait` + Negative, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitPredicate<'db> { + inner: hir_ty::next_solver::TraitPredicate<'db>, + env: ParamEnvAndCrate<'db>, +} + +impl<'db> TraitPredicate<'db> { + pub fn polarity(&self) -> PredicatePolarity { + match self.inner.polarity { + rustc_type_ir::PredicatePolarity::Positive => PredicatePolarity::Positive, + rustc_type_ir::PredicatePolarity::Negative => PredicatePolarity::Negative, + } + } + + pub fn trait_ref(&self) -> TraitRef<'db> { + TraitRef { env: self.env, trait_ref: self.inner.trait_ref } + } +} + /// Trait for obtaining the defining crate of an item. pub trait HasCrate { fn krate(&self, db: &dyn HirDatabase) -> Crate; @@ -7041,6 +7116,12 @@ impl HasCrate for Module { } } +impl HasCrate for AnonConst { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + hir_def::HasModule::krate(&self.id.loc(db).owner, db).into() + } +} + pub trait HasContainer { fn container(&self, db: &dyn HirDatabase) -> ItemContainer; } @@ -7217,17 +7298,14 @@ pub enum DocLinkDef { fn push_ty_diagnostics<'db>( db: &'db dyn HirDatabase, acc: &mut Vec<AnyDiagnostic<'db>>, - diagnostics: Option<ThinArc<(), TyLoweringDiagnostic>>, + diagnostics: &[TyLoweringDiagnostic], source_map: &ExpressionStoreSourceMap, ) { - if let Some(diagnostics) = diagnostics { - acc.extend( - diagnostics - .slice - .iter() - .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)), - ); - } + acc.extend( + diagnostics + .iter() + .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)), + ); } pub trait MethodCandidateCallback { @@ -7342,10 +7420,8 @@ fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_))) .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id }) .any(|param| { - let Some(param) = hir_ty::param_idx(db, param) else { - return false; - }; - defaults.get(param).is_none() + let param = hir_ty::type_or_const_param_idx(db, param); + defaults.get(param as usize).is_none() }) } @@ -7379,5 +7455,16 @@ fn empty_param_env<'db>(krate: base_db::Crate) -> ParamEnvAndCrate<'db> { ParamEnvAndCrate { param_env: ParamEnv::empty(), krate } } +// FIXME: We probably don't want to expose this. +pub trait MacroCallIdExt { + fn loc(self, db: &dyn HirDatabase) -> hir_expand::MacroCallLoc; +} +impl MacroCallIdExt for span::MacroCallId { + #[inline] + fn loc(self, db: &dyn HirDatabase) -> hir_expand::MacroCallLoc { + hir_expand::MacroCallId::from(self).loc(db) + } +} + pub use hir_ty::next_solver; pub use hir_ty::setup_tracing; |