Unnamed repository; edit this file 'description' to name the repository.
87 files changed, 920 insertions, 770 deletions
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml index f975bbaa51..9cc18fc69e 100644 --- a/.github/workflows/rustdoc.yaml +++ b/.github/workflows/rustdoc.yaml @@ -8,6 +8,7 @@ env: CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 RUSTFLAGS: "-D warnings -W unreachable-pub" + RUSTDOCFLAGS: "-D warnings" RUSTUP_MAX_RETRIES: 10 jobs: diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index 5695ab7ed0..66f7e25ffa 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -43,7 +43,7 @@ pub use self::lower::{ hir_assoc_type_binding_to_ast, hir_generic_arg_to_ast, hir_segment_to_ast_segment, }; -/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons. +/// A wrapper around [`span::SyntaxContext`] that is intended only for comparisons. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct HygieneId(span::SyntaxContext); diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs index 60cd66bf6b..1a2d5ebba4 100644 --- a/crates/hir-def/src/hir/generics.rs +++ b/crates/hir-def/src/hir/generics.rs @@ -20,7 +20,7 @@ pub type LocalLifetimeParamId = Idx<LifetimeParamData>; /// Data about a generic type parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeParamData { - /// [`None`] only if the type ref is an [`TypeRef::ImplTrait`]. FIXME: Might be better to just + /// [`None`] only if the type ref is an [`crate::type_ref::TypeRef::ImplTrait`]. FIXME: Might be better to just /// make it always be a value, giving impl trait a special name. pub name: Option<Name>, pub default: Option<TypeRefId>, diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 3f2cf09e21..04acb8b712 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -238,7 +238,7 @@ language_item_table! { LangItems => Clone, sym::clone, clone_trait, TraitId, GenericRequirement::None; Sync, sym::sync, sync_trait, TraitId, GenericRequirement::Exact(0); DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, TraitId, GenericRequirement::None; - /// The associated item of the [`DiscriminantKind`] trait. + /// The associated item of the `DiscriminantKind` trait. Discriminant, sym::discriminant_type, discriminant_type, TypeAliasId, GenericRequirement::None; PointeeTrait, sym::pointee_trait, pointee_trait, TraitId, GenericRequirement::None; diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 5f45e188e0..aefbf6306e 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -739,7 +739,7 @@ impl ModuleData { self.origin.definition_source(db) } - /// Same as [`definition_source`] but only returns the file id to prevent parsing the ASt. + /// Same as [`ModuleData::definition_source`] but only returns the file id to prevent parsing the ASt. pub fn definition_source_file_id(&self) -> HirFileId { match self.origin { ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index fe557d6802..fce92c8a3e 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -295,7 +295,7 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> { /// Falls back to the macro call range if the node cannot be mapped up fully. /// /// For attributes and derives, this will point back to the attribute only. - /// For the entire item use [`InFile::original_file_range_full`]. + /// For the entire item use `InFile::original_file_range_full`. pub fn original_file_range_rooted(self, db: &dyn db::ExpandDatabase) -> FileRange { self.borrow().map(SyntaxNode::text_range).original_node_file_range_rooted(db) } diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index 28800c6fab..bd6f7e4f2b 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -8,9 +8,9 @@ //! //! # The Expansion Order Hierarchy //! -//! `ExpnData` in rustc, rust-analyzer's version is [`MacroCallLoc`]. Traversing the hierarchy -//! upwards can be achieved by walking up [`MacroCallLoc::kind`]'s contained file id, as -//! [`MacroFile`]s are interned [`MacroCallLoc`]s. +//! `ExpnData` in rustc, rust-analyzer's version is `MacroCallLoc`. Traversing the hierarchy +//! upwards can be achieved by walking up `MacroCallLoc::kind`'s contained file id, as +//! `MacroFile`s are interned `MacroCallLoc`s. //! //! # The Macro Definition Hierarchy //! @@ -18,7 +18,7 @@ //! //! # The Call-site Hierarchy //! -//! `ExpnData::call_site` in rustc, [`MacroCallLoc::call_site`] in rust-analyzer. +//! `ExpnData::call_site` in rustc, `MacroCallLoc::call_site` in rust-analyzer. // FIXME: Move this into the span crate? Not quite possible today as that depends on `MacroCallLoc` // which contains a bunch of unrelated things diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 157a5310bd..c92e41f507 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -4,6 +4,8 @@ //! tree originates not from the text of some `FileId`, but from some macro //! expansion. #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +// It's useful to refer to code that is private in doc comments. +#![allow(rustdoc::private_intra_doc_links)] pub use intern; @@ -860,7 +862,7 @@ impl ExpansionInfo { } /// Maps the passed in file range down into a macro expansion if it is the input to a macro call. - /// Unlike [`map_range_down_exact`], this will consider spans that contain the given span. + /// Unlike [`ExpansionInfo::map_range_down_exact`], this will consider spans that contain the given span. /// /// Note this does a linear search through the entire backing vector of the spanmap. pub fn map_range_down( diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs index 0a36c0e726..abab3bfb25 100644 --- a/crates/hir-ty/src/autoderef.rs +++ b/crates/hir-ty/src/autoderef.rs @@ -8,10 +8,9 @@ use std::fmt; use hir_def::{TraitId, TypeAliasId}; use rustc_type_ir::inherent::{IntoKind, Ty as _}; use tracing::debug; -use triomphe::Arc; use crate::{ - TraitEnvironment, + ParamEnvAndCrate, db::HirDatabase, infer::InferenceContext, next_solver::{ @@ -35,13 +34,13 @@ const AUTODEREF_RECURSION_LIMIT: usize = 20; /// detects a cycle in the deref chain. pub fn autoderef<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ty: Canonical<'db, Ty<'db>>, ) -> impl Iterator<Item = Ty<'db>> + use<'db> { let interner = DbInterner::new_with(db, env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let (ty, _) = infcx.instantiate_canonical(&ty); - let autoderef = Autoderef::new(&infcx, &env, ty); + let autoderef = Autoderef::new(&infcx, env.param_env, ty); let mut v = Vec::new(); for (ty, _steps) in autoderef { // `ty` may contain unresolved inference variables. Since there's no chance they would be @@ -111,12 +110,12 @@ struct AutoderefTraits { // borrows it. pub(crate) trait AutoderefCtx<'db> { fn infcx(&self) -> &InferCtxt<'db>; - fn env(&self) -> &TraitEnvironment<'db>; + fn param_env(&self) -> ParamEnv<'db>; } pub(crate) struct DefaultAutoderefCtx<'a, 'db> { infcx: &'a InferCtxt<'db>, - env: &'a TraitEnvironment<'db>, + param_env: ParamEnv<'db>, } impl<'db> AutoderefCtx<'db> for DefaultAutoderefCtx<'_, 'db> { #[inline] @@ -124,8 +123,8 @@ impl<'db> AutoderefCtx<'db> for DefaultAutoderefCtx<'_, 'db> { self.infcx } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - self.env + fn param_env(&self) -> ParamEnv<'db> { + self.param_env } } @@ -136,8 +135,8 @@ impl<'db> AutoderefCtx<'db> for InferenceContextAutoderefCtx<'_, '_, 'db> { &self.0.table.infer_ctxt } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - &self.0.table.trait_env + fn param_env(&self) -> ParamEnv<'db> { + self.0.table.param_env } } @@ -201,7 +200,7 @@ where // autoderef expect this type to have been structurally normalized. if let TyKind::Alias(..) = ty.kind() { let (normalized_ty, obligations) = - structurally_normalize_ty(self.infcx(), self.env().env, ty)?; + structurally_normalize_ty(self.infcx(), self.param_env(), ty)?; self.state.obligations.extend(obligations); (AutoderefKind::Builtin, normalized_ty) } else { @@ -231,10 +230,10 @@ impl<'a, 'db> Autoderef<'a, 'db> { #[inline] pub(crate) fn new_with_tracking( infcx: &'a InferCtxt<'db>, - env: &'a TraitEnvironment<'db>, + param_env: ParamEnv<'db>, base_ty: Ty<'db>, ) -> Self { - Self::new_impl(DefaultAutoderefCtx { infcx, env }, base_ty) + Self::new_impl(DefaultAutoderefCtx { infcx, param_env }, base_ty) } } @@ -257,10 +256,10 @@ impl<'a, 'db> Autoderef<'a, 'db, usize> { #[inline] pub(crate) fn new( infcx: &'a InferCtxt<'db>, - env: &'a TraitEnvironment<'db>, + param_env: ParamEnv<'db>, base_ty: Ty<'db>, ) -> Self { - Self::new_impl(DefaultAutoderefCtx { infcx, env }, base_ty) + Self::new_impl(DefaultAutoderefCtx { infcx, param_env }, base_ty) } } @@ -292,8 +291,8 @@ where } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - self.ctx.env() + fn param_env(&self) -> ParamEnv<'db> { + self.ctx.param_env() } #[inline] @@ -339,7 +338,7 @@ where let trait_ref = TraitRef::new(interner, trait_.into(), [ty]); let obligation = - Obligation::new(interner, ObligationCause::new(), self.env().env, trait_ref); + Obligation::new(interner, ObligationCause::new(), self.param_env(), trait_ref); // We detect whether the self type implements `Deref` before trying to // structurally normalize. We use `predicate_may_hold_opaque_types_jank` // to support not-yet-defined opaque types. It will succeed for `impl Deref` @@ -351,7 +350,7 @@ where let (normalized_ty, obligations) = structurally_normalize_ty( self.infcx(), - self.env().env, + self.param_env(), Ty::new_projection(interner, trait_target.into(), [ty]), )?; debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 65250f94c2..012632aa55 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -5,7 +5,7 @@ mod tests; use base_db::Crate; use hir_def::{ - ConstId, EnumVariantId, GeneralConstId, StaticId, + ConstId, EnumVariantId, GeneralConstId, HasModule, StaticId, attrs::AttrFlags, expr_store::Body, hir::{Expr, ExprId}, @@ -16,14 +16,14 @@ use rustc_type_ir::inherent::IntoKind; use triomphe::Arc; use crate::{ - LifetimeElisionKind, MemoryMap, TraitEnvironment, TyLoweringContext, + LifetimeElisionKind, MemoryMap, ParamEnvAndCrate, TyLoweringContext, db::HirDatabase, display::DisplayTarget, infer::InferenceContext, mir::{MirEvalError, MirLowerError}, next_solver::{ - Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Ty, - ValueConst, + Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, + ParamEnv, Ty, ValueConst, }, }; @@ -85,7 +85,7 @@ pub fn intern_const_ref<'a>( krate: Crate, ) -> Const<'a> { let interner = DbInterner::new_no_crate(db); - let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate)); + let layout = db.layout_of_ty(ty, ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }); let kind = match value { LiteralConstRef::Int(i) => { // FIXME: We should handle failure of layout better. @@ -207,7 +207,7 @@ pub(crate) fn const_eval_discriminant_variant<'db>( let mir_body = db.monomorphized_mir_body( def, GenericArgs::new_from_iter(interner, []), - db.trait_environment_for_body(def), + ParamEnvAndCrate { param_env: db.trait_environment_for_body(def), krate: def.krate(db) }, )?; let c = interpret_mir(db, mir_body, false, None)?.0?; let c = if is_signed { @@ -259,7 +259,7 @@ pub(crate) fn const_eval_cycle_result<'db>( _: &'db dyn HirDatabase, _: ConstId, _: GenericArgs<'db>, - _: Option<Arc<TraitEnvironment<'db>>>, + _: Option<ParamEnvAndCrate<'db>>, ) -> Result<Const<'db>, ConstEvalError<'db>> { Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) } @@ -282,9 +282,13 @@ pub(crate) fn const_eval_query<'db>( db: &'db dyn HirDatabase, def: ConstId, subst: GenericArgs<'db>, - trait_env: Option<Arc<TraitEnvironment<'db>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<Const<'db>, ConstEvalError<'db>> { - let body = db.monomorphized_mir_body(def.into(), subst, db.trait_environment(def.into()))?; + let body = db.monomorphized_mir_body( + def.into(), + subst, + ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) }, + )?; let c = interpret_mir(db, body, false, trait_env)?.0?; Ok(c) } @@ -297,7 +301,10 @@ pub(crate) fn const_eval_static_query<'db>( let body = db.monomorphized_mir_body( def.into(), GenericArgs::new_from_iter(interner, []), - db.trait_environment_for_body(def.into()), + ParamEnvAndCrate { + param_env: db.trait_environment_for_body(def.into()), + krate: def.krate(db), + }, )?; let c = interpret_mir(db, body, false, None)?.0?; Ok(c) diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index df058711a6..f9523e7168 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -12,13 +12,16 @@ use salsa::plumbing::AsId; use triomphe::Arc; use crate::{ - ImplTraitId, TraitEnvironment, TyDefId, ValueTyDefId, + ImplTraitId, TyDefId, ValueTyDefId, consteval::ConstEvalError, dyn_compatibility::DynCompatibilityViolation, layout::{Layout, LayoutError}, lower::{Diagnostics, GenericDefaults}, mir::{BorrowckResult, MirBody, MirLowerError}, - next_solver::{Const, EarlyBinder, GenericArgs, PolyFnSig, TraitRef, Ty, VariancesOf}, + next_solver::{ + Const, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, TraitRef, Ty, VariancesOf, + }, + traits::ParamEnvAndCrate, }; #[query_group::query_group] @@ -46,7 +49,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { &'db self, def: DefWithBodyId, subst: GenericArgs<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] @@ -54,7 +57,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { &'db self, def: InternedClosureId, subst: GenericArgs<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; #[salsa::invoke(crate::mir::borrowck_query)] @@ -70,7 +73,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { &'db self, def: ConstId, subst: GenericArgs<'db>, - trait_env: Option<Arc<TraitEnvironment<'db>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<Const<'db>, ConstEvalError<'db>>; #[salsa::invoke(crate::consteval::const_eval_static_query)] @@ -88,7 +91,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::transparent] fn lookup_impl_method<'db>( &'db self, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, func: FunctionId, fn_subst: GenericArgs<'db>, ) -> (FunctionId, GenericArgs<'db>); @@ -101,7 +104,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { &'db self, def: AdtId, args: GenericArgs<'db>, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError>; #[salsa::invoke(crate::layout::layout_of_ty_query)] @@ -109,7 +112,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn layout_of_ty<'db>( &'db self, ty: Ty<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError>; #[salsa::invoke(crate::layout::target_data_layout_query)] @@ -186,11 +189,10 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::transparent] - fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId) - -> Arc<TraitEnvironment<'db>>; + fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId) -> ParamEnv<'db>; #[salsa::invoke(crate::lower::trait_environment_query)] - fn trait_environment<'db>(&'db self, def: GenericDefId) -> Arc<TraitEnvironment<'db>>; + fn trait_environment<'db>(&'db self, def: GenericDefId) -> ParamEnv<'db>; #[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)] #[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)] diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index ffbcea4d25..0de7fab8d1 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -25,7 +25,7 @@ use triomphe::Arc; use typed_arena::Arena; use crate::{ - Adjust, InferenceResult, TraitEnvironment, + Adjust, InferenceResult, db::HirDatabase, diagnostics::match_check::{ self, @@ -33,7 +33,7 @@ use crate::{ }, display::{DisplayTarget, HirDisplay}, next_solver::{ - DbInterner, Ty, TyKind, TypingMode, + DbInterner, ParamEnv, Ty, TyKind, TypingMode, infer::{DbInternerInferExt, InferCtxt}, }, }; @@ -79,7 +79,7 @@ impl BodyValidationDiagnostic { let infer = InferenceResult::for_body(db, owner); let body = db.body(owner); let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, env.krate); + let interner = DbInterner::new_with(db, owner.krate(db)); let infcx = interner.infer_ctxt().build(TypingMode::typeck_for_body(interner, owner.into())); let mut validator = ExprValidator { @@ -100,7 +100,7 @@ struct ExprValidator<'db> { owner: DefWithBodyId, body: Arc<Body>, infer: &'db InferenceResult<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, diagnostics: Vec<BodyValidationDiagnostic>, validate_lints: bool, infcx: InferCtxt<'db>, @@ -210,7 +210,7 @@ impl<'db> ExprValidator<'db> { return; } - let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env.clone()); + let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env); let pattern_arena = Arena::new(); let mut m_arms = Vec::with_capacity(arms.len()); @@ -332,7 +332,7 @@ impl<'db> ExprValidator<'db> { return; }; let pattern_arena = Arena::new(); - let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env.clone()); + let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env); for stmt in &**statements { let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else { continue; diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index c70c6b6119..e7ee7c62b9 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -14,14 +14,12 @@ use rustc_pattern_analysis::{ use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; use smallvec::{SmallVec, smallvec}; use stdx::never; -use triomphe::Arc; use crate::{ - TraitEnvironment, db::HirDatabase, inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from}, next_solver::{ - Ty, TyKind, + ParamEnv, Ty, TyKind, infer::{InferCtxt, traits::ObligationCause}, }, }; @@ -76,16 +74,12 @@ pub(crate) struct MatchCheckCtx<'a, 'db> { module: ModuleId, pub(crate) db: &'db dyn HirDatabase, exhaustive_patterns: bool, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, infcx: &'a InferCtxt<'db>, } impl<'a, 'db> MatchCheckCtx<'a, 'db> { - pub(crate) fn new( - module: ModuleId, - infcx: &'a InferCtxt<'db>, - env: Arc<TraitEnvironment<'db>>, - ) -> Self { + pub(crate) fn new(module: ModuleId, infcx: &'a InferCtxt<'db>, env: ParamEnv<'db>) -> Self { let db = infcx.interner.db; let def_map = module.crate_def_map(db); let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns); @@ -114,7 +108,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> { } fn is_uninhabited(&self, ty: Ty<'db>) -> bool { - is_ty_uninhabited_from(self.infcx, ty, self.module, self.env.clone()) + is_ty_uninhabited_from(self.infcx, ty, self.module, self.env) } /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`. @@ -159,7 +153,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> { let ty = field_tys[fid].instantiate(self.infcx.interner, substs); let ty = self .infcx - .at(&ObligationCause::dummy(), self.env.env) + .at(&ObligationCause::dummy(), self.env) .deeply_normalize(ty) .unwrap_or(ty); (fid, ty) @@ -446,11 +440,7 @@ impl<'a, 'db> PatCx for MatchCheckCtx<'a, 'db> { let mut variants = IndexVec::with_capacity(enum_data.variants.len()); for &(variant, _, _) in enum_data.variants.iter() { let is_uninhabited = is_enum_variant_uninhabited_from( - cx.infcx, - variant, - subst, - cx.module, - self.env.clone(), + cx.infcx, variant, subst, cx.module, self.env, ); let visibility = if is_uninhabited { VariantVisibility::Empty diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index c76b8dc5f0..16c2922731 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -44,10 +44,9 @@ use rustc_type_ir::{ use smallvec::SmallVec; use span::Edition; use stdx::never; -use triomphe::Arc; use crate::{ - CallableDefId, FnAbi, ImplTraitId, InferenceResult, MemoryMap, TraitEnvironment, consteval, + CallableDefId, FnAbi, ImplTraitId, InferenceResult, MemoryMap, ParamEnvAndCrate, consteval, db::{HirDatabase, InternedClosure, InternedCoroutine}, generics::generics, layout::Layout, @@ -55,8 +54,8 @@ use crate::{ mir::pad16, next_solver::{ AliasTy, Clause, ClauseKind, Const, ConstKind, DbInterner, EarlyBinder, - ExistentialPredicate, FnSig, GenericArg, GenericArgs, PolyFnSig, Region, SolverDefId, Term, - TraitRef, Ty, TyKind, TypingMode, + ExistentialPredicate, FnSig, GenericArg, GenericArgs, ParamEnv, PolyFnSig, Region, + SolverDefId, Term, TraitRef, Ty, TyKind, TypingMode, abi::Safety, infer::{DbInternerInferExt, traits::ObligationCause}, }, @@ -64,6 +63,8 @@ use crate::{ utils::{detect_variant_from_bytes, fn_traits}, }; +pub type Result<T = (), E = HirDisplayError> = std::result::Result<T, E>; + pub trait HirWrite: fmt::Write { fn start_location_link(&mut self, _location: ModuleDefId) {} fn end_location_link(&mut self) {} @@ -191,7 +192,7 @@ impl<'db> HirFormatter<'_, 'db> { } pub trait HirDisplay<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError>; + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result; /// Returns a `Display`able type that is human-readable. fn into_displayable<'a>( @@ -400,7 +401,7 @@ impl<'db> HirFormatter<'_, 'db> { &mut self, iter: impl IntoIterator<Item = T>, sep: &str, - ) -> Result<(), HirDisplayError> { + ) -> Result { let mut first = true; for e in iter { if !first { @@ -419,7 +420,7 @@ impl<'db> HirFormatter<'_, 'db> { } /// This allows using the `write!` macro directly with a `HirFormatter`. - pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> { + pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result { // We write to a buffer first to track output size self.buf.clear(); fmt::write(&mut self.buf, args)?; @@ -429,12 +430,12 @@ impl<'db> HirFormatter<'_, 'db> { self.fmt.write_str(&self.buf).map_err(HirDisplayError::from) } - pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> { + pub fn write_str(&mut self, s: &str) -> Result { self.fmt.write_str(s)?; Ok(()) } - pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> { + pub fn write_char(&mut self, c: char) -> Result { self.fmt.write_char(c)?; Ok(()) } @@ -542,7 +543,7 @@ pub enum ClosureStyle { } impl<'db, T: HirDisplay<'db>> HirDisplayWrapper<'_, 'db, T> { - pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> { + pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result { let krate = self.display_target.krate; let interner = DbInterner::new_with(self.db, krate); self.t.hir_fmt(&mut HirFormatter { @@ -595,21 +596,18 @@ where const TYPE_HINT_TRUNCATION: &str = "…"; impl<'db, T: HirDisplay<'db>> HirDisplay<'db> for &T { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { HirDisplay::hir_fmt(*self, f) } } impl<'db, T: HirDisplay<'db> + Internable> HirDisplay<'db> for Interned<T> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { HirDisplay::hir_fmt(self.as_ref(), f) } } -fn write_projection<'db>( - f: &mut HirFormatter<'_, 'db>, - alias: &AliasTy<'db>, -) -> Result<(), HirDisplayError> { +fn write_projection<'db>(f: &mut HirFormatter<'_, 'db>, alias: &AliasTy<'db>) -> Result { if f.should_truncate() { return write!(f, "{TYPE_HINT_TRUNCATION}"); } @@ -666,7 +664,7 @@ fn write_projection<'db>( } impl<'db> HirDisplay<'db> for GenericArg<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self { GenericArg::Ty(ty) => ty.hir_fmt(f), GenericArg::Lifetime(lt) => lt.hir_fmt(f), @@ -676,7 +674,7 @@ impl<'db> HirDisplay<'db> for GenericArg<'db> { } impl<'db> HirDisplay<'db> for Const<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.kind() { ConstKind::Placeholder(_) => write!(f, "<placeholder>"), ConstKind::Bound(BoundVarIndexKind::Bound(db), bound_const) => { @@ -715,11 +713,11 @@ fn render_const_scalar<'db>( b: &[u8], memory_map: &MemoryMap<'db>, ty: Ty<'db>, -) -> Result<(), HirDisplayError> { - let trait_env = TraitEnvironment::empty(f.krate()); +) -> Result { + let param_env = ParamEnv::empty(); let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis); - let ty = infcx.at(&ObligationCause::new(), trait_env.env).deeply_normalize(ty).unwrap_or(ty); - render_const_scalar_inner(f, b, memory_map, ty, trait_env) + let ty = infcx.at(&ObligationCause::new(), param_env).deeply_normalize(ty).unwrap_or(ty); + render_const_scalar_inner(f, b, memory_map, ty, param_env) } fn render_const_scalar_inner<'db>( @@ -727,9 +725,10 @@ fn render_const_scalar_inner<'db>( b: &[u8], memory_map: &MemoryMap<'db>, ty: Ty<'db>, - trait_env: Arc<TraitEnvironment<'db>>, -) -> Result<(), HirDisplayError> { + param_env: ParamEnv<'db>, +) -> Result { use TyKind; + let param_env = ParamEnvAndCrate { param_env, krate: f.krate() }; match ty.kind() { TyKind::Bool => write!(f, "{}", b[0] != 0), TyKind::Char => { @@ -792,7 +791,7 @@ fn render_const_scalar_inner<'db>( TyKind::Slice(ty) => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); - let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else { + let Ok(layout) = f.db.layout_of_ty(ty, param_env) else { return f.write_str("<layout-error>"); }; let size_one = layout.size.bytes_usize(); @@ -826,7 +825,7 @@ fn render_const_scalar_inner<'db>( let Ok(t) = memory_map.vtable_ty(ty_id) else { return f.write_str("<ty-missing-in-vtable-map>"); }; - let Ok(layout) = f.db.layout_of_ty(t, trait_env) else { + let Ok(layout) = f.db.layout_of_ty(t, param_env) else { return f.write_str("<layout-error>"); }; let size = layout.size.bytes_usize(); @@ -856,7 +855,7 @@ fn render_const_scalar_inner<'db>( return f.write_str("<layout-error>"); } }); - let Ok(layout) = f.db.layout_of_ty(t, trait_env) else { + let Ok(layout) = f.db.layout_of_ty(t, param_env) else { return f.write_str("<layout-error>"); }; let size = layout.size.bytes_usize(); @@ -868,7 +867,7 @@ fn render_const_scalar_inner<'db>( } }, TyKind::Tuple(tys) => { - let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else { + let Ok(layout) = f.db.layout_of_ty(ty, param_env) else { return f.write_str("<layout-error>"); }; f.write_str("(")?; @@ -880,7 +879,7 @@ fn render_const_scalar_inner<'db>( f.write_str(", ")?; } let offset = layout.fields.offset(id).bytes_usize(); - let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else { + let Ok(layout) = f.db.layout_of_ty(ty, param_env) else { f.write_str("<layout-error>")?; continue; }; @@ -891,7 +890,7 @@ fn render_const_scalar_inner<'db>( } TyKind::Adt(def, args) => { let def = def.def_id().0; - let Ok(layout) = f.db.layout_of_adt(def, args, trait_env.clone()) else { + let Ok(layout) = f.db.layout_of_adt(def, args, param_env) else { return f.write_str("<layout-error>"); }; match def { @@ -914,7 +913,7 @@ fn render_const_scalar_inner<'db>( write!(f, "{}", f.db.union_signature(u).name.display(f.db, f.edition())) } hir_def::AdtId::EnumId(e) => { - let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else { + let Ok(target_data_layout) = f.db.target_data_layout(f.krate()) else { return f.write_str("<target-layout-not-available>"); }; let Some((var_id, var_layout)) = @@ -954,7 +953,7 @@ fn render_const_scalar_inner<'db>( let Some(len) = consteval::try_const_usize(f.db, len) else { return f.write_str("<unknown-array-len>"); }; - let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else { + let Ok(layout) = f.db.layout_of_ty(ty, param_env) else { return f.write_str("<layout-error>"); }; let size_one = layout.size.bytes_usize(); @@ -995,18 +994,19 @@ fn render_variant_after_name<'db>( data: &VariantFields, f: &mut HirFormatter<'_, 'db>, field_types: &ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>, - trait_env: Arc<TraitEnvironment<'db>>, + param_env: ParamEnv<'db>, layout: &Layout, args: GenericArgs<'db>, b: &[u8], memory_map: &MemoryMap<'db>, -) -> Result<(), HirDisplayError> { +) -> Result { + let param_env = ParamEnvAndCrate { param_env, krate: f.krate() }; match data.shape { FieldsShape::Record | FieldsShape::Tuple => { let render_field = |f: &mut HirFormatter<'_, 'db>, id: LocalFieldId| { let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize(); let ty = field_types[id].instantiate(f.interner, args); - let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else { + let Ok(layout) = f.db.layout_of_ty(ty, param_env) else { return f.write_str("<layout-error>"); }; let size = layout.size.bytes_usize(); @@ -1043,10 +1043,7 @@ fn render_variant_after_name<'db>( } impl<'db> HirDisplay<'db> for Ty<'db> { - fn hir_fmt( - &self, - f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_, 'db>, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_, 'db>) -> Result { let interner = f.interner; if f.should_truncate() { return write!(f, "{TYPE_HINT_TRUNCATION}"); @@ -1649,7 +1646,7 @@ fn hir_fmt_generics<'db>( parameters: &[GenericArg<'db>], generic_def: Option<hir_def::GenericDefId>, self_: Option<Ty<'db>>, -) -> Result<(), HirDisplayError> { +) -> Result { if parameters.is_empty() { return Ok(()); } @@ -1699,7 +1696,7 @@ fn hir_fmt_generic_args<'db>( parameters: &[GenericArg<'db>], generic_def: Option<hir_def::GenericDefId>, self_: Option<Ty<'db>>, -) -> Result<(), HirDisplayError> { +) -> Result { if parameters.is_empty() { return Ok(()); } @@ -1719,7 +1716,7 @@ fn hir_fmt_generic_arguments<'db>( f: &mut HirFormatter<'_, 'db>, parameters: &[GenericArg<'db>], self_: Option<Ty<'db>>, -) -> Result<(), HirDisplayError> { +) -> Result { let mut first = true; let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some()); @@ -1743,7 +1740,7 @@ fn hir_fmt_tys<'db>( f: &mut HirFormatter<'_, 'db>, tys: &[Ty<'db>], self_: Option<Ty<'db>>, -) -> Result<(), HirDisplayError> { +) -> Result { let mut first = true; for ty in tys { @@ -1759,7 +1756,7 @@ fn hir_fmt_tys<'db>( } impl<'db> HirDisplay<'db> for PolyFnSig<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let FnSig { inputs_and_output, c_variadic, safety, abi: _ } = self.skip_binder(); if let Safety::Unsafe = safety { write!(f, "unsafe ")?; @@ -1790,7 +1787,7 @@ impl<'db> HirDisplay<'db> for PolyFnSig<'db> { } impl<'db> HirDisplay<'db> for Term<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self { Term::Ty(it) => it.hir_fmt(f), Term::Const(it) => it.hir_fmt(f), @@ -1822,7 +1819,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix<'db>( this: Either<Ty<'db>, Region<'db>>, predicates: &[Clause<'db>], default_sized: SizedByDefault, -) -> Result<(), HirDisplayError> { +) -> Result { write!(f, "{prefix}")?; if !predicates.is_empty() || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. }) @@ -1839,7 +1836,7 @@ fn write_bounds_like_dyn_trait<'db>( this: Either<Ty<'db>, Region<'db>>, predicates: &[Clause<'db>], default_sized: SizedByDefault, -) -> Result<(), HirDisplayError> { +) -> Result { // Note: This code is written to produce nice results (i.e. // corresponding to surface Rust) for types that can occur in // actual Rust. It will have weird results if the predicates @@ -1983,7 +1980,7 @@ fn write_bounds_like_dyn_trait<'db>( } impl<'db> HirDisplay<'db> for TraitRef<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let trait_ = self.def_id.0; f.start_location_link(trait_.into()); write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?; @@ -1994,7 +1991,7 @@ impl<'db> HirDisplay<'db> for TraitRef<'db> { } impl<'db> HirDisplay<'db> for Region<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.kind() { RegionKind::ReEarlyParam(param) => { let generics = generics(f.db, param.id.parent); @@ -2028,7 +2025,7 @@ pub fn write_visibility<'db>( module_id: ModuleId, vis: Visibility, f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +) -> Result { match vis { Visibility::Public => write!(f, "pub "), Visibility::PubCrate(_) => write!(f, "pub(crate) "), @@ -2051,21 +2048,13 @@ pub fn write_visibility<'db>( } pub trait HirDisplayWithExpressionStore<'db> { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError>; + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result; } impl<'db, T: ?Sized + HirDisplayWithExpressionStore<'db>> HirDisplayWithExpressionStore<'db> for &'_ T { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { T::hir_fmt(&**self, f, store) } } @@ -2086,16 +2075,12 @@ impl<'a, T> ExpressionStoreAdapter<'a, T> { } impl<'db, T: HirDisplayWithExpressionStore<'db>> HirDisplay<'db> for ExpressionStoreAdapter<'_, T> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { T::hir_fmt(&self.0, f, self.1) } } impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { match &store[*self] { LifetimeRef::Named(name) => write!(f, "{}", name.display(f.db, f.edition())), LifetimeRef::Static => write!(f, "'static"), @@ -2114,11 +2099,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId { } impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { match &store[*self] { TypeRef::Never => write!(f, "!")?, TypeRef::TypeParam(param) => { @@ -2243,11 +2224,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId { } impl<'db> HirDisplayWithExpressionStore<'db> for ConstRef { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - _store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, _store: &ExpressionStore) -> Result { // FIXME write!(f, "{{const}}")?; @@ -2256,11 +2233,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for ConstRef { } impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { match self { &TypeBound::Path(path, modifier) => { match modifier { @@ -2300,11 +2273,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound { } impl<'db> HirDisplayWithExpressionStore<'db> for Path { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { match (self.type_anchor(), self.kind()) { (Some(anchor), _) => { write!(f, "<")?; @@ -2452,11 +2421,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for Path { } impl<'db> HirDisplayWithExpressionStore<'db> for hir_def::expr_store::path::GenericArg { - fn hir_fmt( - &self, - f: &mut HirFormatter<'_, 'db>, - store: &ExpressionStore, - ) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result { match self { hir_def::expr_store::path::GenericArg::Type(ty) => ty.hir_fmt(f, store), hir_def::expr_store::path::GenericArg::Const(_c) => { diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs index d76de4b8ca..def3c44927 100644 --- a/crates/hir-ty/src/drop.rs +++ b/crates/hir-ty/src/drop.rs @@ -4,13 +4,12 @@ use hir_def::{AdtId, signatures::StructFlags}; use rustc_hash::FxHashSet; use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; use stdx::never; -use triomphe::Arc; use crate::{ - InferenceResult, TraitEnvironment, consteval, + InferenceResult, consteval, method_resolution::TraitImpls, next_solver::{ - DbInterner, SimplifiedType, Ty, TyKind, + DbInterner, ParamEnv, SimplifiedType, Ty, TyKind, infer::{InferCtxt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, }, @@ -47,22 +46,18 @@ pub enum DropGlue { HasDropGlue, } -pub fn has_drop_glue<'db>( - infcx: &InferCtxt<'db>, - ty: Ty<'db>, - env: Arc<TraitEnvironment<'db>>, -) -> DropGlue { +pub fn has_drop_glue<'db>(infcx: &InferCtxt<'db>, ty: Ty<'db>, env: ParamEnv<'db>) -> DropGlue { has_drop_glue_impl(infcx, ty, env, &mut FxHashSet::default()) } fn has_drop_glue_impl<'db>( infcx: &InferCtxt<'db>, ty: Ty<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, visited: &mut FxHashSet<Ty<'db>>, ) -> DropGlue { let mut ocx = ObligationCtxt::new(infcx); - let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); + let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, ty).unwrap_or(ty); if !visited.insert(ty) { // Recursive type. @@ -91,7 +86,7 @@ fn has_drop_glue_impl<'db>( has_drop_glue_impl( infcx, field_ty.instantiate(infcx.interner, subst), - env.clone(), + env, visited, ) }) @@ -111,7 +106,7 @@ fn has_drop_glue_impl<'db>( has_drop_glue_impl( infcx, field_ty.instantiate(infcx.interner, subst), - env.clone(), + env, visited, ) }) @@ -124,7 +119,7 @@ fn has_drop_glue_impl<'db>( } TyKind::Tuple(tys) => tys .iter() - .map(|ty| has_drop_glue_impl(infcx, ty, env.clone(), visited)) + .map(|ty| has_drop_glue_impl(infcx, ty, env, visited)) .max() .unwrap_or(DropGlue::None), TyKind::Array(ty, len) => { @@ -142,9 +137,7 @@ fn has_drop_glue_impl<'db>( let env = db.trait_environment_for_body(owner); captures .iter() - .map(|capture| { - has_drop_glue_impl(infcx, capture.ty(db, subst), env.clone(), visited) - }) + .map(|capture| has_drop_glue_impl(infcx, capture.ty(db, subst), env, visited)) .max() .unwrap_or(DropGlue::None) } @@ -169,14 +162,14 @@ fn has_drop_glue_impl<'db>( | TyKind::Placeholder(..) => DropGlue::None, TyKind::Dynamic(..) => DropGlue::HasDropGlue, TyKind::Alias(..) => { - if infcx.type_is_copy_modulo_regions(env.env, ty) { + if infcx.type_is_copy_modulo_regions(env, ty) { DropGlue::None } else { DropGlue::HasDropGlue } } TyKind::Param(_) => { - if infcx.type_is_copy_modulo_regions(env.env, ty) { + if infcx.type_is_copy_modulo_regions(env, ty) { DropGlue::None } else { DropGlue::DependOnParams diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index ab173799bc..cafe032969 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -944,7 +944,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { resolver: Resolver<'db>, ) -> Self { let trait_env = db.trait_environment_for_body(owner); - let table = unify::InferenceTable::new(db, trait_env, Some(owner)); + let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner)); let types = InternedStandardTypes::new(table.interner()); InferenceContext { result: InferenceResult::new(types.error), diff --git a/crates/hir-ty/src/infer/autoderef.rs b/crates/hir-ty/src/infer/autoderef.rs index 1af102af23..b54a6cdee2 100644 --- a/crates/hir-ty/src/infer/autoderef.rs +++ b/crates/hir-ty/src/infer/autoderef.rs @@ -16,11 +16,11 @@ use crate::{ impl<'db> InferenceTable<'db> { pub(crate) fn autoderef(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db, usize> { - Autoderef::new(&self.infer_ctxt, &self.trait_env, base_ty) + Autoderef::new(&self.infer_ctxt, self.param_env, base_ty) } pub(crate) fn autoderef_with_tracking(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db> { - Autoderef::new_with_tracking(&self.infer_ctxt, &self.trait_env, base_ty) + Autoderef::new_with_tracking(&self.infer_ctxt, self.param_env, base_ty) } } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 89ebd2b21d..14b0c9076c 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -367,7 +367,7 @@ impl<'db> InferenceContext<'_, 'db> { _ = self .table .infer_ctxt - .at(&ObligationCause::new(), self.table.trait_env.env) + .at(&ObligationCause::new(), self.table.param_env) .eq(inferred_fnptr_sig, generalized_fnptr_sig) .map(|infer_ok| self.table.register_infer_ok(infer_ok)); @@ -749,19 +749,18 @@ impl<'db> InferenceContext<'_, 'db> { { // Check that E' = S'. let cause = ObligationCause::new(); - let InferOk { value: (), obligations } = table - .infer_ctxt - .at(&cause, table.trait_env.env) - .eq(expected_ty, supplied_ty)?; + let InferOk { value: (), obligations } = + table.infer_ctxt.at(&cause, table.param_env).eq(expected_ty, supplied_ty)?; all_obligations.extend(obligations); } let supplied_output_ty = supplied_sig.output(); let cause = ObligationCause::new(); - let InferOk { value: (), obligations } = table - .infer_ctxt - .at(&cause, table.trait_env.env) - .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; + let InferOk { value: (), obligations } = + table + .infer_ctxt + .at(&cause, table.param_env) + .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?; all_obligations.extend(obligations); let inputs = supplied_sig diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index df24148920..77c7155550 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -50,10 +50,9 @@ use rustc_type_ir::{ }; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; -use triomphe::Arc; use crate::{ - Adjust, Adjustment, AutoBorrow, PointerCast, TargetFeatures, TraitEnvironment, + Adjust, Adjustment, AutoBorrow, ParamEnvAndCrate, PointerCast, TargetFeatures, autoderef::Autoderef, db::{HirDatabase, InternedClosureId}, infer::{ @@ -62,7 +61,7 @@ use crate::{ next_solver::{ Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper, Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, - GenericArgs, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind, + GenericArgs, ParamEnv, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind, TypingMode, infer::{ DbInternerInferExt, InferCtxt, InferOk, InferResult, @@ -77,7 +76,7 @@ use crate::{ trait CoerceDelegate<'db> { fn infcx(&self) -> &InferCtxt<'db>; - fn env(&self) -> &TraitEnvironment<'db>; + fn param_env(&self) -> ParamEnv<'db>; fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget); fn set_diverging(&mut self, diverging_ty: Ty<'db>); @@ -137,8 +136,8 @@ where } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - self.delegate.env() + fn param_env(&self) -> ParamEnv<'db> { + self.delegate.param_env() } #[inline] @@ -169,7 +168,7 @@ where fn unify_raw(&self, a: Ty<'db>, b: Ty<'db>) -> InferResult<'db, Ty<'db>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.infcx().commit_if_ok(|_| { - let at = self.infcx().at(&self.cause, self.env().env); + let at = self.infcx().at(&self.cause, self.param_env()); let res = if self.use_lub { at.lub(b, a) @@ -329,7 +328,7 @@ where obligations.push(Obligation::new( self.interner(), self.cause.clone(), - self.env().env, + self.param_env(), Binder::dummy(PredicateKind::Coerce(CoercePredicate { a: source_ty, b: target_ty, @@ -381,7 +380,7 @@ where let mut first_error = None; let mut r_borrow_var = None; - let mut autoderef = Autoderef::new_with_tracking(self.infcx(), self.env(), a); + let mut autoderef = Autoderef::new_with_tracking(self.infcx(), self.param_env(), a); let mut found = None; for (referent_ty, autoderefs) in autoderef.by_ref() { @@ -684,7 +683,7 @@ where let mut queue: SmallVec<[PredicateObligation<'db>; 4]> = smallvec![Obligation::new( self.interner(), cause, - self.env().env, + self.param_env(), TraitRef::new( self.interner(), coerce_unsized_did.into(), @@ -975,8 +974,8 @@ impl<'db> CoerceDelegate<'db> for InferenceCoercionDelegate<'_, '_, 'db> { &self.0.table.infer_ctxt } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - &self.0.table.trait_env + fn param_env(&self) -> ParamEnv<'db> { + self.0.table.param_env } #[inline] @@ -1104,12 +1103,8 @@ impl<'db> InferenceContext<'_, 'db> { match self.table.commit_if_ok(|table| { // We need to eagerly handle nested obligations due to lazy norm. let mut ocx = ObligationCtxt::new(&table.infer_ctxt); - let value = ocx.lub( - &ObligationCause::new(), - table.trait_env.env, - prev_ty, - new_ty, - )?; + let value = + ocx.lub(&ObligationCause::new(), table.param_env, prev_ty, new_ty)?; if ocx.try_evaluate_obligations().is_empty() { Ok(InferOk { value, obligations: ocx.into_pending_obligations() }) } else { @@ -1152,7 +1147,7 @@ impl<'db> InferenceContext<'_, 'db> { let sig = self .table .infer_ctxt - .at(&ObligationCause::new(), self.table.trait_env.env) + .at(&ObligationCause::new(), self.table.param_env) .lub(a_sig, b_sig) .map(|ok| self.table.register_infer_ok(ok))?; @@ -1231,7 +1226,7 @@ impl<'db> InferenceContext<'_, 'db> { .commit_if_ok(|table| { table .infer_ctxt - .at(&ObligationCause::new(), table.trait_env.env) + .at(&ObligationCause::new(), table.param_env) .lub(prev_ty, new_ty) }) .unwrap_err()) @@ -1483,7 +1478,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { // // Another example is `break` with no argument expression. assert!(expression_ty.is_unit(), "if let hack without unit type"); - icx.table.infer_ctxt.at(cause, icx.table.trait_env.env).eq(expected, found).map( + icx.table.infer_ctxt.at(cause, icx.table.param_env).eq(expected, found).map( |infer_ok| { icx.table.register_infer_ok(infer_ok); expression_ty @@ -1540,7 +1535,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { pub fn could_coerce<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { coerce(db, env, tys).is_ok() @@ -1548,7 +1543,7 @@ pub fn could_coerce<'db>( struct HirCoercionDelegate<'a, 'db> { infcx: &'a InferCtxt<'db>, - env: &'a TraitEnvironment<'db>, + param_env: ParamEnv<'db>, target_features: &'a TargetFeatures<'db>, } @@ -1558,8 +1553,8 @@ impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> { self.infcx } #[inline] - fn env(&self) -> &TraitEnvironment<'db> { - self.env + fn param_env(&self) -> ParamEnv<'db> { + self.param_env } fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) { (self.target_features, TargetFeatureIsSafeInTarget::No) @@ -1573,7 +1568,7 @@ impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> { fn coerce<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), TypeError<DbInterner<'db>>> { let interner = DbInterner::new_with(db, env.krate); @@ -1586,7 +1581,7 @@ fn coerce<'db>( let mut coerce = Coerce { delegate: HirCoercionDelegate { infcx: &infcx, - env: &env, + param_env: env.param_env, target_features: &target_features, }, cause, diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 01508b0f9b..4e1711e48e 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -4,7 +4,7 @@ use std::{iter::repeat_with, mem}; use either::Either; use hir_def::{ - BlockId, FieldId, GenericDefId, ItemContainerId, Lookup, TupleFieldId, TupleId, + FieldId, GenericDefId, ItemContainerId, Lookup, TupleFieldId, TupleId, expr_store::path::{GenericArgs as HirGenericArgs, Path}, hir::{ Array, AsmOperand, AsmOptions, BinaryOp, BindingAnnotation, Expr, ExprId, ExprOrPatId, @@ -23,7 +23,7 @@ use syntax::ast::RangeOp; use tracing::debug; use crate::{ - Adjust, Adjustment, CallableDefId, DeclContext, DeclOrigin, Rawness, TraitEnvironment, + Adjust, Adjustment, CallableDefId, DeclContext, DeclOrigin, Rawness, autoderef::InferenceContextAutoderef, consteval, db::InternedCoroutine, @@ -377,11 +377,11 @@ impl<'db> InferenceContext<'_, 'db> { ); self.types.bool } - Expr::Block { statements, tail, label, id } => { - self.infer_block(tgt_expr, *id, statements, *tail, *label, expected) + Expr::Block { statements, tail, label, id: _ } => { + self.infer_block(tgt_expr, statements, *tail, *label, expected) } - Expr::Unsafe { id, statements, tail } => { - self.infer_block(tgt_expr, *id, statements, *tail, None, expected) + Expr::Unsafe { id: _, statements, tail } => { + self.infer_block(tgt_expr, statements, *tail, None, expected) } Expr::Const(id) => { self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { @@ -389,8 +389,8 @@ impl<'db> InferenceContext<'_, 'db> { }) .1 } - Expr::Async { id, statements, tail } => { - self.infer_async_block(tgt_expr, id, statements, tail) + Expr::Async { id: _, statements, tail } => { + self.infer_async_block(tgt_expr, statements, tail) } &Expr::Loop { body, label } => { // FIXME: should be: @@ -1167,7 +1167,6 @@ impl<'db> InferenceContext<'_, 'db> { fn infer_async_block( &mut self, tgt_expr: ExprId, - id: &Option<BlockId>, statements: &[Statement], tail: &Option<ExprId>, ) -> Ty<'db> { @@ -1179,7 +1178,7 @@ impl<'db> InferenceContext<'_, 'db> { // FIXME: We should handle async blocks like we handle closures let expected = &Expectation::has_type(ret_ty); let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { - let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected); + let ty = this.infer_block(tgt_expr, statements, *tail, None, expected); if let Some(target) = expected.only_has_type(&mut this.table) { match this.coerce(tgt_expr.into(), ty, target, AllowTwoPhase::No, ExprIsRead::Yes) { Ok(res) => res, @@ -1447,7 +1446,6 @@ impl<'db> InferenceContext<'_, 'db> { fn infer_block( &mut self, expr: ExprId, - block_id: Option<BlockId>, statements: &[Statement], tail: Option<ExprId>, label: Option<LabelId>, @@ -1455,11 +1453,6 @@ impl<'db> InferenceContext<'_, 'db> { ) -> Ty<'db> { let coerce_ty = expected.coercion_target_type(&mut self.table); let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr); - let prev_env = block_id.map(|block_id| { - let prev_env = self.table.trait_env.clone(); - TraitEnvironment::with_block(&mut self.table.trait_env, block_id); - prev_env - }); let (break_ty, ty) = self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty), label, |this| { @@ -1566,9 +1559,6 @@ impl<'db> InferenceContext<'_, 'db> { } }); self.resolver.reset_to_guard(g); - if let Some(prev_env) = prev_env { - self.table.trait_env = prev_env; - } break_ty.unwrap_or(ty) } @@ -1974,7 +1964,7 @@ impl<'db> InferenceContext<'_, 'db> { // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. let origin = ObligationCause::new(); - ocx.sup(&origin, self.table.trait_env.env, expected_output, formal_output)?; + ocx.sup(&origin, self.table.param_env, expected_output, formal_output)?; if !ocx.try_evaluate_obligations().is_empty() { return Err(TypeError::Mismatch); } @@ -2066,7 +2056,7 @@ impl<'db> InferenceContext<'_, 'db> { let formal_ty_error = this .table .infer_ctxt - .at(&ObligationCause::new(), this.table.trait_env.env) + .at(&ObligationCause::new(), this.table.param_env) .eq(formal_input_ty, coerced_ty); // If neither check failed, the types are compatible @@ -2143,7 +2133,7 @@ impl<'db> InferenceContext<'_, 'db> { self.db, GenericDefId::from_callable(self.db, fn_def.0), ); - let param_env = self.table.trait_env.env; + let param_env = self.table.param_env; self.table.register_predicates(clauses_as_obligations( generic_predicates.iter_instantiated_copied(self.interner(), parameters.as_slice()), ObligationCause::new(), @@ -2162,7 +2152,7 @@ impl<'db> InferenceContext<'_, 'db> { self.table.register_predicate(Obligation::new( self.interner(), ObligationCause::new(), - self.table.trait_env.env, + self.table.param_env, TraitRef::new(self.interner(), trait_.into(), substs), )); } diff --git a/crates/hir-ty/src/infer/op.rs b/crates/hir-ty/src/infer/op.rs index 6fbac8f5ae..8236de167f 100644 --- a/crates/hir-ty/src/infer/op.rs +++ b/crates/hir-ty/src/infer/op.rs @@ -343,7 +343,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { let obligation = Obligation::new( self.interner(), cause, - self.table.trait_env.env, + self.table.param_env, TraitRef::new_from_args(self.interner(), trait_did.into(), args), ); let mut ocx = ObligationCtxt::new(self.infcx()); diff --git a/crates/hir-ty/src/infer/opaques.rs b/crates/hir-ty/src/infer/opaques.rs index ba4b53a0d7..ce4597f83d 100644 --- a/crates/hir-ty/src/infer/opaques.rs +++ b/crates/hir-ty/src/infer/opaques.rs @@ -136,7 +136,7 @@ impl<'db> InferenceContext<'_, 'db> { } let cause = ObligationCause::new(); - let at = self.table.infer_ctxt.at(&cause, self.table.trait_env.env); + let at = self.table.infer_ctxt.at(&cause, self.table.param_env); let hidden_type = match at.deeply_normalize(hidden_type) { Ok(hidden_type) => hidden_type, Err(_errors) => OpaqueHiddenType { ty: self.types.error }, diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 6e3d15893f..301cbf462c 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -224,7 +224,7 @@ impl<'db> InferenceContext<'_, 'db> { ) { let interner = self.interner(); let predicates = GenericPredicates::query_all(self.db, def); - let param_env = self.table.trait_env.env; + let param_env = self.table.param_env; self.table.register_predicates(clauses_as_obligations( predicates.iter_instantiated_copied(interner, subst.as_slice()), ObligationCause::new(), @@ -343,7 +343,7 @@ impl<'db> InferenceContext<'_, 'db> { self.table.register_predicate(Obligation::new( self.interner(), ObligationCause::new(), - self.table.trait_env.env, + self.table.param_env, trait_ref, )); args diff --git a/crates/hir-ty/src/infer/place_op.rs b/crates/hir-ty/src/infer/place_op.rs index 9544fb449f..3ef5e5870a 100644 --- a/crates/hir-ty/src/infer/place_op.rs +++ b/crates/hir-ty/src/infer/place_op.rs @@ -124,7 +124,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { ctx.table.register_predicate(Obligation::new( ctx.interner(), ObligationCause::new(), - ctx.table.trait_env.env, + ctx.table.param_env, ClauseKind::ConstArgHasType(ct, ctx.types.usize), )); self_ty = Ty::new_slice(ctx.interner(), element_ty); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index bc3c46341c..a5060416a1 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -2,6 +2,7 @@ use std::fmt; +use base_db::Crate; use hir_def::{AdtId, DefWithBodyId, GenericParamId}; use hir_expand::name::Name; use intern::sym; @@ -12,15 +13,13 @@ use rustc_type_ir::{ solve::Certainty, }; use smallvec::SmallVec; -use triomphe::Arc; use crate::{ - TraitEnvironment, db::HirDatabase, next_solver::{ AliasTy, Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, - GenericArgs, Goal, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty, - TyKind, TypingMode, + GenericArgs, Goal, ParamEnv, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, + Ty, TyKind, TypingMode, fulfill::{FulfillmentCtxt, NextSolverError}, infer::{ DbInternerInferExt, InferCtxt, InferOk, InferResult, @@ -32,7 +31,8 @@ use crate::{ obligation_ctxt::ObligationCtxt, }, traits::{ - FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt, + FnTrait, NextTraitSolveResult, ParamEnvAndCrate, next_trait_solve_canonical_in_ctxt, + next_trait_solve_in_ctxt, }, }; @@ -89,7 +89,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> { /// unresolved goal `T = U`. pub fn could_unify<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { could_unify_impl(db, env, tys, |ctxt| ctxt.try_evaluate_obligations()) @@ -101,7 +101,7 @@ pub fn could_unify<'db>( /// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U` pub fn could_unify_deeply<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { could_unify_impl(db, env, tys, |ctxt| ctxt.evaluate_obligations_error_on_ambiguity()) @@ -109,14 +109,14 @@ pub fn could_unify_deeply<'db>( fn could_unify_impl<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, select: for<'a> fn(&mut ObligationCtxt<'a, 'db>) -> Vec<NextSolverError<'db>>, ) -> bool { let interner = DbInterner::new_with(db, env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let cause = ObligationCause::dummy(); - let at = infcx.at(&cause, env.env); + let at = infcx.at(&cause, env.param_env); let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(tys); let mut ctxt = ObligationCtxt::new(&infcx); let can_unify = at @@ -129,7 +129,7 @@ fn could_unify_impl<'db>( #[derive(Clone)] pub(crate) struct InferenceTable<'db> { pub(crate) db: &'db dyn HirDatabase, - pub(crate) trait_env: Arc<TraitEnvironment<'db>>, + pub(crate) param_env: ParamEnv<'db>, pub(crate) infer_ctxt: InferCtxt<'db>, pub(super) fulfillment_cx: FulfillmentCtxt<'db>, pub(super) diverging_type_vars: FxHashSet<Ty<'db>>, @@ -145,10 +145,11 @@ impl<'db> InferenceTable<'db> { /// Outside it, always pass `owner = None`. pub(crate) fn new( db: &'db dyn HirDatabase, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnv<'db>, + krate: Crate, owner: Option<DefWithBodyId>, ) -> Self { - let interner = DbInterner::new_with(db, trait_env.krate); + let interner = DbInterner::new_with(db, krate); let typing_mode = match owner { Some(owner) => TypingMode::typeck_for_body(interner, owner.into()), // IDE things wants to reveal opaque types. @@ -157,7 +158,7 @@ impl<'db> InferenceTable<'db> { let infer_ctxt = interner.infer_ctxt().build(typing_mode); InferenceTable { db, - trait_env, + param_env: trait_env, fulfillment_cx: FulfillmentCtxt::new(&infer_ctxt), infer_ctxt, diverging_type_vars: FxHashSet::default(), @@ -170,7 +171,7 @@ impl<'db> InferenceTable<'db> { } pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'db>) -> bool { - self.infer_ctxt.type_is_copy_modulo_regions(self.trait_env.env, ty) + self.infer_ctxt.type_is_copy_modulo_regions(self.param_env, ty) } pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool { @@ -272,7 +273,7 @@ impl<'db> InferenceTable<'db> { pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> { self.infer_ctxt - .at(&ObligationCause::new(), self.trait_env.env) + .at(&ObligationCause::new(), self.param_env) .structurally_normalize_ty(alias, &mut self.fulfillment_cx) .unwrap_or(alias) } @@ -332,7 +333,7 @@ impl<'db> InferenceTable<'db> { } pub(crate) fn at<'a>(&'a self, cause: &'a ObligationCause) -> At<'a, 'db> { - self.infer_ctxt.at(cause, self.trait_env.env) + self.infer_ctxt.at(cause, self.param_env) } pub(crate) fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> { @@ -374,7 +375,7 @@ impl<'db> InferenceTable<'db> { // in a reentrant borrow, causing an ICE. let result = self .infer_ctxt - .at(&ObligationCause::misc(), self.trait_env.env) + .at(&ObligationCause::misc(), self.param_env) .structurally_normalize_ty(ty, &mut self.fulfillment_cx); match result { Ok(normalized_ty) => normalized_ty, @@ -422,14 +423,14 @@ impl<'db> InferenceTable<'db> { /// choice (during e.g. method resolution or deref). #[tracing::instrument(level = "debug", skip(self))] pub(crate) fn try_obligation(&mut self, predicate: Predicate<'db>) -> NextTraitSolveResult { - let goal = Goal { param_env: self.trait_env.env, predicate }; + let goal = Goal { param_env: self.param_env, predicate }; let canonicalized = self.canonicalize(goal); next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized) } pub(crate) fn register_obligation(&mut self, predicate: Predicate<'db>) { - let goal = Goal { param_env: self.trait_env.env, predicate }; + let goal = Goal { param_env: self.param_env, predicate }; self.register_obligation_in_env(goal) } @@ -486,7 +487,7 @@ impl<'db> InferenceTable<'db> { self.register_predicate(Obligation::new( self.interner(), cause, - self.trait_env.env, + self.param_env, ClauseKind::WellFormed(term), )); } diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs index 5e742bba3e..075a7066db 100644 --- a/crates/hir-ty/src/inhabitedness.rs +++ b/crates/hir-ty/src/inhabitedness.rs @@ -7,14 +7,12 @@ use rustc_type_ir::{ TypeSuperVisitable, TypeVisitable, TypeVisitor, inherent::{AdtDef, IntoKind}, }; -use triomphe::Arc; use crate::{ - TraitEnvironment, consteval::try_const_usize, db::HirDatabase, next_solver::{ - DbInterner, EarlyBinder, GenericArgs, Ty, TyKind, + DbInterner, EarlyBinder, GenericArgs, ParamEnv, Ty, TyKind, infer::{InferCtxt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, }, @@ -26,7 +24,7 @@ pub(crate) fn is_ty_uninhabited_from<'db>( infcx: &InferCtxt<'db>, ty: Ty<'db>, target_mod: ModuleId, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, ) -> bool { let _p = tracing::info_span!("is_ty_uninhabited_from", ?ty).entered(); let mut uninhabited_from = UninhabitedFrom::new(infcx, target_mod, env); @@ -41,7 +39,7 @@ pub(crate) fn is_enum_variant_uninhabited_from<'db>( variant: EnumVariantId, subst: GenericArgs<'db>, target_mod: ModuleId, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, ) -> bool { let _p = tracing::info_span!("is_enum_variant_uninhabited_from").entered(); @@ -56,7 +54,7 @@ struct UninhabitedFrom<'a, 'db> { // guard for preventing stack overflow in non trivial non terminating types max_depth: usize, infcx: &'a InferCtxt<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, } const CONTINUE_OPAQUELY_INHABITED: ControlFlow<VisiblyUninhabited> = Continue(()); @@ -78,7 +76,7 @@ impl<'db> TypeVisitor<DbInterner<'db>> for UninhabitedFrom<'_, 'db> { if matches!(ty.kind(), TyKind::Alias(..)) { let mut ocx = ObligationCtxt::new(self.infcx); - match ocx.structurally_normalize_ty(&ObligationCause::dummy(), self.env.env, ty) { + match ocx.structurally_normalize_ty(&ObligationCause::dummy(), self.env, ty) { Ok(it) => ty = it, Err(_) => return CONTINUE_OPAQUELY_INHABITED, } @@ -101,11 +99,7 @@ impl<'db> TypeVisitor<DbInterner<'db>> for UninhabitedFrom<'_, 'db> { } impl<'a, 'db> UninhabitedFrom<'a, 'db> { - fn new( - infcx: &'a InferCtxt<'db>, - target_mod: ModuleId, - env: Arc<TraitEnvironment<'db>>, - ) -> Self { + fn new(infcx: &'a InferCtxt<'db>, target_mod: ModuleId, env: ParamEnv<'db>) -> Self { Self { target_mod, recursive_ty: FxHashSet::default(), max_depth: 500, infcx, env } } diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 97660a67ef..565063fb13 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -21,7 +21,7 @@ use rustc_type_ir::{ use triomphe::Arc; use crate::{ - InferenceResult, TraitEnvironment, + InferenceResult, ParamEnvAndCrate, consteval::try_const_usize, db::HirDatabase, next_solver::{ @@ -131,7 +131,7 @@ fn layout_of_simd_ty<'db>( id: StructId, repr_packed: bool, args: &GenericArgs<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, dl: &TargetDataLayout, ) -> Result<Arc<Layout>, LayoutError> { // Supported SIMD vectors are homogeneous ADTs with exactly one array field: @@ -159,7 +159,7 @@ fn layout_of_simd_ty<'db>( pub fn layout_of_ty_query<'db>( db: &'db dyn HirDatabase, ty: Ty<'db>, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError> { let krate = trait_env.krate; let interner = DbInterner::new_with(db, krate); @@ -248,10 +248,8 @@ pub fn layout_of_ty_query<'db>( let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; - let fields = tys - .iter() - .map(|k| db.layout_of_ty(k, trait_env.clone())) - .collect::<Result<Vec<_>, _>>()?; + let fields = + tys.iter().map(|k| db.layout_of_ty(k, trait_env)).collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); let fields = fields.iter().collect::<IndexVec<_, _>>(); cx.calc.univariant(&fields, &ReprOptions::default(), kind)? @@ -329,7 +327,7 @@ pub fn layout_of_ty_query<'db>( .map(|it| { let ty = it.ty.instantiate(interner, args.split_closure_args_untupled().parent_args); - db.layout_of_ty(ty, trait_env.clone()) + db.layout_of_ty(ty, trait_env) }) .collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); @@ -362,7 +360,7 @@ pub fn layout_of_ty_query<'db>( pub(crate) fn layout_of_ty_cycle_result<'db>( _: &dyn HirDatabase, _: Ty<'db>, - _: Arc<TraitEnvironment<'db>>, + _: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError> { Err(LayoutError::RecursiveTypeWithoutIndirection) } diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index ecebf7935d..cf2d0989fd 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -13,7 +13,7 @@ use smallvec::SmallVec; use triomphe::Arc; use crate::{ - TraitEnvironment, + ParamEnvAndCrate, db::HirDatabase, layout::{Layout, LayoutCx, LayoutError, field_ty}, next_solver::GenericArgs, @@ -23,7 +23,7 @@ pub fn layout_of_adt_query<'db>( db: &'db dyn HirDatabase, def: AdtId, args: GenericArgs<'db>, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError> { let krate = trait_env.krate; let Ok(target) = db.target_data_layout(krate) else { @@ -34,7 +34,7 @@ pub fn layout_of_adt_query<'db>( let handle_variant = |def: VariantId, var: &VariantFields| { var.fields() .iter() - .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &args), trait_env.clone())) + .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &args), trait_env)) .collect::<Result<Vec<_>, _>>() }; let (variants, repr, is_special_no_niche) = match def { @@ -99,7 +99,7 @@ pub(crate) fn layout_of_adt_cycle_result<'db>( _: &'db dyn HirDatabase, _def: AdtId, _args: GenericArgs<'db>, - _trait_env: Arc<TraitEnvironment<'db>>, + _trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<Layout>, LayoutError> { Err(LayoutError::RecursiveTypeWithoutIndirection) } diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs index 878813a696..43215253ba 100644 --- a/crates/hir-ty/src/layout/tests.rs +++ b/crates/hir-ty/src/layout/tests.rs @@ -1,6 +1,6 @@ use base_db::target::TargetData; use either::Either; -use hir_def::db::DefDatabase; +use hir_def::{HasModule, db::DefDatabase}; use project_model::{Sysroot, toolchain_info::QueryConfig}; use rustc_hash::FxHashMap; use rustc_type_ir::inherent::GenericArgs as _; @@ -9,7 +9,7 @@ use test_fixture::WithFixture; use triomphe::Arc; use crate::{ - InferenceResult, + InferenceResult, ParamEnvAndCrate, db::HirDatabase, layout::{Layout, LayoutError}, next_solver::{DbInterner, GenericArgs}, @@ -90,13 +90,15 @@ fn eval_goal( ), Either::Right(ty_id) => db.ty(ty_id.into()).instantiate_identity(), }; - db.layout_of_ty( - goal_ty, - db.trait_environment(match adt_or_type_alias_id { - Either::Left(adt) => hir_def::GenericDefId::AdtId(adt), - Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty), - }), - ) + let param_env = db.trait_environment(match adt_or_type_alias_id { + Either::Left(adt) => hir_def::GenericDefId::AdtId(adt), + Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty), + }); + let krate = match adt_or_type_alias_id { + Either::Left(it) => it.krate(&db), + Either::Right(it) => it.krate(&db), + }; + db.layout_of_ty(goal_ty, ParamEnvAndCrate { param_env, krate }) }) } @@ -139,7 +141,9 @@ fn eval_expr( .0; let infer = InferenceResult::for_body(&db, function_id.into()); let goal_ty = infer.type_of_binding[b]; - db.layout_of_ty(goal_ty, db.trait_environment(function_id.into())) + let param_env = db.trait_environment(function_id.into()); + let krate = function_id.krate(&db); + db.layout_of_ty(goal_ty, ParamEnvAndCrate { param_env, krate }) }) } diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 6d3adec6a8..5ebe87c5d5 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -2,6 +2,8 @@ //! information and various assists. #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +// It's useful to refer to code that is private in doc comments. +#![allow(rustdoc::private_intra_doc_links)] // FIXME: We used to import `rustc_*` deps from `rustc_private` with `feature = "in-rust-tree" but // temporarily switched to crates.io versions due to hardships that working on them from rustc @@ -67,7 +69,6 @@ use rustc_type_ir::{ }; use syntax::ast::{ConstArg, make}; use traits::FnTrait; -use triomphe::Arc; use crate::{ db::HirDatabase, @@ -94,7 +95,7 @@ pub use lower::{ }; pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db}; pub use target_feature::TargetFeatures; -pub use traits::{TraitEnvironment, check_orphan_rules}; +pub use traits::{ParamEnvAndCrate, check_orphan_rules}; pub use utils::{ TargetFeatureIsSafeInTarget, Unsafety, all_super_traits, direct_super_traits, is_fn_unsafe_to_call, target_feature_is_safe_in_target, @@ -474,10 +475,10 @@ where /// To be used from `hir` only. pub fn callable_sig_from_fn_trait<'db>( self_ty: Ty<'db>, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, db: &'db dyn HirDatabase, ) -> Option<(FnTrait, PolyFnSig<'db>)> { - let mut table = InferenceTable::new(db, trait_env.clone(), None); + let mut table = InferenceTable::new(db, trait_env.param_env, trait_env.krate, None); let lang_items = table.interner().lang_items(); let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?; diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index cfd2a06b2a..301e89556d 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -53,7 +53,7 @@ use tracing::debug; use triomphe::{Arc, ThinArc}; use crate::{ - FnAbi, ImplTraitId, TraitEnvironment, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, consteval::intern_const_ref, db::{HirDatabase, InternedOpaqueTyId}, generics::{Generics, generics, trait_self_param_idx}, @@ -1743,10 +1743,9 @@ impl<'db> GenericPredicates<'db> { pub(crate) fn trait_environment_for_body_query( db: &dyn HirDatabase, def: DefWithBodyId, -) -> Arc<TraitEnvironment<'_>> { +) -> ParamEnv<'_> { let Some(def) = def.as_generic_def_id(db) else { - let krate = def.module(db).krate(); - return TraitEnvironment::empty(krate); + return ParamEnv::empty(); }; db.trait_environment(def) } @@ -1754,24 +1753,16 @@ pub(crate) fn trait_environment_for_body_query( pub(crate) fn trait_environment_query<'db>( db: &'db dyn HirDatabase, def: GenericDefId, -) -> Arc<TraitEnvironment<'db>> { +) -> ParamEnv<'db> { let module = def.module(db); let interner = DbInterner::new_with(db, module.krate()); let predicates = GenericPredicates::query_all(db, def); - let traits_in_scope = predicates - .iter_identity_copied() - .filter_map(|pred| match pred.kind().skip_binder() { - ClauseKind::Trait(tr) => Some((tr.self_ty(), tr.def_id().0)), - _ => None, - }) - .collect(); let clauses = rustc_type_ir::elaborate::elaborate(interner, predicates.iter_identity_copied()); let clauses = Clauses::new_from_iter(interner, clauses); - let env = ParamEnv { clauses }; // FIXME: We should normalize projections here, like rustc does. - TraitEnvironment::new(module.krate(), module.containing_block(), traits_in_scope, env) + ParamEnv { clauses } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 9a6adedb99..a5ec2a3fec 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -32,13 +32,13 @@ use stdx::impl_from; use triomphe::Arc; use crate::{ - TraitEnvironment, all_super_traits, + all_super_traits, db::HirDatabase, infer::{InferenceContext, unify::InferenceTable}, lower::GenericPredicates, next_solver::{ - Binder, ClauseKind, DbInterner, FnSig, GenericArgs, PredicateKind, SimplifiedType, - SolverDefId, TraitRef, Ty, TyKind, TypingMode, + Binder, ClauseKind, DbInterner, FnSig, GenericArgs, ParamEnv, PredicateKind, + SimplifiedType, SolverDefId, TraitRef, Ty, TyKind, TypingMode, infer::{ BoundRegionConversionTime, DbInternerInferExt, InferCtxt, InferOk, select::ImplSource, @@ -47,6 +47,7 @@ use crate::{ obligation_ctxt::ObligationCtxt, util::clauses_as_obligations, }, + traits::ParamEnvAndCrate, }; pub use self::probe::{ @@ -75,7 +76,7 @@ impl MethodResolutionUnstableFeatures { pub struct MethodResolutionContext<'a, 'db> { pub infcx: &'a InferCtxt<'db>, pub resolver: &'a Resolver<'db>, - pub env: &'a TraitEnvironment<'db>, + pub param_env: ParamEnv<'db>, pub traits_in_scope: &'a FxHashSet<TraitId>, pub edition: Edition, pub unstable_features: &'a MethodResolutionUnstableFeatures, @@ -194,7 +195,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> { let ctx = MethodResolutionContext { infcx: &self.table.infer_ctxt, resolver: &self.resolver, - env: &self.table.trait_env, + param_env: self.table.param_env, traits_in_scope, edition: self.edition, unstable_features: &self.unstable_features, @@ -264,7 +265,7 @@ impl<'db> InferenceTable<'db> { let obligation = Obligation::new( self.interner(), cause, - self.trait_env.env, + self.param_env, TraitRef::new_from_args(self.interner(), trait_def_id.into(), args), ); @@ -322,7 +323,7 @@ impl<'db> InferenceTable<'db> { let bounds = clauses_as_obligations( bounds.iter_instantiated_copied(interner, args.as_slice()), ObligationCause::new(), - self.trait_env.env, + self.param_env, ); obligations.extend(bounds); @@ -336,7 +337,7 @@ impl<'db> InferenceTable<'db> { obligations.push(Obligation::new( interner, obligation.cause.clone(), - self.trait_env.env, + self.param_env, Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(ty.into()))), )); } @@ -350,7 +351,7 @@ impl<'db> InferenceTable<'db> { pub fn lookup_impl_const<'db>( infcx: &InferCtxt<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, const_id: ConstId, subs: GenericArgs<'db>, ) -> (ConstId, GenericArgs<'db>) { @@ -380,7 +381,7 @@ pub fn lookup_impl_const<'db>( /// call the method using the vtable. pub fn is_dyn_method<'db>( interner: DbInterner<'db>, - _env: Arc<TraitEnvironment<'db>>, + _env: ParamEnv<'db>, func: FunctionId, fn_subst: GenericArgs<'db>, ) -> Option<usize> { @@ -415,7 +416,7 @@ pub fn is_dyn_method<'db>( /// Returns `func` if it's not a method defined in a trait or the lookup failed. pub(crate) fn lookup_impl_method_query<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, func: FunctionId, fn_subst: GenericArgs<'db>, ) -> (FunctionId, GenericArgs<'db>) { @@ -433,11 +434,15 @@ pub(crate) fn lookup_impl_method_query<'db>( ); let name = &db.function_signature(func).name; - let Some((impl_fn, impl_subst)) = - lookup_impl_assoc_item_for_trait_ref(&infcx, trait_ref, env, name).and_then(|assoc| { - if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None } - }) - else { + let Some((impl_fn, impl_subst)) = lookup_impl_assoc_item_for_trait_ref( + &infcx, + trait_ref, + env.param_env, + name, + ) + .and_then(|assoc| { + if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None } + }) else { return (func, fn_subst); }; @@ -453,10 +458,10 @@ pub(crate) fn lookup_impl_method_query<'db>( fn lookup_impl_assoc_item_for_trait_ref<'db>( infcx: &InferCtxt<'db>, trait_ref: TraitRef<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, name: &Name, ) -> Option<(AssocItemId, GenericArgs<'db>)> { - let (impl_id, impl_subst) = find_matching_impl(infcx, &env, trait_ref)?; + let (impl_id, impl_subst) = find_matching_impl(infcx, env, trait_ref)?; let item = impl_id.impl_items(infcx.interner.db).items.iter().find_map(|(n, it)| match *it { AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)), @@ -468,13 +473,12 @@ fn lookup_impl_assoc_item_for_trait_ref<'db>( pub(crate) fn find_matching_impl<'db>( infcx: &InferCtxt<'db>, - env: &TraitEnvironment<'db>, + env: ParamEnv<'db>, trait_ref: TraitRef<'db>, ) -> Option<(ImplId, GenericArgs<'db>)> { - let trait_ref = - infcx.at(&ObligationCause::dummy(), env.env).deeply_normalize(trait_ref).ok()?; + let trait_ref = infcx.at(&ObligationCause::dummy(), env).deeply_normalize(trait_ref).ok()?; - let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env.env, trait_ref); + let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env, trait_ref); let selection = infcx.select(&obligation).ok()??; diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs index 570dd63a50..6d6515a457 100644 --- a/crates/hir-ty/src/method_resolution/confirm.rs +++ b/crates/hir-ty/src/method_resolution/confirm.rs @@ -507,7 +507,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> { GenericPredicates::query_all(self.db(), def_id.into()) .iter_instantiated_copied(self.interner(), all_args), ObligationCause::new(), - self.ctx.table.trait_env.env, + self.ctx.table.param_env, ); let sig = diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs index adc144ce11..02f86815ed 100644 --- a/crates/hir-ty/src/method_resolution/probe.rs +++ b/crates/hir-ty/src/method_resolution/probe.rs @@ -334,7 +334,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> { .infcx .instantiate_query_response_and_region_obligations( &ObligationCause::new(), - self.env.env, + self.param_env, &orig_values, ty, ) @@ -394,7 +394,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> { // converted to, in order to find out which of those methods might actually // be callable. let mut autoderef_via_deref = - Autoderef::new(infcx, self.env, self_ty).include_raw_pointers(); + Autoderef::new(infcx, self.param_env, self_ty).include_raw_pointers(); let mut reached_raw_pointer = false; let arbitrary_self_types_enabled = self.unstable_features.arbitrary_self_types @@ -403,7 +403,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> { let reachable_via_deref = autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false)); - let mut autoderef_via_receiver = Autoderef::new(infcx, self.env, self_ty) + let mut autoderef_via_receiver = Autoderef::new(infcx, self.param_env, self_ty) .include_raw_pointers() .use_receiver_trait(); let steps = autoderef_via_receiver @@ -835,7 +835,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> { #[inline] fn param_env(&self) -> ParamEnv<'db> { - self.ctx.env.env + self.ctx.param_env } /// When we're looking up a method by path (UFCS), we relate the receiver diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index f47e3b7a30..3cafb6aa25 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -977,15 +977,13 @@ pub enum Rvalue<'db> { UnaryOp(UnOp, Operand<'db>), /// Computes the discriminant of the place, returning it as an integer of type - /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// `discriminant_ty`. Returns zero for types without discriminant. /// /// The validity requirements for the underlying value are undecided for this rvalue, see /// [#91095]. Note too that the value of the discriminant is not the same thing as the - /// variant index; use [`discriminant_for_variant`] to convert. + /// variant index; use `discriminant_for_variant` to convert. /// - /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty /// [#91095]: https://github.com/rust-lang/rust/issues/91095 - /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant Discriminant(Place<'db>), /// Creates an aggregate value, like a tuple or struct. diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index 2d2fc03dcc..031654a259 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -12,12 +12,12 @@ use stdx::never; use triomphe::Arc; use crate::{ - InferenceResult, TraitEnvironment, + InferenceResult, db::{HirDatabase, InternedClosure, InternedClosureId}, display::DisplayTarget, mir::OperandKind, next_solver::{ - DbInterner, GenericArgs, Ty, TypingMode, + DbInterner, GenericArgs, ParamEnv, Ty, TypingMode, infer::{DbInternerInferExt, InferCtxt}, }, }; @@ -107,8 +107,8 @@ pub fn borrowck_query<'db>( let infcx = interner.infer_ctxt().build(typing_mode); res.push(BorrowckResult { mutability_of_locals: mutability_of_locals(&infcx, &body), - moved_out_of_ref: moved_out_of_ref(&infcx, &env, &body), - partially_moved: partially_moved(&infcx, &env, &body), + moved_out_of_ref: moved_out_of_ref(&infcx, env, &body), + partially_moved: partially_moved(&infcx, env, &body), borrow_regions: borrow_regions(db, &body), mir_body: body, }); @@ -131,7 +131,7 @@ fn make_fetch_closure_field<'db>( fn moved_out_of_ref<'db>( infcx: &InferCtxt<'db>, - env: &TraitEnvironment<'db>, + env: ParamEnv<'db>, body: &MirBody<'db>, ) -> Vec<MovedOutOfRef<'db>> { let db = infcx.interner.db; @@ -152,7 +152,7 @@ fn moved_out_of_ref<'db>( ); } if is_dereference_of_ref - && !infcx.type_is_copy_modulo_regions(env.env, ty) + && !infcx.type_is_copy_modulo_regions(env, ty) && !ty.references_non_lt_error() { result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty }); @@ -231,7 +231,7 @@ fn moved_out_of_ref<'db>( fn partially_moved<'db>( infcx: &InferCtxt<'db>, - env: &TraitEnvironment<'db>, + env: ParamEnv<'db>, body: &MirBody<'db>, ) -> Vec<PartiallyMoved<'db>> { let db = infcx.interner.db; @@ -247,7 +247,7 @@ fn partially_moved<'db>( body.owner.module(db).krate(), ); } - if !infcx.type_is_copy_modulo_regions(env.env, ty) && !ty.references_non_lt_error() { + if !infcx.type_is_copy_modulo_regions(env, ty) && !ty.references_non_lt_error() { result.push(PartiallyMoved { span, ty, local: p.local }); } } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 3418689027..02e322f037 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -34,7 +34,7 @@ use syntax::{SyntaxNodePtr, TextRange}; use triomphe::Arc; use crate::{ - CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, TraitEnvironment, + CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, ParamEnvAndCrate, consteval::{self, ConstEvalError, try_const_usize}, db::{HirDatabase, InternedClosure, InternedClosureId}, display::{ClosureStyle, DisplayTarget, HirDisplay}, @@ -165,7 +165,7 @@ enum MirOrDynIndex<'db> { pub struct Evaluator<'db> { db: &'db dyn HirDatabase, - trait_env: Arc<TraitEnvironment<'db>>, + param_env: ParamEnvAndCrate<'db>, target_data_layout: Arc<TargetDataLayout>, stack: Vec<u8>, heap: Vec<u8>, @@ -594,7 +594,7 @@ pub fn interpret_mir<'db>( // a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can // (and probably should) do better here, for example by excluding bindings outside of the target expression. assert_placeholder_ty_is_unused: bool, - trait_env: Option<Arc<TraitEnvironment<'db>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> { let ty = body.locals[return_slot()].ty; let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; @@ -632,7 +632,7 @@ impl<'db> Evaluator<'db> { db: &'db dyn HirDatabase, owner: DefWithBodyId, assert_placeholder_ty_is_unused: bool, - trait_env: Option<Arc<TraitEnvironment<'db>>>, + trait_env: Option<ParamEnvAndCrate<'db>>, ) -> Result<'db, Evaluator<'db>> { let module = owner.module(db); let crate_id = module.krate(); @@ -654,7 +654,10 @@ impl<'db> Evaluator<'db> { static_locations: Default::default(), db, random_state: oorandom::Rand64::new(0), - trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)), + param_env: trait_env.unwrap_or_else(|| ParamEnvAndCrate { + param_env: db.trait_environment_for_body(owner), + krate: crate_id, + }), crate_id, stdout: vec![], stderr: vec![], @@ -864,7 +867,7 @@ impl<'db> Evaluator<'db> { } let r = self .db - .layout_of_ty(ty, self.trait_env.clone()) + .layout_of_ty(ty, self.param_env) .map_err(|e| MirEvalError::LayoutError(e, ty))?; self.layout_cache.borrow_mut().insert(ty, r.clone()); Ok(r) @@ -1927,18 +1930,17 @@ impl<'db> Evaluator<'db> { let mut id = const_id.0; let mut subst = subst; if let hir_def::GeneralConstId::ConstId(c) = id { - let (c, s) = lookup_impl_const(&self.infcx, self.trait_env.clone(), c, subst); + let (c, s) = lookup_impl_const(&self.infcx, self.param_env.param_env, c, subst); id = hir_def::GeneralConstId::ConstId(c); subst = s; } result_owner = match id { - GeneralConstId::ConstId(const_id) => self - .db - .const_eval(const_id, subst, Some(self.trait_env.clone())) - .map_err(|e| { + GeneralConstId::ConstId(const_id) => { + self.db.const_eval(const_id, subst, Some(self.param_env)).map_err(|e| { let name = id.name(self.db); MirEvalError::ConstEvalError(name, Box::new(e)) - })?, + })? + } GeneralConstId::StaticId(static_id) => { self.db.const_eval_static(static_id).map_err(|e| { let name = id.name(self.db); @@ -2331,7 +2333,7 @@ impl<'db> Evaluator<'db> { let ty = ocx .structurally_normalize_ty( &ObligationCause::dummy(), - this.trait_env.env, + this.param_env.param_env, ty, ) .map_err(|_| MirEvalError::NotSupported("couldn't normalize".to_owned()))?; @@ -2510,7 +2512,7 @@ impl<'db> Evaluator<'db> { ) -> Result<'db, Option<StackFrame<'db>>> { let mir_body = self .db - .monomorphized_mir_body_for_closure(closure, generic_args, self.trait_env.clone()) + .monomorphized_mir_body_for_closure(closure, generic_args, self.param_env) .map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?; let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some() { @@ -2606,16 +2608,19 @@ impl<'db> Evaluator<'db> { } let (def, generic_args) = pair; let r = if let Some(self_ty_idx) = - is_dyn_method(self.interner(), self.trait_env.clone(), def, generic_args) + is_dyn_method(self.interner(), self.param_env.param_env, def, generic_args) { MirOrDynIndex::Dyn(self_ty_idx) } else { - let (imp, generic_args) = - self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args); + let (imp, generic_args) = self.db.lookup_impl_method( + ParamEnvAndCrate { param_env: self.param_env.param_env, krate: self.crate_id }, + def, + generic_args, + ); let mir_body = self .db - .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone()) + .monomorphized_mir_body(imp.into(), generic_args, self.param_env) .map_err(|e| { MirEvalError::InFunction( Box::new(MirEvalError::MirLowerError(imp, e)), diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 591c12ec24..42c11113ee 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -840,7 +840,7 @@ impl<'db> Evaluator<'db> { "size_of generic arg is not provided".into(), )); }; - let result = match has_drop_glue(&self.infcx, ty, self.trait_env.clone()) { + let result = match has_drop_glue(&self.infcx, ty, self.param_env.param_env) { DropGlue::HasDropGlue => true, DropGlue::None => false, DropGlue::DependOnParams => { diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index bb2afb2f00..2c0c3427cb 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -1,4 +1,4 @@ -use hir_def::db::DefDatabase; +use hir_def::{HasModule, db::DefDatabase}; use hir_expand::EditionedFileId; use span::Edition; use syntax::{TextRange, TextSize}; @@ -40,7 +40,10 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), .monomorphized_mir_body( func_id.into(), GenericArgs::new_from_iter(interner, []), - db.trait_environment(func_id.into()), + crate::ParamEnvAndCrate { + param_env: db.trait_environment(func_id.into()), + krate: func_id.krate(db), + }, ) .map_err(|e| MirEvalError::MirLowerError(func_id, e))?; diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 190b2f99cc..5bce4222a4 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -25,7 +25,7 @@ use syntax::TextRange; use triomphe::Arc; use crate::{ - Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, + Adjust, Adjustment, AutoBorrow, CallableDefId, ParamEnvAndCrate, consteval::ConstEvalError, db::{HirDatabase, InternedClosure, InternedClosureId}, display::{DisplayTarget, HirDisplay, hir_display_with_store}, @@ -42,7 +42,7 @@ use crate::{ TupleFieldId, Ty, UnOp, VariantId, return_slot, }, next_solver::{ - Const, DbInterner, ParamConst, Region, TyKind, TypingMode, UnevaluatedConst, + Const, DbInterner, ParamConst, ParamEnv, Region, TyKind, TypingMode, UnevaluatedConst, infer::{DbInternerInferExt, InferCtxt}, }, traits::FnTrait, @@ -81,7 +81,7 @@ struct MirLowerCtx<'a, 'db> { infer: &'a InferenceResult<'db>, resolver: Resolver<'db>, drop_scopes: Vec<DropScope<'db>>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, infcx: InferCtxt<'db>, } @@ -302,7 +302,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; let resolver = owner.resolver(db); let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, env.krate); + let interner = DbInterner::new_with(db, resolver.krate()); // FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body? let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); @@ -1462,7 +1462,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { } fn lower_literal_to_operand(&mut self, ty: Ty<'db>, l: &Literal) -> Result<'db, Operand<'db>> { - let size = || self.db.layout_of_ty(ty, self.env.clone()).map(|it| it.size.bytes_usize()); + let size = || { + self.db + .layout_of_ty(ty, ParamEnvAndCrate { param_env: self.env, krate: self.krate() }) + .map(|it| it.size.bytes_usize()) + }; const USIZE_SIZE: usize = size_of::<usize>(); let bytes: Box<[_]> = match l { hir_def::hir::Literal::String(b) => { @@ -1799,7 +1803,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { &self.infcx, self.infer[expr_id], self.owner.module(self.db), - self.env.clone(), + self.env, ) } @@ -2070,7 +2074,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { span: MirSpan, ) { for &l in scope.locals.iter().rev() { - if !self.infcx.type_is_copy_modulo_regions(self.env.env, self.result.locals[l].ty) { + if !self.infcx.type_is_copy_modulo_regions(self.env, self.result.locals[l].ty) { let prev = std::mem::replace(current, self.new_basic_block()); self.set_terminator( prev, diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs index 1f73d5cd31..b67365c344 100644 --- a/crates/hir-ty/src/mir/monomorphization.rs +++ b/crates/hir-ty/src/mir/monomorphization.rs @@ -14,9 +14,11 @@ use rustc_type_ir::{ }; use triomphe::Arc; -use crate::next_solver::{Const, ConstKind, Region, RegionKind}; use crate::{ - TraitEnvironment, + ParamEnvAndCrate, + next_solver::{Const, ConstKind, Region, RegionKind}, +}; +use crate::{ db::{HirDatabase, InternedClosureId}, next_solver::{ DbInterner, GenericArgs, Ty, TyKind, TypingMode, @@ -30,7 +32,7 @@ use super::{MirBody, MirLowerError, Operand, OperandKind, Rvalue, StatementKind, struct Filler<'db> { infcx: InferCtxt<'db>, - trait_env: Arc<TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, subst: GenericArgs<'db>, } @@ -53,7 +55,11 @@ impl<'db> FallibleTypeFolder<DbInterner<'db>> for Filler<'db> { let mut ocx = ObligationCtxt::new(&self.infcx); let ty = ocx - .structurally_normalize_ty(&ObligationCause::dummy(), self.trait_env.env, ty) + .structurally_normalize_ty( + &ObligationCause::dummy(), + self.trait_env.param_env, + ty, + ) .map_err(|_| MirLowerError::NotSupported("can't normalize alias".to_owned()))?; ty.try_super_fold_with(self) } @@ -93,11 +99,7 @@ impl<'db> FallibleTypeFolder<DbInterner<'db>> for Filler<'db> { } impl<'db> Filler<'db> { - fn new( - db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, - subst: GenericArgs<'db>, - ) -> Self { + fn new(db: &'db dyn HirDatabase, env: ParamEnvAndCrate<'db>, subst: GenericArgs<'db>) -> Self { let interner = DbInterner::new_with(db, env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); Self { infcx, trait_env: env, subst } @@ -210,7 +212,7 @@ pub fn monomorphized_mir_body_query<'db>( db: &'db dyn HirDatabase, owner: DefWithBodyId, subst: GenericArgs<'db>, - trait_env: Arc<crate::TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { let mut filler = Filler::new(db, trait_env, subst); let body = db.mir_body(owner)?; @@ -223,7 +225,7 @@ pub(crate) fn monomorphized_mir_body_cycle_result<'db>( _db: &'db dyn HirDatabase, _: DefWithBodyId, _: GenericArgs<'db>, - _: Arc<crate::TraitEnvironment<'db>>, + _: ParamEnvAndCrate<'db>, ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { Err(MirLowerError::Loop) } @@ -232,7 +234,7 @@ pub fn monomorphized_mir_body_for_closure_query<'db>( db: &'db dyn HirDatabase, closure: InternedClosureId, subst: GenericArgs<'db>, - trait_env: Arc<crate::TraitEnvironment<'db>>, + trait_env: ParamEnvAndCrate<'db>, ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { let mut filler = Filler::new(db, trait_env, subst); let body = db.mir_body_for_closure(closure)?; diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs index 443191423a..14b8a61088 100644 --- a/crates/hir-ty/src/next_solver/infer/mod.rs +++ b/crates/hir-ty/src/next_solver/infer/mod.rs @@ -402,7 +402,7 @@ impl<'db> InferCtxt<'db> { self.evaluate_obligation(obligation).may_apply() } - /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank) + /// See the comment on `GeneralAutoderef::overloaded_deref_ty` /// for more details. pub fn predicate_may_hold_opaque_types_jank( &self, @@ -532,7 +532,7 @@ impl<'db> InferCtxt<'db> { }) } - /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank) + /// See the comment on `GeneralAutoderef::overloaded_deref_ty` /// for more details. pub fn goal_may_hold_opaque_types_jank(&self, goal: Goal<'db, Predicate<'db>>) -> bool { <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(goal) diff --git a/crates/hir-ty/src/next_solver/predicate.rs b/crates/hir-ty/src/next_solver/predicate.rs index 7cc3af748a..783966ee1e 100644 --- a/crates/hir-ty/src/next_solver/predicate.rs +++ b/crates/hir-ty/src/next_solver/predicate.rs @@ -427,6 +427,10 @@ impl<'db> ParamEnv<'db> { pub fn empty() -> Self { ParamEnv { clauses: Clauses::new_from_iter(DbInterner::conjure(), []) } } + + pub fn clauses(self) -> Clauses<'db> { + self.clauses + } } impl<'db> rustc_type_ir::inherent::ParamEnv<DbInterner<'db>> for ParamEnv<'db> { diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs index 0b84ce13a3..dbac20074b 100644 --- a/crates/hir-ty/src/opaques.rs +++ b/crates/hir-ty/src/opaques.rs @@ -122,7 +122,7 @@ pub(crate) fn tait_hidden_types<'db>( let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); let mut ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); - let param_env = db.trait_environment(type_alias.into()).env; + let param_env = db.trait_environment(type_alias.into()); let defining_bodies = tait_defining_bodies(db, &loc); diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs index 0241751e82..495a9937f6 100644 --- a/crates/hir-ty/src/specialization.rs +++ b/crates/hir-ty/src/specialization.rs @@ -1,6 +1,6 @@ //! Impl specialization related things -use hir_def::{ImplId, nameres::crate_def_map}; +use hir_def::{HasModule, ImplId, nameres::crate_def_map}; use intern::sym; use rustc_type_ir::inherent::SliceLike; use tracing::debug; @@ -46,7 +46,7 @@ fn specializes_query( parent_impl_def_id: ImplId, ) -> bool { let trait_env = db.trait_environment(specializing_impl_def_id.into()); - let interner = DbInterner::new_with(db, trait_env.krate); + let interner = DbInterner::new_with(db, specializing_impl_def_id.krate(db)); let specializing_impl_signature = db.impl_signature(specializing_impl_def_id); let parent_impl_signature = db.impl_signature(parent_impl_def_id); @@ -70,7 +70,7 @@ fn specializes_query( // create a parameter environment corresponding to an identity instantiation of the specializing impl, // i.e. the most generic instantiation of the specializing impl. - let param_env = trait_env.env; + let param_env = trait_env; // Create an infcx, taking the predicates of the specializing impl as assumptions: let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index 1462f1e317..b1a2802264 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -4,7 +4,7 @@ use std::hash::Hash; use base_db::Crate; use hir_def::{ - AdtId, AssocItemId, BlockId, HasModule, ImplId, Lookup, TraitId, + AdtId, AssocItemId, HasModule, ImplId, Lookup, TraitId, lang_item::LangItems, nameres::DefMap, signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags}, @@ -17,7 +17,6 @@ use rustc_type_ir::{ inherent::{AdtDef, BoundExistentialPredicates, IntoKind, Span as _}, solve::Certainty, }; -use triomphe::Arc; use crate::{ db::HirDatabase, @@ -29,60 +28,22 @@ use crate::{ }, }; -/// A set of clauses that we assume to be true. E.g. if we are inside this function: -/// ```rust -/// fn foo<T: Default>(t: T) {} -/// ``` -/// we assume that `T: Default`. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TraitEnvironment<'db> { +/// Type for `hir`, because commonly we want both param env and a crate in an exported API. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ParamEnvAndCrate<'db> { + pub param_env: ParamEnv<'db>, pub krate: Crate, - pub block: Option<BlockId>, - // FIXME make this a BTreeMap - traits_from_clauses: Box<[(Ty<'db>, TraitId)]>, - pub env: ParamEnv<'db>, -} - -impl<'db> TraitEnvironment<'db> { - pub fn empty(krate: Crate) -> Arc<Self> { - Arc::new(TraitEnvironment { - krate, - block: None, - traits_from_clauses: Box::default(), - env: ParamEnv::empty(), - }) - } - - pub fn new( - krate: Crate, - block: Option<BlockId>, - traits_from_clauses: Box<[(Ty<'db>, TraitId)]>, - env: ParamEnv<'db>, - ) -> Arc<Self> { - Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env }) - } - - // pub fn with_block(self: &mut Arc<Self>, block: BlockId) { - pub fn with_block(this: &mut Arc<Self>, block: BlockId) { - Arc::make_mut(this).block = Some(block); - } - - pub fn traits_in_scope_from_clauses(&self, ty: Ty<'db>) -> impl Iterator<Item = TraitId> + '_ { - self.traits_from_clauses - .iter() - .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) - } } /// This should be used in `hir` only. pub fn structurally_normalize_ty<'db>( infcx: &InferCtxt<'db>, ty: Ty<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnv<'db>, ) -> Ty<'db> { let TyKind::Alias(..) = ty.kind() else { return ty }; let mut ocx = ObligationCtxt::new(infcx); - let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); + let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, ty).unwrap_or(ty); ty.replace_infer_with_error(infcx.interner) } @@ -192,7 +153,7 @@ impl FnTrait { pub fn implements_trait_unique<'db>( ty: Ty<'db>, db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, trait_: TraitId, ) -> bool { implements_trait_unique_impl(db, env, trait_, &mut |infcx| { @@ -203,7 +164,7 @@ pub fn implements_trait_unique<'db>( /// This should not be used in `hir-ty`, only in `hir`. pub fn implements_trait_unique_with_args<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, trait_: TraitId, args: GenericArgs<'db>, ) -> bool { @@ -212,7 +173,7 @@ pub fn implements_trait_unique_with_args<'db>( fn implements_trait_unique_impl<'db>( db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, trait_: TraitId, create_args: &mut dyn FnMut(&InferCtxt<'db>) -> GenericArgs<'db>, ) -> bool { @@ -222,7 +183,7 @@ fn implements_trait_unique_impl<'db>( let args = create_args(&infcx); let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args); - let goal = Goal::new(interner, env.env, trait_ref); + let goal = Goal::new(interner, env.param_env, trait_ref); let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal); matches!(result, Ok((_, Certainty::Yes))) diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 5e716c6df1..2f412d88ab 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -412,9 +412,7 @@ fn resolve_impl_trait_item<'db>( ns: Option<Namespace>, ) -> Option<DocLinkDef> { let krate = ty.krate(db); - let environment = resolver - .generic_def() - .map_or_else(|| crate::TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); + let environment = crate::param_env_from_resolver(db, &resolver); let traits_in_scope = resolver.traits_in_scope(db); // `ty.iterate_path_candidates()` require a scope, which is not available when resolving @@ -428,7 +426,7 @@ fn resolve_impl_trait_item<'db>( let ctx = MethodResolutionContext { infcx: &infcx, resolver: &resolver, - env: &environment, + param_env: environment.param_env, traits_in_scope: &traits_in_scope, edition: krate.edition(db), unstable_features: &unstable_features, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 10a1fa12e0..07e61a83c4 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -13,7 +13,7 @@ use hir_ty::{ GenericPredicates, db::HirDatabase, display::{ - HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault, + HirDisplay, HirDisplayWithExpressionStore, HirFormatter, Result, SizedByDefault, hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility, }, next_solver::ClauseKind, @@ -29,7 +29,7 @@ use crate::{ }; impl<'db> HirDisplay<'db> for Function { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let db = f.db; let data = db.function_signature(self.id); let container = self.as_assoc_item(db).map(|it| it.container(db)); @@ -185,10 +185,7 @@ impl<'db> HirDisplay<'db> for Function { } } -fn write_impl_header<'db>( - impl_: &Impl, - f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +fn write_impl_header<'db>(impl_: &Impl, f: &mut HirFormatter<'_, 'db>) -> Result { let db = f.db; f.write_str("impl")?; @@ -207,7 +204,7 @@ fn write_impl_header<'db>( } impl<'db> HirDisplay<'db> for SelfParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let data = f.db.function_signature(self.func); let param = *data.params.first().unwrap(); match &data.store[param] { @@ -233,7 +230,7 @@ impl<'db> HirDisplay<'db> for SelfParam { } impl<'db> HirDisplay<'db> for Adt { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self { Adt::Struct(it) => it.hir_fmt(f), Adt::Union(it) => it.hir_fmt(f), @@ -243,7 +240,7 @@ impl<'db> HirDisplay<'db> for Adt { } impl<'db> HirDisplay<'db> for Struct { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let module_id = self.module(f.db).id; // FIXME: Render repr if its set explicitly? write_visibility(module_id, self.visibility(f.db), f)?; @@ -284,7 +281,7 @@ impl<'db> HirDisplay<'db> for Struct { } impl<'db> HirDisplay<'db> for Enum { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; f.write_str("enum ")?; write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?; @@ -301,7 +298,7 @@ impl<'db> HirDisplay<'db> for Enum { } impl<'db> HirDisplay<'db> for Union { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; f.write_str("union ")?; write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?; @@ -322,7 +319,7 @@ fn write_fields<'db>( limit: usize, in_line: bool, f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +) -> Result { let count = fields.len().min(limit); let (indent, separator) = if in_line { ("", ' ') } else { (" ", '\n') }; f.write_char(if !has_where_clause { ' ' } else { separator })?; @@ -355,7 +352,7 @@ fn write_variants<'db>( has_where_clause: bool, limit: usize, f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +) -> Result { let count = variants.len().min(limit); f.write_char(if !has_where_clause { ' ' } else { '\n' })?; if count == 0 { @@ -391,7 +388,7 @@ fn write_variants<'db>( } impl<'db> HirDisplay<'db> for Field { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?; write!(f, "{}: ", self.name(f.db).display(f.db, f.edition()))?; self.ty(f.db).hir_fmt(f) @@ -399,14 +396,14 @@ impl<'db> HirDisplay<'db> for Field { } impl<'db> HirDisplay<'db> for TupleField { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write!(f, "pub {}: ", self.name().display(f.db, f.edition()))?; self.ty(f.db).hir_fmt(f) } } impl<'db> HirDisplay<'db> for Variant { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?; let data = self.id.fields(f.db); match data.shape { @@ -436,19 +433,19 @@ impl<'db> HirDisplay<'db> for Variant { } impl<'db> HirDisplay<'db> for Type<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { self.ty.hir_fmt(f) } } impl<'db> HirDisplay<'db> for TypeNs<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { self.ty.hir_fmt(f) } } impl<'db> HirDisplay<'db> for ExternCrateDecl { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; f.write_str("extern crate ")?; write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?; @@ -460,7 +457,7 @@ impl<'db> HirDisplay<'db> for ExternCrateDecl { } impl<'db> HirDisplay<'db> for GenericParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self { GenericParam::TypeParam(it) => it.hir_fmt(f), GenericParam::ConstParam(it) => it.hir_fmt(f), @@ -470,7 +467,7 @@ impl<'db> HirDisplay<'db> for GenericParam { } impl<'db> HirDisplay<'db> for TypeOrConstParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.split(f.db) { either::Either::Left(it) => it.hir_fmt(f), either::Either::Right(it) => it.hir_fmt(f), @@ -479,7 +476,7 @@ impl<'db> HirDisplay<'db> for TypeOrConstParam { } impl<'db> HirDisplay<'db> for TypeParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let params = f.db.generic_params(self.id.parent()); let param_data = ¶ms[self.id.local_id()]; let krate = self.id.parent().krate(f.db).id; @@ -541,22 +538,19 @@ impl<'db> HirDisplay<'db> for TypeParam { } impl<'db> HirDisplay<'db> for LifetimeParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write!(f, "{}", self.name(f.db).display(f.db, f.edition())) } } impl<'db> HirDisplay<'db> for ConstParam { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write!(f, "const {}: ", self.name(f.db).display(f.db, f.edition()))?; self.ty(f.db).hir_fmt(f) } } -fn write_generic_params<'db>( - def: GenericDefId, - f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +fn write_generic_params<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result { let (params, store) = f.db.generic_params_and_store(def); if params.iter_lt().next().is_none() && params.iter_type_or_consts().all(|it| it.1.const_param().is_none()) @@ -614,10 +608,7 @@ fn write_generic_params<'db>( Ok(()) } -fn write_where_clause<'db>( - def: GenericDefId, - f: &mut HirFormatter<'_, 'db>, -) -> Result<bool, HirDisplayError> { +fn write_where_clause<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result<bool> { let (params, store) = f.db.generic_params_and_store(def); if !has_disaplayable_predicates(f.db, ¶ms, &store) { return Ok(false); @@ -649,7 +640,7 @@ fn write_where_predicates<'db>( params: &GenericParams, store: &ExpressionStore, f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +) -> Result { use WherePredicate::*; // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`. @@ -710,7 +701,7 @@ fn write_where_predicates<'db>( } impl<'db> HirDisplay<'db> for Const { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { let db = f.db; let container = self.as_assoc_item(db).map(|it| it.container(db)); let mut module = self.module(db); @@ -731,7 +722,7 @@ impl<'db> HirDisplay<'db> for Const { } impl<'db> HirDisplay<'db> for Static { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; let data = f.db.static_signature(self.id); f.write_str("static ")?; @@ -745,13 +736,13 @@ impl<'db> HirDisplay<'db> for Static { } impl<'db> HirDisplay<'db> for TraitRef<'db> { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { self.trait_ref.hir_fmt(f) } } impl<'db> HirDisplay<'db> for Trait { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { // FIXME(trait-alias) needs special handling to print the equal sign write_trait_header(self, f)?; let def_id = GenericDefId::TraitId(self.id); @@ -790,10 +781,7 @@ impl<'db> HirDisplay<'db> for Trait { } } -fn write_trait_header<'db>( - trait_: &Trait, - f: &mut HirFormatter<'_, 'db>, -) -> Result<(), HirDisplayError> { +fn write_trait_header<'db>(trait_: &Trait, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?; let data = f.db.trait_signature(trait_.id); if data.flags.contains(TraitFlags::UNSAFE) { @@ -808,7 +796,7 @@ fn write_trait_header<'db>( } impl<'db> HirDisplay<'db> for TypeAlias { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; let data = f.db.type_alias_signature(self.id); write!(f, "type {}", data.name.display(f.db, f.edition()))?; @@ -831,7 +819,7 @@ impl<'db> HirDisplay<'db> for TypeAlias { } impl<'db> HirDisplay<'db> for Module { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.parent(f.db) { Some(m) => write_visibility(m.id, self.visibility(f.db), f)?, None => { @@ -849,7 +837,7 @@ impl<'db> HirDisplay<'db> for Module { } impl<'db> HirDisplay<'db> for Crate { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.display_name(f.db) { Some(name) => write!(f, "extern crate {name}"), None => f.write_str("extern crate {unknown}"), @@ -858,7 +846,7 @@ impl<'db> HirDisplay<'db> for Crate { } impl<'db> HirDisplay<'db> for Macro { - fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> { + fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result { match self.id { hir_def::MacroId::Macro2Id(_) => f.write_str("macro"), hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"), diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 6f427d728b..9ea1456a41 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -20,7 +20,7 @@ use crate::{ pub trait HasSource { type Ast; /// Fetches the definition's source node. - /// Using [`crate::Semantics::source`] is preferred when working with [`crate::Semantics`], + /// Using [`crate::SemanticsImpl::source`] is preferred when working with [`crate::Semantics`], /// as that caches the parsed file in the semantics' cache. /// /// The current some implementations can return `InFile` instead of `Option<InFile>`. diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 2146e4db77..2210bb79cd 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -76,7 +76,7 @@ use hir_expand::{ AstId, MacroCallKind, RenderedExpandError, ValueResult, proc_macro::ProcMacroKind, }; use hir_ty::{ - GenericPredicates, InferenceResult, TraitEnvironment, TyDefId, TyLoweringDiagnostic, + GenericPredicates, InferenceResult, ParamEnvAndCrate, TyDefId, TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, check_orphan_rules, consteval::try_const_usize, db::{InternedClosureId, InternedCoroutineId}, @@ -89,7 +89,7 @@ use hir_ty::{ mir::{MutBorrowKind, interpret_mir}, next_solver::{ AliasTy, ClauseKind, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, - PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode, + ParamEnv, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode, infer::{DbInternerInferExt, InferCtxt}, }, traits::{self, is_inherent_impl_coherent, structurally_normalize_ty}, @@ -1245,7 +1245,7 @@ impl TupleField { .get(self.index as usize) .copied() .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)); - Type { env: db.trait_environment_for_body(self.owner), ty } + Type { env: body_param_env_from_has_crate(db, self.owner), ty } } } @@ -1322,13 +1322,16 @@ impl Field { pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { db.layout_of_ty( self.ty(db).ty, - db.trait_environment(match hir_def::VariantId::from(self.parent) { - hir_def::VariantId::EnumVariantId(id) => { - GenericDefId::AdtId(id.lookup(db).parent.into()) - } - hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()), - hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()), - }), + param_env_from_has_crate( + db, + match hir_def::VariantId::from(self.parent) { + hir_def::VariantId::EnumVariantId(id) => { + GenericDefId::AdtId(id.lookup(db).parent.into()) + } + hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()), + hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()), + }, + ), ) .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap())) } @@ -1745,13 +1748,12 @@ impl Adt { } pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { - let env = db.trait_environment(self.into()); 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, _| { GenericArg::error_from_id(interner, id) }); - db.layout_of_adt(adt_id, args, env) + db.layout_of_adt(adt_id, args, param_env_from_has_crate(db, adt_id)) .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) } @@ -2276,7 +2278,7 @@ impl Function { } pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> { - let environment = db.trait_environment(self.id.into()); + let environment = param_env_from_has_crate(db, self.id); // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); @@ -2285,7 +2287,7 @@ impl Function { .iter() .enumerate() .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty }; + let ty = Type { env: environment, ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2301,7 +2303,7 @@ impl Function { } pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> { - let environment = db.trait_environment(self.id.into()); + let environment = param_env_from_has_crate(db, self.id); // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); @@ -2312,7 +2314,7 @@ impl Function { .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty }; + let ty = Type { env: environment, ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2324,7 +2326,7 @@ impl Function { db: &'db dyn HirDatabase, generics: impl Iterator<Item = Type<'db>>, ) -> Vec<Param<'db>> { - let environment = db.trait_environment(self.id.into()); + let environment = param_env_from_has_crate(db, self.id); let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); let callable_sig = @@ -2336,7 +2338,7 @@ impl Function { .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { env: environment.clone(), ty }; + let ty = Type { env: environment, ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2471,7 +2473,10 @@ impl Function { let body = db.monomorphized_mir_body( self.id.into(), GenericArgs::new_from_iter(interner, []), - db.trait_environment(self.id.into()), + ParamEnvAndCrate { + param_env: db.trait_environment(self.id.into()), + krate: self.id.module(db).krate(), + }, )?; let (result, output) = interpret_mir(db, body, false, None)?; let mut text = match result { @@ -2613,7 +2618,7 @@ impl SelfParam { // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let callable_sig = db.callable_item_signature(self.func.into()).instantiate_identity().skip_binder(); - let environment = db.trait_environment(self.func.into()); + let environment = param_env_from_has_crate(db, self.func); let ty = callable_sig.inputs().as_slice()[0]; Type { env: environment, ty } } @@ -2628,7 +2633,7 @@ impl SelfParam { let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty)); let callable_sig = db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder(); - let environment = db.trait_environment(self.func.into()); + let environment = param_env_from_has_crate(db, self.func); let ty = callable_sig.inputs().as_slice()[0]; Type { env: environment, ty } } @@ -3687,11 +3692,11 @@ impl GenericDef { pub struct GenericSubstitution<'db> { def: GenericDefId, subst: GenericArgs<'db>, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, } impl<'db> GenericSubstitution<'db> { - fn new(def: GenericDefId, subst: GenericArgs<'db>, env: Arc<TraitEnvironment<'db>>) -> Self { + fn new(def: GenericDefId, subst: GenericArgs<'db>, env: ParamEnvAndCrate<'db>) -> Self { Self { def, subst, env } } @@ -3737,9 +3742,7 @@ impl<'db> GenericSubstitution<'db> { .zip(type_params); container_params .chain(self_params) - .filter_map(|(ty, name)| { - Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) - }) + .filter_map(|(ty, name)| Some((name?.symbol().clone(), Type { ty, env: self.env }))) .collect() } } @@ -4459,7 +4462,7 @@ impl Impl { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TraitRef<'db> { - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, trait_ref: hir_ty::next_solver::TraitRef<'db>, } @@ -4469,9 +4472,7 @@ impl<'db> TraitRef<'db> { resolver: &Resolver<'_>, trait_ref: hir_ty::next_solver::TraitRef<'db>, ) -> Self { - let env = resolver - .generic_def() - .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); + let env = param_env_from_resolver(db, resolver); TraitRef { env, trait_ref } } @@ -4481,7 +4482,7 @@ impl<'db> TraitRef<'db> { pub fn self_ty(&self) -> TypeNs<'_> { let ty = self.trait_ref.self_ty(); - TypeNs { env: self.env.clone(), ty } + TypeNs { env: self.env, ty } } /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the @@ -4492,7 +4493,7 @@ impl<'db> TraitRef<'db> { .as_slice() .get(idx) .and_then(|arg| arg.ty()) - .map(|ty| TypeNs { env: self.env.clone(), ty }) + .map(|ty| TypeNs { env: self.env, ty }) } } @@ -4556,11 +4557,8 @@ impl<'db> Closure<'db> { let owner = db.lookup_intern_closure(id).0; let infer = InferenceResult::for_body(db, owner); let (captures, _) = infer.closure_info(id); - let env = db.trait_environment_for_body(owner); - captures - .iter() - .map(|capture| Type { env: env.clone(), ty: capture.ty(db, self.subst) }) - .collect() + let env = body_param_env_from_has_crate(db, owner); + captures.iter().map(|capture| Type { env, ty: capture.ty(db, self.subst) }).collect() } pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait { @@ -4768,7 +4766,7 @@ impl CaptureUsageSource { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Type<'db> { - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ty: Ty<'db>, } @@ -4786,21 +4784,17 @@ impl<'db> Type<'db> { resolver: &Resolver<'_>, ty: Ty<'db>, ) -> Self { - let environment = resolver - .generic_def() - .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); + let environment = param_env_from_resolver(db, resolver); Type { env: environment, ty } } pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty<'db>) -> Self { - Type { env: TraitEnvironment::empty(krate), ty } + Type { env: empty_param_env(krate), ty } } fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { let resolver = lexical_env.resolver(db); - let environment = resolver - .generic_def() - .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); + let environment = param_env_from_resolver(db, &resolver); Type { env: environment, ty } } @@ -4856,7 +4850,7 @@ impl<'db> Type<'db> { pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self { let tys = tys.iter().map(|it| it.ty); let interner = DbInterner::conjure(); - Type { env: TraitEnvironment::empty(krate), ty: Ty::new_tup_from_iter(interner, tys) } + Type { env: empty_param_env(krate), ty: Ty::new_tup_from_iter(interner, tys) } } pub fn is_unit(&self) -> bool { @@ -5046,7 +5040,7 @@ impl<'db> Type<'db> { }) .or(lang_items.Future)?; - if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { + if !traits::implements_trait_unique(self.ty, db, self.env, trait_) { return None; } @@ -5077,7 +5071,7 @@ impl<'db> Type<'db> { let Some(iterator_trait) = lang_items.Iterator else { return false; }; - traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait) + traits::implements_trait_unique(self.ty, db, self.env, iterator_trait) } /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type @@ -5089,7 +5083,7 @@ impl<'db> Type<'db> { Some(into_iter_trait.id) })?; - if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { + if !traits::implements_trait_unique(self.ty, db, self.env, trait_) { return None; } @@ -5110,7 +5104,7 @@ impl<'db> Type<'db> { None => return false, }; - traits::implements_trait_unique(self.ty, db, self.env.clone(), fnonce_trait) + traits::implements_trait_unique(self.ty, db, self.env, fnonce_trait) } // FIXME: Find better API that also handles const generics @@ -5121,7 +5115,7 @@ impl<'db> Type<'db> { trait_.id.into(), std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)), ); - traits::implements_trait_unique_with_args(db, self.env.clone(), trait_.id, args) + traits::implements_trait_unique_with_args(db, self.env, trait_.id, args) } pub fn normalize_trait_assoc_type( @@ -5144,7 +5138,7 @@ impl<'db> Type<'db> { ); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); - let ty = structurally_normalize_ty(&infcx, projection, self.env.clone()); + let ty = structurally_normalize_ty(&infcx, projection, self.env.param_env); if ty.is_ty_error() { None } else { Some(self.derived(ty)) } } @@ -5166,8 +5160,7 @@ impl<'db> Type<'db> { // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db), _ => { - let (fn_trait, sig) = - hir_ty::callable_sig_from_fn_trait(self.ty, self.env.clone(), db)?; + let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(self.ty, self.env, db)?; return Some(Callable { ty: self.clone(), sig, @@ -5291,7 +5284,7 @@ impl<'db> Type<'db> { let interner = DbInterner::new_no_crate(db); // There should be no inference vars in types passed here let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); - autoderef(db, self.env.clone(), canonical) + autoderef(db, self.env, canonical) } // This would be nicer if it just returned an iterator, but that runs into @@ -5477,13 +5470,11 @@ impl<'db> Type<'db> { let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let unstable_features = MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map()); - let environment = resolver - .generic_def() - .map_or_else(|| TraitEnvironment::empty(module.krate()), |d| db.trait_environment(d)); + let environment = param_env_from_resolver(db, resolver); let ctx = MethodResolutionContext { infcx: &infcx, resolver, - env: &environment, + param_env: environment.param_env, traits_in_scope, edition: resolver.krate().data(db).edition, unstable_features: &unstable_features, @@ -5704,7 +5695,13 @@ impl<'db> Type<'db> { .filter(|ty| matches!(ty.kind(), TyKind::Param(_))) .flat_map(|ty| { self.env - .traits_in_scope_from_clauses(ty) + .param_env + .clauses() + .iter() + .filter_map(move |pred| match pred.kind().skip_binder() { + ClauseKind::Trait(tr) if tr.self_ty() == ty => Some(tr.def_id().0), + _ => None, + }) .flat_map(|t| hir_ty::all_super_traits(db, t)) }) .map(Trait::from) @@ -5728,7 +5725,7 @@ impl<'db> Type<'db> { } fn derived(&self, ty: Ty<'db>) -> Self { - Type { env: self.env.clone(), ty } + Type { env: self.env, ty } } /// Visits every type, including generic arguments, in this type. `callback` is called with type @@ -5736,7 +5733,7 @@ impl<'db> Type<'db> { pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) { struct Visitor<'db, F> { db: &'db dyn HirDatabase, - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, callback: F, visited: FxHashSet<Ty<'db>>, } @@ -5751,7 +5748,7 @@ impl<'db> Type<'db> { return; } - (self.callback)(Type { env: self.env.clone(), ty }); + (self.callback)(Type { env: self.env, ty }); if let Some(bounds) = ty.impl_trait_bounds(self.db) { bounds.visit_with(self); @@ -5761,8 +5758,7 @@ impl<'db> Type<'db> { } } - let mut visitor = - Visitor { db, env: self.env.clone(), callback, visited: FxHashSet::default() }; + let mut visitor = Visitor { db, env: self.env, callback, visited: FxHashSet::default() }; self.ty.visit_with(&mut visitor); } /// Check if type unifies with another type. @@ -5772,7 +5768,7 @@ impl<'db> Type<'db> { pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); - hir_ty::could_unify(db, self.env.clone(), &tys) + hir_ty::could_unify(db, self.env, &tys) } /// Check if type unifies with another type eagerly making sure there are no unresolved goals. @@ -5782,13 +5778,13 @@ impl<'db> Type<'db> { pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); - hir_ty::could_unify_deeply(db, self.env.clone(), &tys) + hir_ty::could_unify_deeply(db, self.env, &tys) } pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool { let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty)); - hir_ty::could_coerce(db, self.env.clone(), &tys) + hir_ty::could_coerce(db, self.env, &tys) } pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> { @@ -5807,34 +5803,32 @@ impl<'db> Type<'db> { } pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> { - db.layout_of_ty(self.ty, self.env.clone()) + db.layout_of_ty(self.ty, self.env) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue { let interner = DbInterner::new_with(db, self.env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); - hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone()) + hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.param_env) } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeNs<'db> { - env: Arc<TraitEnvironment<'db>>, + env: ParamEnvAndCrate<'db>, ty: Ty<'db>, } impl<'db> TypeNs<'db> { fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { let resolver = lexical_env.resolver(db); - let environment = resolver - .generic_def() - .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); + let environment = param_env_from_resolver(db, &resolver); TypeNs { env: environment, ty } } pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> { - Type { env: self.env.clone(), ty: self.ty } + Type { env: self.env, ty: self.ty } } // FIXME: Find better API that also handles const generics @@ -6546,5 +6540,35 @@ fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) }) } +fn param_env_from_resolver<'db>( + db: &'db dyn HirDatabase, + resolver: &Resolver<'_>, +) -> ParamEnvAndCrate<'db> { + ParamEnvAndCrate { + param_env: resolver + .generic_def() + .map_or_else(ParamEnv::empty, |generic_def| db.trait_environment(generic_def)), + krate: resolver.krate(), + } +} + +fn param_env_from_has_crate<'db>( + db: &'db dyn HirDatabase, + id: impl hir_def::HasModule + Into<GenericDefId> + Copy, +) -> ParamEnvAndCrate<'db> { + ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) } +} + +fn body_param_env_from_has_crate<'db>( + db: &'db dyn HirDatabase, + id: impl hir_def::HasModule + Into<DefWithBodyId> + Copy, +) -> ParamEnvAndCrate<'db> { + ParamEnvAndCrate { param_env: db.trait_environment_for_body(id.into()), krate: id.krate(db) } +} + +fn empty_param_env<'db>(krate: base_db::Crate) -> ParamEnvAndCrate<'db> { + ParamEnvAndCrate { param_env: ParamEnv::empty(), krate } +} + pub use hir_ty::next_solver; pub use hir_ty::setup_tracing; diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 8144b2f737..901c9e1575 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -29,7 +29,7 @@ use hir_expand::{ name::{AsName, Name}, }; use hir_ty::{ - Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext, + Adjustment, InferenceResult, LifetimeElisionKind, ParamEnvAndCrate, TyLoweringContext, diagnostics::{ InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, @@ -37,7 +37,8 @@ use hir_ty::{ lang_items::lang_items_for_bin_op, method_resolution::{self, CandidateId}, next_solver::{ - DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt, + DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode, + infer::DbInternerInferExt, }, traits::structurally_normalize_ty, }; @@ -227,10 +228,15 @@ impl<'db> SourceAnalyzer<'db> { }) } - fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment<'db>> { - self.body_().map(|(def, ..)| def).map_or_else( - || TraitEnvironment::empty(self.resolver.krate()), - |def| db.trait_environment_for_body(def), + fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> { + ParamEnvAndCrate { param_env, krate: self.resolver.krate() } + } + + fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { + self.param_and( + self.body_() + .map(|(def, ..)| def) + .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)), ) } @@ -827,7 +833,7 @@ impl<'db> SourceAnalyzer<'db> { let mut container = Either::Right(container.ty); for field_name in offset_of_expr.fields() { if let Either::Right(container) = &mut container { - *container = structurally_normalize_ty(&infcx, *container, trait_env.clone()); + *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env); } let handle_variants = |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| { @@ -1412,7 +1418,7 @@ impl<'db> SourceAnalyzer<'db> { Some(it) => it, None => return (func, substs), }; - let env = db.trait_environment_for_body(owner); + let env = self.param_and(db.trait_environment_for_body(owner)); db.lookup_impl_method(env, func, substs) } @@ -1426,10 +1432,10 @@ impl<'db> SourceAnalyzer<'db> { Some(it) => it, None => return (const_id, subs), }; - let env = db.trait_environment_for_body(owner); + let env = self.param_and(db.trait_environment_for_body(owner)); let interner = DbInterner::new_with(db, env.krate); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); - method_resolution::lookup_impl_const(&infcx, env, const_id, subs) + method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs) } fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems { diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 0b5dae6bc4..16b5684c16 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -59,6 +59,8 @@ //! <https://rust-analyzer.github.io/blog/2020/09/28/how-to-make-a-light-bulb.html> #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +// It's useful to refer to code that is private in doc comments. +#![allow(rustdoc::private_intra_doc_links)] mod assist_config; mod assist_context; diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs index eab2b9063f..fbb3cde968 100644 --- a/crates/ide-completion/src/completions/keyword.rs +++ b/crates/ide-completion/src/completions/keyword.rs @@ -344,6 +344,60 @@ fn main() { } "#, ); + + check_edit( + "loop", + r#" +fn main() { + let x = &$0 + bar(); +} +"#, + r#" +fn main() { + let x = &loop { + $0 +}; + bar(); +} +"#, + ); + + check_edit( + "loop", + r#" +fn main() { + let x = -$0 + bar(); +} +"#, + r#" +fn main() { + let x = -loop { + $0 +}; + bar(); +} +"#, + ); + + check_edit( + "loop", + r#" +fn main() { + let x = 2 + $0 + bar(); +} +"#, + r#" +fn main() { + let x = 2 + loop { + $0 +}; + bar(); +} +"#, + ); } #[test] diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index e761da7152..add637a16f 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -1321,9 +1321,8 @@ fn classify_name_ref<'db>( let incomplete_expr_stmt = it.parent().and_then(ast::ExprStmt::cast).map(|it| it.semicolon_token().is_none()); let before_else_kw = before_else_kw(it); - let incomplete_let = it - .parent() - .and_then(ast::LetStmt::cast) + let incomplete_let = left_ancestors(it.parent()) + .find_map(ast::LetStmt::cast) .is_some_and(|it| it.semicolon_token().is_none()) || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw; let in_value = is_in_value(it); @@ -1882,6 +1881,13 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> { Some((use_tree.path()?, true)) } +fn left_ancestors(node: Option<SyntaxNode>) -> impl Iterator<Item = SyntaxNode> { + node.into_iter().flat_map(|node| { + let end = node.text_range().end(); + node.ancestors().take_while(move |it| it.text_range().end() == end) + }) +} + fn is_in_token_of_for_loop(path: &ast::Path) -> bool { // oh my ... (|| { diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index c526c7f070..71d32da747 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -23,7 +23,7 @@ use crate::{ /// editor pop-up. /// /// It is basically a POD with various properties. To construct a [`CompletionItem`], -/// use [`Builder::new`] method and the [`Builder`] struct. +/// use the [`Builder`] struct. #[derive(Clone, UpmapFromRaFixture)] #[non_exhaustive] pub struct CompletionItem { diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index f7a118db50..6dfa183136 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -1,5 +1,8 @@ //! `completions` crate provides utilities for generating completions of user input. +// It's useful to refer to code that is private in doc comments. +#![allow(rustdoc::private_intra_doc_links)] + mod completions; mod config; mod context; diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 3dd2c1f6c4..b15bf0cd01 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -3,9 +3,10 @@ //! NOTE: The crate is undergoing refactors, don't believe everything the docs //! say :-) //! -//! The parser doesn't know about concrete representation of tokens and syntax -//! trees. Abstract [`TokenSource`] and [`TreeSink`] traits are used instead. As -//! a consequence, this crate does not contain a lexer. +//! The parser doesn't know about concrete representation of tokens +//! and syntax trees. Abstract [`Input`] and [`Output`] traits are +//! used to provide tokens instead. As a consequence, this crate does +//! not contain a lexer. //! //! The [`Parser`] struct from the [`parser`] module is a cursor into the //! sequence of tokens. Parsing routines use [`Parser`] to inspect current diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index 2c6a82bf0c..d6d9ed4676 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs @@ -1,5 +1,5 @@ -//! Thin wrappers around [`camino::path`], distinguishing between absolute and -//! relative paths. +//! Thin wrappers around [`camino::Utf8PathBuf`], distinguishing +//! between absolute and relative paths. use std::{ borrow::Borrow, diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index 680372210a..a6e228d977 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -17,19 +17,19 @@ pub enum Request { // As such, this is the only request that needs to be supported across all protocol versions // and by keeping it first, we ensure it always has the same discriminant encoding in postcard /// Performs an API version check between the client and the server. - /// Since [`VERSION_CHECK_VERSION`] + /// Since [`crate::version::VERSION_CHECK_VERSION`] ApiVersionCheck {}, /// Retrieves a list of macros from a given dynamic library. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: Utf8PathBuf }, /// Expands a procedural macro. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ExpandMacro(Box<ExpandMacro>), /// Sets server-specific configurations. - /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), } @@ -51,23 +51,23 @@ pub enum Response { // As such, this is the only request that needs to be supported across all protocol versions // and by keeping it first, we ensure it always has the same discriminant encoding in postcard /// Returns the API version supported by the server. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ApiVersionCheck(u32), /// Returns a list of available macros in a dynamic library. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ListMacros(Result<Vec<(String, ProcMacroKind)>, String>), /// Returns result of a macro expansion. - /// Since [`NO_VERSION_CHECK_VERSION`] + /// Since [`crate::version::NO_VERSION_CHECK_VERSION`] ExpandMacro(Result<FlatTree, PanicMessage>), /// Confirms the application of a configuration update. - /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] SetConfig(ServerConfig), /// Returns the result of a macro expansion, including extended span data. - /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] + /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`] ExpandMacroExtended(Result<ExpandMacroExtended, PanicMessage>), } @@ -185,7 +185,7 @@ mod tests { use super::*; - fn fixture_token_tree() -> TopSubtree<Span> { + fn fixture_token_tree_top_many_none() -> TopSubtree<Span> { let anchor = SpanAnchor { file_id: span::EditionedFileId::new( span::FileId::from_raw(0xe4e4e), @@ -201,7 +201,7 @@ mod tests { ctx: SyntaxContext::root(Edition::CURRENT), }, close: Span { - range: TextRange::empty(TextSize::new(19)), + range: TextRange::empty(TextSize::new(0)), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }, @@ -259,10 +259,18 @@ mod tests { ctx: SyntaxContext::root(Edition::CURRENT), }, ); + builder.open( + DelimiterKind::Bracket, + Span { + range: TextRange::at(TextSize::new(15), TextSize::of('[')), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + ); builder.push(Leaf::Literal(Literal { symbol: sym::INTEGER_0, span: Span { - range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), + range: TextRange::at(TextSize::new(16), TextSize::of("0u32")), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }, @@ -270,45 +278,140 @@ mod tests { suffix: Some(sym::u32), })); builder.close(Span { - range: TextRange::at(TextSize::new(19), TextSize::of('}')), + range: TextRange::at(TextSize::new(20), TextSize::of(']')), anchor, ctx: SyntaxContext::root(Edition::CURRENT), }); + builder.close(Span { + range: TextRange::at(TextSize::new(21), TextSize::of('}')), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }); + + builder.build() + } + + fn fixture_token_tree_top_empty_none() -> TopSubtree<Span> { + let anchor = SpanAnchor { + file_id: span::EditionedFileId::new( + span::FileId::from_raw(0xe4e4e), + span::Edition::CURRENT, + ), + ast_id: ROOT_ERASED_FILE_AST_ID, + }; + + let builder = TopSubtreeBuilder::new(Delimiter { + open: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + close: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + kind: DelimiterKind::Invisible, + }); + + builder.build() + } + + fn fixture_token_tree_top_empty_brace() -> TopSubtree<Span> { + let anchor = SpanAnchor { + file_id: span::EditionedFileId::new( + span::FileId::from_raw(0xe4e4e), + span::Edition::CURRENT, + ), + ast_id: ROOT_ERASED_FILE_AST_ID, + }; + + let builder = TopSubtreeBuilder::new(Delimiter { + open: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + close: Span { + range: TextRange::empty(TextSize::new(0)), + anchor, + ctx: SyntaxContext::root(Edition::CURRENT), + }, + kind: DelimiterKind::Brace, + }); + builder.build() } #[test] fn test_proc_macro_rpc_works() { - let tt = fixture_token_tree(); - for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { - let mut span_data_table = Default::default(); - let task = ExpandMacro { - data: ExpandMacroData { - macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table), - macro_name: Default::default(), - attributes: None, - has_global_spans: ExpnGlobals { - serialize: true, - def_site: 0, - call_site: 0, - mixed_site: 0, + for tt in [ + fixture_token_tree_top_many_none, + fixture_token_tree_top_empty_none, + fixture_token_tree_top_empty_brace, + ] { + for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { + let tt = tt(); + let mut span_data_table = Default::default(); + let task = ExpandMacro { + data: ExpandMacroData { + macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table), + macro_name: Default::default(), + attributes: None, + has_global_spans: ExpnGlobals { + serialize: true, + def_site: 0, + call_site: 0, + mixed_site: 0, + }, + span_data_table: Vec::new(), }, - span_data_table: Vec::new(), - }, - lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), - env: Default::default(), - current_dir: Default::default(), - }; - - let json = serde_json::to_string(&task).unwrap(); - // println!("{}", json); - let back: ExpandMacro = serde_json::from_str(&json).unwrap(); - - assert!( - tt == back.data.macro_body.to_subtree_resolved(v, &span_data_table), - "version: {v}" - ); + lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), + env: Default::default(), + current_dir: Default::default(), + }; + + let json = serde_json::to_string(&task).unwrap(); + // println!("{}", json); + let back: ExpandMacro = serde_json::from_str(&json).unwrap(); + + assert_eq!( + tt, + back.data.macro_body.to_subtree_resolved(v, &span_data_table), + "version: {v}" + ); + } + } + } + + #[test] + #[cfg(feature = "sysroot-abi")] + fn test_proc_macro_rpc_works_ts() { + for tt in [ + fixture_token_tree_top_many_none, + fixture_token_tree_top_empty_none, + fixture_token_tree_top_empty_brace, + ] { + let tt = tt(); + for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION { + let mut span_data_table = Default::default(); + let flat_tree = FlatTree::from_subtree(tt.view(), v, &mut span_data_table); + assert_eq!( + tt, + flat_tree.clone().to_subtree_resolved(v, &span_data_table), + "version: {v}" + ); + let ts = flat_tree.to_tokenstream_resolved(v, &span_data_table, |a, b| a.cover(b)); + let call_site = *span_data_table.first().unwrap(); + let mut span_data_table = Default::default(); + assert_eq!( + tt, + FlatTree::from_tokenstream(ts.clone(), v, call_site, &mut span_data_table) + .to_subtree_resolved(v, &span_data_table), + "version: {v}, ts:\n{ts:#?}" + ); + } } } } diff --git a/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs b/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs index 92e9038554..1ac8cd4006 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs @@ -85,7 +85,7 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap { .collect() } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct FlatTree { subtree: Vec<u32>, literal: Vec<u32>, @@ -615,14 +615,17 @@ impl<'a, T: SpanTransformer> root: &'a proc_macro_srv::TokenStream<T::Span>, ) { let call_site = self.token_id_of(call_site); - self.subtree.push(SubtreeRepr { - open: call_site, - close: call_site, - kind: tt::DelimiterKind::Invisible, - tt: [!0, !0], - }); - self.work.push_back((0, root.len(), Some(root.iter()))); - + if let Some(group) = root.as_single_group() { + self.enqueue(group); + } else { + self.subtree.push(SubtreeRepr { + open: call_site, + close: call_site, + kind: tt::DelimiterKind::Invisible, + tt: [!0, !0], + }); + self.work.push_back((0, root.len(), Some(root.iter()))); + } while let Some((idx, len, group)) = self.work.pop_front() { self.group(idx, len, group); } @@ -962,6 +965,11 @@ impl<T: SpanTransformer> Reader<'_, T> { }; res[i] = Some(g); } - res[0].take().unwrap().stream.unwrap_or_default() + let group = res[0].take().unwrap(); + if group.delimiter == proc_macro_srv::Delimiter::None { + group.stream.unwrap_or_default() + } else { + TokenStream::new(vec![proc_macro_srv::TokenTree::Group(group)]) + } } } diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index c3838a8e61..93319df824 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -83,31 +83,10 @@ impl<'env> ProcMacroSrv<'env> { } pub fn join_spans(&self, first: Span, second: Span) -> Option<Span> { - // We can't modify the span range for fixup spans, those are meaningful to fixup, so just - // prefer the non-fixup span. - if first.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER { - return Some(second); - } - if second.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER { - return Some(first); - } - // FIXME: Once we can talk back to the client, implement a "long join" request for anchors - // that differ in [AstId]s as joining those spans requires resolving the AstIds. - if first.anchor != second.anchor { - return None; - } - // Differing context, we can't merge these so prefer the one that's root - if first.ctx != second.ctx { - if first.ctx.is_root() { - return Some(second); - } else if second.ctx.is_root() { - return Some(first); - } - } - Some(Span { - range: first.range.cover(second.range), - anchor: second.anchor, - ctx: second.ctx, + first.join(second, |_, _| { + // FIXME: Once we can talk back to the client, implement a "long join" request for anchors + // that differ in [AstId]s as joining those spans requires resolving the AstIds. + None }) } } diff --git a/crates/proc-macro-srv/src/token_stream.rs b/crates/proc-macro-srv/src/token_stream.rs index e134a47f8c..36827d2561 100644 --- a/crates/proc-macro-srv/src/token_stream.rs +++ b/crates/proc-macro-srv/src/token_stream.rs @@ -40,6 +40,13 @@ impl<S> TokenStream<S> { TokenStreamIter::new(self)
}
+ pub fn as_single_group(&self) -> Option<&Group<S>> {
+ match &**self.0 {
+ [TokenTree::Group(group)] => Some(group),
+ _ => None,
+ }
+ }
+
pub(crate) fn from_str(s: &str, span: S) -> Result<Self, String>
where
S: SpanLike + Copy,
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 731104981a..6e1a3f37ff 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -305,7 +305,7 @@ impl TargetKind { /// If this is a valid cargo target, returns the name cargo uses in command line arguments /// and output, otherwise None. - /// https://docs.rs/cargo_metadata/latest/cargo_metadata/enum.TargetKind.html + /// <https://docs.rs/cargo_metadata/latest/cargo_metadata/enum.TargetKind.html> pub fn as_cargo_target(self) -> Option<&'static str> { match self { TargetKind::Bin => Some("bin"), diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 910bc0a96b..8eee3d1455 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -1,7 +1,7 @@ //! In rust-analyzer, we maintain a strict separation between pure abstract //! semantic project model and a concrete model of a particular build system. //! -//! Pure model is represented by the [`base_db::CrateGraph`] from another crate. +//! Pure model is represented by the `base_db::CrateGraph` from another crate. //! //! In this crate, we are concerned with "real world" project models. //! @@ -13,7 +13,10 @@ //! * Project discovery (where's the relevant Cargo.toml for the current dir). //! * Custom build steps (`build.rs` code generation and compilation of //! procedural macros). -//! * Lowering of concrete model to a [`base_db::CrateGraph`] +//! * Lowering of concrete model to a `base_db::CrateGraph` + +// It's useful to refer to code that is private in doc comments. +#![allow(rustdoc::private_intra_doc_links)] pub mod project_json; pub mod toolchain_info { diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs index d3e1f11d78..041b9accf4 100644 --- a/crates/project-model/src/project_json.rs +++ b/crates/project-model/src/project_json.rs @@ -1,6 +1,6 @@ //! `rust-project.json` file format. //! -//! This format is spiritually a serialization of [`base_db::CrateGraph`]. The +//! This format is spiritually a serialization of `base_db::CrateGraph`. The //! idea here is that people who do not use Cargo, can instead teach their build //! system to generate `rust-project.json` which can be ingested by //! rust-analyzer. diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index e02891eca2..10abb21ace 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -1044,7 +1044,7 @@ impl ProjectWorkspace { /// Returns `true` if the project workspace is [`Json`]. /// - /// [`Json`]: ProjectWorkspace::Json + /// [`Json`]: ProjectWorkspaceKind::Json #[must_use] pub fn is_json(&self) -> bool { matches!(self.kind, ProjectWorkspaceKind::Json { .. }) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 767672fc2f..ed0b646685 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -10,8 +10,8 @@ use std::{ use cfg::{CfgAtom, CfgDiff}; use hir::{ - Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasSource, HirDisplay, ModuleDef, Name, - crate_lang_items, + Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasCrate, HasSource, HirDisplay, ModuleDef, + Name, crate_lang_items, db::{DefDatabase, ExpandDatabase, HirDatabase}, next_solver::{DbInterner, GenericArgs}, }; @@ -391,7 +391,10 @@ impl flags::AnalysisStats { let Err(e) = db.layout_of_adt( hir_def::AdtId::from(a), GenericArgs::new_from_iter(interner, []), - db.trait_environment(a.into()), + hir_ty::ParamEnvAndCrate { + param_env: db.trait_environment(a.into()), + krate: a.krate(db).into(), + }, ) else { continue; }; diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs index 41055272b1..2f052618cd 100644 --- a/crates/rust-analyzer/src/command.rs +++ b/crates/rust-analyzer/src/command.rs @@ -197,4 +197,22 @@ impl<T: Sized + Send + 'static> CommandHandle<T> { ))) } } + + pub(crate) fn has_exited(&mut self) -> bool { + match self.child.0.try_wait() { + Ok(Some(_exit_code)) => { + // We have an exit code. + true + } + Ok(None) => { + // Hasn't exited yet. + false + } + Err(_) => { + // Couldn't get an exit code. Assume that we've + // exited. + true + } + } + } } diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs index 0e96eff278..4aef5b0b7f 100644 --- a/crates/rust-analyzer/src/discover.rs +++ b/crates/rust-analyzer/src/discover.rs @@ -67,7 +67,7 @@ impl DiscoverCommand { cmd.args(args); Ok(DiscoverHandle { - _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, + handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, span: info_span!("discover_command").entered(), }) } @@ -76,7 +76,7 @@ impl DiscoverCommand { /// A handle to a spawned [Discover]. #[derive(Debug)] pub(crate) struct DiscoverHandle { - _handle: CommandHandle<DiscoverProjectMessage>, + pub(crate) handle: CommandHandle<DiscoverProjectMessage>, #[allow(dead_code)] // not accessed, but used to log on drop. span: EnteredSpan, } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 91f7db7854..7828f50844 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -45,7 +45,7 @@ use crate::{ op_queue::{Cause, OpQueue}, reload, target_spec::{CargoTargetSpec, ProjectJsonTargetSpec, TargetSpec}, - task_pool::{TaskPool, TaskQueue}, + task_pool::{DeferredTaskQueue, TaskPool}, test_runner::{CargoTestHandle, CargoTestMessage}, }; @@ -121,9 +121,10 @@ pub(crate) struct GlobalState { pub(crate) test_run_remaining_jobs: usize, // Project loading - pub(crate) discover_handle: Option<discover::DiscoverHandle>, + pub(crate) discover_handles: Vec<discover::DiscoverHandle>, pub(crate) discover_sender: Sender<discover::DiscoverProjectMessage>, pub(crate) discover_receiver: Receiver<discover::DiscoverProjectMessage>, + pub(crate) discover_jobs_active: u32, // Debouncing channel for fetching the workspace // we want to delay it until the VFS looks stable-ish (and thus is not currently in the middle @@ -175,7 +176,6 @@ pub(crate) struct GlobalState { pub(crate) fetch_build_data_queue: OpQueue<(), FetchBuildDataResponse>, pub(crate) fetch_proc_macros_queue: OpQueue<(ChangeWithProcMacros, Vec<ProcMacroPaths>), bool>, pub(crate) prime_caches_queue: OpQueue, - pub(crate) discover_workspace_queue: OpQueue, /// A deferred task queue. /// @@ -186,7 +186,8 @@ pub(crate) struct GlobalState { /// For certain features, such as [`GlobalState::handle_discover_msg`], /// this queue should run only *after* [`GlobalState::process_changes`] has /// been called. - pub(crate) deferred_task_queue: TaskQueue, + pub(crate) deferred_task_queue: DeferredTaskQueue, + /// HACK: Workaround for https://github.com/rust-lang/rust-analyzer/issues/19709 /// This is marked true if we failed to load a crate root file at crate graph creation, /// which will usually end up causing a bunch of incorrect diagnostics on startup. @@ -241,9 +242,9 @@ impl GlobalState { }; let cancellation_pool = thread::Pool::new(1); - let task_queue = { + let deferred_task_queue = { let (sender, receiver) = unbounded(); - TaskQueue { sender, receiver } + DeferredTaskQueue { sender, receiver } }; let mut analysis_host = AnalysisHost::new(config.lru_parse_query_capacity()); @@ -291,9 +292,10 @@ impl GlobalState { test_run_receiver, test_run_remaining_jobs: 0, - discover_handle: None, + discover_handles: vec![], discover_sender, discover_receiver, + discover_jobs_active: 0, fetch_ws_receiver: None, @@ -312,9 +314,8 @@ impl GlobalState { fetch_proc_macros_queue: OpQueue::default(), prime_caches_queue: OpQueue::default(), - discover_workspace_queue: OpQueue::default(), - deferred_task_queue: task_queue, + deferred_task_queue, incomplete_crate_graph: false, minicore: MiniCoreRustAnalyzerInternalOnly::default(), @@ -540,10 +541,9 @@ impl GlobalState { // didn't find anything (to make up for the lack of precision). { if !matches!(&workspace_structure_change, Some((.., true))) { - _ = self - .deferred_task_queue - .sender - .send(crate::main_loop::QueuedTask::CheckProcMacroSources(modified_rust_files)); + _ = self.deferred_task_queue.sender.send( + crate::main_loop::DeferredTask::CheckProcMacroSources(modified_rust_files), + ); } // FIXME: ideally we should only trigger a workspace fetch for non-library changes // but something's going wrong with the source root business when we add a new local diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index 87be09dcbd..4a6544508f 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -91,7 +91,7 @@ pub(crate) fn handle_did_open_text_document( let _ = state .deferred_task_queue .sender - .send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri)); + .send(crate::main_loop::DeferredTask::CheckIfIndexed(params.text_document.uri)); } } Ok(()) diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 8b4748ddb3..77dedf1272 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -74,7 +74,7 @@ pub fn main_loop(config: Config, connection: Connection) -> anyhow::Result<()> { enum Event { Lsp(lsp_server::Message), Task(Task), - QueuedTask(QueuedTask), + DeferredTask(DeferredTask), Vfs(vfs::loader::Message), Flycheck(FlycheckMessage), TestResult(CargoTestMessage), @@ -89,7 +89,7 @@ impl fmt::Display for Event { Event::Task(_) => write!(f, "Event::Task"), Event::Vfs(_) => write!(f, "Event::Vfs"), Event::Flycheck(_) => write!(f, "Event::Flycheck"), - Event::QueuedTask(_) => write!(f, "Event::QueuedTask"), + Event::DeferredTask(_) => write!(f, "Event::DeferredTask"), Event::TestResult(_) => write!(f, "Event::TestResult"), Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"), Event::FetchWorkspaces(_) => write!(f, "Event::SwitchWorkspaces"), @@ -98,7 +98,7 @@ impl fmt::Display for Event { } #[derive(Debug)] -pub(crate) enum QueuedTask { +pub(crate) enum DeferredTask { CheckIfIndexed(lsp_types::Url), CheckProcMacroSources(Vec<FileId>), } @@ -164,7 +164,7 @@ impl fmt::Debug for Event { match self { Event::Lsp(it) => fmt::Debug::fmt(it, f), Event::Task(it) => fmt::Debug::fmt(it, f), - Event::QueuedTask(it) => fmt::Debug::fmt(it, f), + Event::DeferredTask(it) => fmt::Debug::fmt(it, f), Event::Vfs(it) => fmt::Debug::fmt(it, f), Event::Flycheck(it) => fmt::Debug::fmt(it, f), Event::TestResult(it) => fmt::Debug::fmt(it, f), @@ -279,7 +279,7 @@ impl GlobalState { task.map(Event::Task), recv(self.deferred_task_queue.receiver) -> task => - task.map(Event::QueuedTask), + task.map(Event::DeferredTask), recv(self.fmt_pool.receiver) -> task => task.map(Event::Task), @@ -323,12 +323,12 @@ impl GlobalState { lsp_server::Message::Notification(not) => self.on_notification(not), lsp_server::Message::Response(resp) => self.complete_request(resp), }, - Event::QueuedTask(task) => { + Event::DeferredTask(task) => { let _p = tracing::info_span!("GlobalState::handle_event/queued_task").entered(); - self.handle_queued_task(task); - // Coalesce multiple task events into one loop turn + self.handle_deferred_task(task); + // Coalesce multiple deferred task events into one loop turn while let Ok(task) = self.deferred_task_queue.receiver.try_recv() { - self.handle_queued_task(task); + self.handle_deferred_task(task); } } Event::Task(task) => { @@ -531,6 +531,8 @@ impl GlobalState { } } + self.cleanup_discover_handles(); + if let Some(diagnostic_changes) = self.diagnostics.take_changes() { for file_id in diagnostic_changes { let uri = file_id_to_url(&self.vfs.read().0, file_id); @@ -806,33 +808,34 @@ impl GlobalState { self.report_progress("Fetching", state, msg, None, None); } Task::DiscoverLinkedProjects(arg) => { - if let Some(cfg) = self.config.discover_workspace_config() - && !self.discover_workspace_queue.op_in_progress() - { + if let Some(cfg) = self.config.discover_workspace_config() { // the clone is unfortunately necessary to avoid a borrowck error when // `self.report_progress` is called later let title = &cfg.progress_label.clone(); let command = cfg.command.clone(); let discover = DiscoverCommand::new(self.discover_sender.clone(), command); - self.report_progress(title, Progress::Begin, None, None, None); - self.discover_workspace_queue - .request_op("Discovering workspace".to_owned(), ()); - let _ = self.discover_workspace_queue.should_start_op(); + if self.discover_jobs_active == 0 { + self.report_progress(title, Progress::Begin, None, None, None); + } + self.discover_jobs_active += 1; let arg = match arg { DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it), DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it), }; - let handle = discover.spawn( - arg, - &std::env::current_dir() - .expect("Failed to get cwd during project discovery"), - ); - self.discover_handle = Some(handle.unwrap_or_else(|e| { - panic!("Failed to spawn project discovery command: {e}") - })); + let handle = discover + .spawn( + arg, + &std::env::current_dir() + .expect("Failed to get cwd during project discovery"), + ) + .unwrap_or_else(|e| { + panic!("Failed to spawn project discovery command: {e}") + }); + + self.discover_handles.push(handle); } } Task::FetchBuildData(progress) => { @@ -981,9 +984,9 @@ impl GlobalState { } } - fn handle_queued_task(&mut self, task: QueuedTask) { + fn handle_deferred_task(&mut self, task: DeferredTask) { match task { - QueuedTask::CheckIfIndexed(uri) => { + DeferredTask::CheckIfIndexed(uri) => { let snap = self.snapshot(); self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| { @@ -1007,7 +1010,7 @@ impl GlobalState { } }); } - QueuedTask::CheckProcMacroSources(modified_rust_files) => { + DeferredTask::CheckProcMacroSources(modified_rust_files) => { let analysis = AssertUnwindSafe(self.snapshot().analysis); self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, { move |sender| { @@ -1036,25 +1039,43 @@ impl GlobalState { .expect("No title could be found; this is a bug"); match message { DiscoverProjectMessage::Finished { project, buildfile } => { - self.discover_handle = None; - self.report_progress(&title, Progress::End, None, None, None); - self.discover_workspace_queue.op_completed(()); + self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1); + if self.discover_jobs_active == 0 { + self.report_progress(&title, Progress::End, None, None, None); + } let mut config = Config::clone(&*self.config); config.add_discovered_project_from_command(project, buildfile); self.update_configuration(config); } DiscoverProjectMessage::Progress { message } => { - self.report_progress(&title, Progress::Report, Some(message), None, None) + if self.discover_jobs_active > 0 { + self.report_progress(&title, Progress::Report, Some(message), None, None) + } } DiscoverProjectMessage::Error { error, source } => { - self.discover_handle = None; let message = format!("Project discovery failed: {error}"); - self.discover_workspace_queue.op_completed(()); self.show_and_log_error(message.clone(), source); - self.report_progress(&title, Progress::End, Some(message), None, None) + + self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1); + if self.discover_jobs_active == 0 { + self.report_progress(&title, Progress::End, Some(message), None, None) + } + } + } + } + + /// Drop any discover command processes that have exited, due to + /// finishing or erroring. + fn cleanup_discover_handles(&mut self) { + let mut active_handles = vec![]; + + for mut discover_handle in self.discover_handles.drain(..) { + if !discover_handle.handle.has_exited() { + active_handles.push(discover_handle); } } + self.discover_handles = active_handles; } fn handle_cargo_test_msg(&mut self, message: CargoTestMessage) { diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 8876b850be..317c112365 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -74,7 +74,7 @@ impl GlobalState { && !self.fetch_workspaces_queue.op_in_progress() && !self.fetch_build_data_queue.op_in_progress() && !self.fetch_proc_macros_queue.op_in_progress() - && !self.discover_workspace_queue.op_in_progress() + && self.discover_jobs_active == 0 && self.vfs_progress_config_version >= self.vfs_config_version } @@ -297,7 +297,7 @@ impl GlobalState { .collect(); let cargo_config = self.config.cargo(None); let discover_command = self.config.discover_workspace_config().cloned(); - let is_quiescent = !(self.discover_workspace_queue.op_in_progress() + let is_quiescent = !(self.discover_jobs_active > 0 || self.vfs_progress_config_version < self.vfs_config_version || !self.vfs_done); diff --git a/crates/rust-analyzer/src/task_pool.rs b/crates/rust-analyzer/src/task_pool.rs index c5de69bb9f..ef0feb1796 100644 --- a/crates/rust-analyzer/src/task_pool.rs +++ b/crates/rust-analyzer/src/task_pool.rs @@ -6,7 +6,7 @@ use std::panic::UnwindSafe; use crossbeam_channel::Sender; use stdx::thread::{Pool, ThreadIntent}; -use crate::main_loop::QueuedTask; +use crate::main_loop::DeferredTask; pub(crate) struct TaskPool<T> { sender: Sender<T>, @@ -45,11 +45,11 @@ impl<T> TaskPool<T> { } } -/// `TaskQueue`, like its name suggests, queues tasks. +/// `DeferredTaskQueue` holds deferred tasks. /// -/// This should only be used if a task must run after [`GlobalState::process_changes`] -/// has been called. -pub(crate) struct TaskQueue { - pub(crate) sender: crossbeam_channel::Sender<QueuedTask>, - pub(crate) receiver: crossbeam_channel::Receiver<QueuedTask>, +/// These are tasks that must be run after +/// [`GlobalState::process_changes`] has been called. +pub(crate) struct DeferredTaskQueue { + pub(crate) sender: crossbeam_channel::Sender<DeferredTask>, + pub(crate) receiver: crossbeam_channel::Receiver<DeferredTask>, } diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs index e803747998..bd49e08b10 100644 --- a/crates/span/src/ast_id.rs +++ b/crates/span/src/ast_id.rs @@ -44,6 +44,7 @@ pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = /// ErasedFileAstId used as the span for syntax node fixups. Any Span containing this file id is to be /// considered fake. +/// Do not modify this, it is used by the proc-macro server. pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = ErasedFileAstId(pack_hash_index_and_kind(0, 0, ErasedFileAstIdKind::Fixup as u32)); @@ -700,7 +701,7 @@ impl AstIdMap { } } - /// The [`AstId`] of the root node + /// The root node. pub fn root(&self) -> SyntaxNodePtr { self.arena[Idx::from_raw(RawIdx::from_u32(0))].0 } diff --git a/crates/span/src/hygiene.rs b/crates/span/src/hygiene.rs index 6c363825aa..6805417177 100644 --- a/crates/span/src/hygiene.rs +++ b/crates/span/src/hygiene.rs @@ -249,7 +249,7 @@ const _: () = { ) } - /// Invariant: Only [`SyntaxContext::ROOT`] has a [`None`] outer expansion. + /// Invariant: Only the root [`SyntaxContext`] has a [`None`] outer expansion. // FIXME: The None case needs to encode the context crate id. We can encode that as the MSB of // MacroCallId is reserved anyways so we can do bit tagging here just fine. // The bigger issue is that this will cause interning to now create completely separate chains @@ -348,7 +348,7 @@ impl SyntaxContext { } } - /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context. + /// The root context, which is the parent of all other contexts. All `FileId`s have this context. #[inline] pub const fn root(edition: Edition) -> Self { let edition = edition as u32; diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs index ae9e038459..cb91f49249 100644 --- a/crates/span/src/lib.rs +++ b/crates/span/src/lib.rs @@ -28,6 +28,33 @@ impl Span { let range = self.range.cover(other.range); Span { range, ..self } } + + pub fn join( + self, + other: Span, + differing_anchor: impl FnOnce(Span, Span) -> Option<Span>, + ) -> Option<Span> { + // We can't modify the span range for fixup spans, those are meaningful to fixup, so just + // prefer the non-fixup span. + if self.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + return Some(other); + } + if other.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { + return Some(self); + } + if self.anchor != other.anchor { + return differing_anchor(self, other); + } + // Differing context, we can't merge these so prefer the one that's root + if self.ctx != other.ctx { + if self.ctx.is_root() { + return Some(other); + } else if other.ctx.is_root() { + return Some(self); + } + } + Some(Span { range: self.range.cover(other.range), anchor: other.anchor, ctx: other.ctx }) + } } /// Spans represent a region of code, used by the IDE to be able link macro inputs and outputs diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 7346b93192..de341f0553 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -282,7 +282,7 @@ fn api_walkthrough() { assert!(parse.errors().is_empty()); // The `tree` method returns an owned syntax node of type `SourceFile`. - // Owned nodes are cheap: inside, they are `Rc` handles to the underling data. + // Owned nodes are cheap: inside, they are `Rc` handles to the underlying data. let file: SourceFile = parse.tree(); // `SourceFile` is the root of the syntax tree. We can iterate file's items. diff --git a/crates/test-utils/src/assert_linear.rs b/crates/test-utils/src/assert_linear.rs index f78bf59a2f..27665a74dc 100644 --- a/crates/test-utils/src/assert_linear.rs +++ b/crates/test-utils/src/assert_linear.rs @@ -11,7 +11,7 @@ //! Ideally, we should use a proper "model selection" to directly compare //! quadratic and linear models, but that sounds rather complicated: //! -//! > https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data +//! > <https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data> //! //! We might get false positives on a VM, but never false negatives. So, if the //! first round fails, we repeat the ordeal three more times and fail only if diff --git a/crates/test-utils/src/fixture.rs b/crates/test-utils/src/fixture.rs index 559894ee62..831d2b30c1 100644 --- a/crates/test-utils/src/fixture.rs +++ b/crates/test-utils/src/fixture.rs @@ -96,9 +96,10 @@ pub struct Fixture { /// /// Syntax: `cfg:test,dbg=false,opt_level=2` pub cfgs: Vec<(String, Option<String>)>, - /// Specifies the edition of this crate. This must be used with `crate` meta. If - /// this is not specified, ([`base_db::input::Edition::CURRENT`]) will be used. - /// This must be used with `crate` meta. + /// Specifies the edition of this crate. This must be used with + /// `crate` meta. If this is not specified, + /// `base_db::input::Edition::CURRENT` will be used. This must be + /// used with `crate` meta. /// /// Syntax: `edition:2021` pub edition: Option<String>, @@ -106,8 +107,8 @@ pub struct Fixture { /// /// Syntax: `env:PATH=/bin,RUST_LOG=debug` pub env: FxHashMap<String, String>, - /// Introduces a new [source root](base_db::input::SourceRoot). This file **and - /// the following files** will belong the new source root. This must be used + /// Introduces a new source root. This file **and the following + /// files** will belong the new source root. This must be used /// with `crate` meta. /// /// Use this if you want to test something that uses `SourceRoot::is_library()` @@ -126,7 +127,7 @@ pub struct Fixture { /// This is implied if this file belongs to a library source root. /// /// Use this if you want to test something that checks if a crate is a workspace - /// member via [`CrateOrigin`](base_db::input::CrateOrigin). + /// member via `CrateOrigin`. /// /// Syntax: `library` pub library: bool, diff --git a/docs/book/README.md b/docs/book/README.md index 11f7e8f98c..0a3161f3af 100644 --- a/docs/book/README.md +++ b/docs/book/README.md @@ -8,7 +8,6 @@ To run the documentation site locally: ```shell cargo install mdbook -cargo install mdbook-toc cargo xtask codegen cd docs/book mdbook serve diff --git a/docs/book/book.toml b/docs/book/book.toml index c77eabda14..0978851d50 100644 --- a/docs/book/book.toml +++ b/docs/book/book.toml @@ -33,8 +33,3 @@ use-boolean-and = true [output.html.fold] enable = true level = 3 - -[preprocessor.toc] -command = "mdbook-toc" -renderer = ["html"] -max-level = 3 diff --git a/docs/book/src/contributing/README.md b/docs/book/src/contributing/README.md index ad2816b18a..c95a1dba62 100644 --- a/docs/book/src/contributing/README.md +++ b/docs/book/src/contributing/README.md @@ -26,8 +26,6 @@ Discussion happens in this Zulip stream: <https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer> -<!-- toc --> - # Issue Labels * [good-first-issue](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) diff --git a/docs/book/src/contributing/architecture.md b/docs/book/src/contributing/architecture.md index f2b6c053b0..67653ebd74 100644 --- a/docs/book/src/contributing/architecture.md +++ b/docs/book/src/contributing/architecture.md @@ -20,8 +20,6 @@ For older, by now mostly outdated stuff, see the [guide](./guide.md) and [anothe  -<!-- toc --> - On the highest level, rust-analyzer is a thing which accepts input source code from the client and produces a structured semantic model of the code. More specifically, input data consists of a set of test files (`(PathBuf, String)` pairs) and information about project structure, captured in the so called `CrateGraph`. diff --git a/docs/book/src/contributing/guide.md b/docs/book/src/contributing/guide.md index 774eb5b2a5..9e944bfe0f 100644 --- a/docs/book/src/contributing/guide.md +++ b/docs/book/src/contributing/guide.md @@ -12,8 +12,6 @@ however, it's based on an older 2019-01-20 release (git tag [guide-2019-01]): [guide-2019-01]: https://github.com/rust-lang/rust-analyzer/tree/guide-2019-01 [2024-01-01]: https://github.com/rust-lang/rust-analyzer/tree/2024-01-01 -<!-- toc --> - ## The big picture On the highest possible level, rust-analyzer is a stateful component. A client may diff --git a/docs/book/src/contributing/lsp-extensions.md b/docs/book/src/contributing/lsp-extensions.md index 0e91e12612..5922f0b551 100644 --- a/docs/book/src/contributing/lsp-extensions.md +++ b/docs/book/src/contributing/lsp-extensions.md @@ -19,8 +19,6 @@ Requests, which are likely to always remain specific to `rust-analyzer` are unde If you want to be notified about the changes to this document, subscribe to [#4604](https://github.com/rust-lang/rust-analyzer/issues/4604). -<!-- toc --> - ## Configuration in `initializationOptions` **Upstream Issue:** <https://github.com/microsoft/language-server-protocol/issues/567> diff --git a/docs/book/src/other_editors.md b/docs/book/src/other_editors.md index 896df52af5..f7116fc19a 100644 --- a/docs/book/src/other_editors.md +++ b/docs/book/src/other_editors.md @@ -6,8 +6,6 @@ Protocol](https://microsoft.github.io/language-server-protocol/). This page assumes that you have already [installed the rust-analyzer binary](./rust_analyzer_binary.html). -<!-- toc --> - ## Emacs To use `rust-analyzer`, you need to install and enable one of the two |