Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower/path.rs')
| -rw-r--r-- | crates/hir-ty/src/lower/path.rs | 152 |
1 files changed, 107 insertions, 45 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index dfa8873b86..0757d57500 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -25,10 +25,10 @@ use smallvec::SmallVec; use crate::{ GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource, - PathLoweringDiagnostic, TyDefId, ValueTyDefId, - consteval::{unknown_const, unknown_const_as_generic}, + PathLoweringDiagnostic, Span, TyDefId, ValueTyDefId, db::HirDatabase, generics::{Generics, generics}, + infer::unify::InferenceTable, lower::{ AssocTypeShorthandResolution, ForbidParamsAfterReason, GenericPredicateSource, LifetimeElisionKind, PathDiagnosticCallbackData, const_param_ty, @@ -84,6 +84,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } } + #[track_caller] + pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> { + self.ctx.expect_table() + } + #[inline] #[cold] fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) { @@ -149,17 +154,18 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { // We need the original resolution to lower `Self::AssocTy` correctly res: Option<TypeNs>, infer_args: bool, + span: Span, ) -> (Ty<'db>, Option<TypeNs>) { let remaining_segments = self.segments.len() - self.current_segment_idx; match remaining_segments { 0 => (ty, res), 1 => { // resolve unselected assoc types - (self.select_associated_type(res, infer_args), None) + (self.select_associated_type(res, infer_args, span), None) } _ => { // FIXME report error (ambiguous associated type) - (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None) + (self.ctx.types.types.error, None) } } } @@ -169,6 +175,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { &mut self, resolution: TypeNs, infer_args: bool, + span: Span, ) -> (Ty<'db>, Option<TypeNs>) { let remaining_segments = self.segments.skip(self.current_segment_idx + 1); tracing::debug!(?remaining_segments); @@ -181,8 +188,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { 1 => { let trait_ref = self.lower_trait_ref_from_resolved_path( trait_, - Ty::new_error(self.ctx.interner, ErrorGuaranteed), + self.ctx.types.types.error, infer_args, + span, ); tracing::debug!(?trait_ref); self.skip_resolved_segment(); @@ -203,6 +211,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args, None, true, + span, ); let args = GenericArgs::new_from_iter( self.ctx.interner, @@ -222,7 +231,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } None => { // FIXME: report error (associated type not found) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } } } @@ -230,11 +239,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { // Trait object type without dyn; this should be handled in upstream. See // `lower_path()`. stdx::never!("unexpected fully resolved trait path"); - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } _ => { // FIXME report error (ambiguous associated type) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) + self.ctx.types.types.error } }; return (ty, None); @@ -250,19 +259,19 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { Ty::new_adt(self.ctx.interner, adt, args) } - TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), + TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args, span), + TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args, span), + TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args, span), // FIXME: report error TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => { - return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None); + return (self.ctx.types.types.error, None); } }; tracing::debug!(?ty); self.skip_resolved_segment(); - self.lower_ty_relative_path(ty, Some(resolution), infer_args) + self.lower_ty_relative_path(ty, Some(resolution), infer_args, span) } /// This returns whether to keep the resolution (`true`) of throw it (`false`). @@ -470,13 +479,17 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } #[tracing::instrument(skip(self), ret)] - fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> { + fn select_associated_type( + &mut self, + res: Option<TypeNs>, + infer_args: bool, + span: Span, + ) -> Ty<'db> { let interner = self.ctx.interner; let db = self.ctx.db; let def = self.ctx.generic_def; let segment = self.current_or_prev_segment; let assoc_name = segment.name; - let error_ty = || Ty::new_error(self.ctx.interner, ErrorGuaranteed); let (assoc_type, trait_args) = match res { Some(TypeNs::GenericParam(param)) => { let AssocTypeShorthandResolution::Resolved(assoc_type) = @@ -488,7 +501,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ) else { // FIXME: Emit an error. - return error_ty(); + return self.ctx.types.types.error; }; assoc_type .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref())) @@ -496,7 +509,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { } Some(TypeNs::SelfType(impl_)) => { let Some(impl_trait) = db.impl_trait(impl_) else { - return error_ty(); + return self.ctx.types.types.error; }; let impl_trait = impl_trait.instantiate_identity().skip_norm_wip(); // Searching for `Self::Assoc` in `impl Trait for Type` is like searching for `Self::Assoc` in `Trait`. @@ -509,7 +522,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ) else { // FIXME: Emit an error. - return error_ty(); + return self.ctx.types.types.error; }; let (assoc_type, trait_args) = assoc_type .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref())) @@ -521,14 +534,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { .skip_norm_wip(), ) } - _ => return error_ty(), + _ => return self.ctx.types.types.error, }; // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent // generic params. It's inefficient to splice the `Substitution`s, so we may want // that method to optionally take parent `Substitution` as we already know them at // this point (`t.substitution`). - let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true); + let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true, span); let substs = GenericArgs::new_from_iter( interner, @@ -538,7 +551,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { Ty::new_projection_from_args(interner, assoc_type.into(), substs) } - fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { + fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool, span: Span) -> Ty<'db> { let generic_def = match typeable { TyDefId::BuiltinType(builtinty) => { return Ty::from_builtin_type(self.ctx.interner, builtinty); @@ -546,7 +559,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { TyDefId::AdtId(it) => it.into(), TyDefId::TypeAliasId(it) => it.into(), }; - let args = self.substs_from_path_segment(generic_def, infer_args, None, false); + let args = self.substs_from_path_segment(generic_def, infer_args, None, false, span); let ty = ty_query(self.ctx.db, typeable); ty.instantiate(self.ctx.interner, args).skip_norm_wip() } @@ -561,6 +574,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: ValueTyDefId, infer_args: bool, lowering_assoc_type_generics: bool, + span: Span, ) -> GenericArgs<'db> { let interner = self.ctx.interner; let prev_current_segment_idx = self.current_segment_idx; @@ -604,6 +618,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args, None, lowering_assoc_type_generics, + span, ); self.current_segment_idx = prev_current_segment_idx; self.current_or_prev_segment = prev_current_segment; @@ -616,6 +631,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { infer_args: bool, explicit_self_ty: Option<Ty<'db>>, lowering_assoc_type_generics: bool, + span: Span, ) -> GenericArgs<'db> { let old_lifetime_elision = self.ctx.lifetime_elision; @@ -656,6 +672,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { PathGenericsSource::Segment(self.current_segment_u32()), lowering_assoc_type_generics, self.ctx.lifetime_elision, + span, ); self.ctx.lifetime_elision = old_lifetime_elision; result @@ -670,10 +687,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { generics_source: PathGenericsSource, lowering_assoc_type_generics: bool, lifetime_elision: LifetimeElisionKind<'db>, + span: Span, ) -> GenericArgs<'db> { struct LowererCtx<'a, 'b, 'c, 'db> { ctx: &'a mut PathLoweringContext<'b, 'c, 'db>, generics_source: PathGenericsSource, + span: Span, } impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> { @@ -736,13 +755,13 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { fn provided_type_like_const( &mut self, - _type_ref: TypeRefId, + type_ref: TypeRefId, const_ty: Ty<'db>, arg: TypeLikeConst<'_>, ) -> Const<'db> { match arg { TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty), - TypeLikeConst::Infer => unknown_const(const_ty), + TypeLikeConst::Infer => self.ctx.ctx.next_const_var(type_ref.into()), } } @@ -753,16 +772,18 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { param: GenericParamDataRef<'_>, infer_args: bool, preceding_args: &[GenericArg<'db>], + had_count_error: bool, ) -> GenericArg<'db> { let default = || { self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| { default.instantiate(self.ctx.ctx.interner, preceding_args).skip_norm_wip() }) }; + // If `!infer_args`, we've already emitted an error, so put a dummy span. + let span = if !infer_args || had_count_error { Span::Dummy } else { self.span }; match param { GenericParamDataRef::LifetimeParamData(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() + self.ctx.ctx.next_region_var(span).into() } GenericParamDataRef::TypeParamData(param) => { if !infer_args @@ -771,7 +792,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { { return default; } - Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() + self.ctx.ctx.next_ty_var_no_placeholder(span).into() } GenericParamDataRef::ConstParamData(param) => { if !infer_args @@ -780,10 +801,10 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { { return default; } - let GenericParamId::ConstParamId(const_id) = param_id else { + let GenericParamId::ConstParamId(_) = param_id else { unreachable!("non-const param ID for const param"); }; - unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id)) + self.ctx.ctx.next_const_var(span).into() } } } @@ -793,13 +814,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { GenericParamId::TypeParamId(_) => { Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() } - GenericParamId::ConstParamId(const_id) => { - unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id)) - } - GenericParamId::LifetimeParamId(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() - } + GenericParamId::ConstParamId(_) => self.ctx.ctx.types.consts.error.into(), + GenericParamId::LifetimeParamId(_) => self.ctx.ctx.types.regions.error.into(), } } @@ -843,7 +859,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { lifetime_elision, lowering_assoc_type_generics, explicit_self_ty, - &mut LowererCtx { ctx: self, generics_source }, + &mut LowererCtx { ctx: self, generics_source, span }, ) } @@ -852,8 +868,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: TraitId, explicit_self_ty: Ty<'db>, infer_args: bool, + span: Span, ) -> TraitRef<'db> { - let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); + let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args, span); TraitRef::new_from_args(self.ctx.interner, resolved.into(), args) } @@ -862,13 +879,21 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { resolved: TraitId, explicit_self_ty: Ty<'db>, infer_args: bool, + span: Span, ) -> GenericArgs<'db> { - self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false) + self.substs_from_path_segment( + resolved.into(), + infer_args, + Some(explicit_self_ty), + false, + span, + ) } pub(super) fn assoc_type_bindings_from_type_bound<'c>( mut self, trait_ref: TraitRef<'db>, + span: Span, ) -> Option<impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'c, 'db>> { let interner = self.ctx.interner; @@ -900,6 +925,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { }, false, this.ctx.lifetime_elision, + span, ) }); let args = GenericArgs::new_from_iter( @@ -1019,6 +1045,7 @@ pub(crate) trait GenericArgsLowerer<'db> { param: GenericParamDataRef<'_>, infer_args: bool, preceding_args: &[GenericArg<'db>], + had_count_error: bool, ) -> GenericArg<'db>; fn parent_arg(&mut self, param_idx: u32, param_id: GenericParamId) -> GenericArg<'db>; @@ -1187,7 +1214,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( ctx.provided_kind(self_param_id, self_param, self_ty) } else { explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| { - ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs) + ctx.inferred_kind( + def, + self_param_id, + self_param, + infer_args, + &substs, + had_count_error, + ) }) }; params.next(); @@ -1206,7 +1240,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( { // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here // we will handle it as if it was specified, instead of inferring it. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); + substs.push(ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + )); params.next(); } (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_)) @@ -1222,7 +1263,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( ) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetime. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); + substs.push(ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + )); params.next(); force_infer_lt = Some((arg_idx as u32, param_id)); } @@ -1291,7 +1339,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>( | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | LifetimeElisionKind::AnonymousReportError => { assert!(had_count_error); - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + ) } LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { Region::new_static(interner).into() @@ -1301,11 +1356,18 @@ pub(crate) fn substs_from_args_and_bindings<'db>( | LifetimeElisionKind::Infer => { // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here // (but this will probably be done in hir-def lowering instead). - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind( + def, + param_id, + param, + infer_args, + &substs, + had_count_error, + ) } } } else { - ctx.inferred_kind(def, param_id, param, infer_args, &substs) + ctx.inferred_kind(def, param_id, param, infer_args, &substs, had_count_error) }; substs.push(param); params.next(); |