diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5ebb5628ad..6ba2b31353 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3043,10 +3043,17 @@ pub struct BuiltinType { } impl BuiltinType { + // Constructors are added on demand, feel free to add more. pub fn str() -> BuiltinType { BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str } } + pub fn i32() -> BuiltinType { + BuiltinType { + inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32), + } + } + pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); Type::new_for_crate(core, TyBuilder::builtin(self.inner)) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 6e3a76f346..ea5fb39338 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -4,6 +4,7 @@ use std::iter; use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant}; use ide_db::{RootDatabase, active_parameter::ActiveParameter}; use itertools::Either; +use stdx::always; use syntax::{ AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T, TextRange, TextSize, @@ -869,8 +870,15 @@ fn classify_name_ref<'db>( return None; } + let mut receiver_ty = receiver.as_ref().and_then(|it| sema.type_of_expr(it)); + if receiver_is_ambiguous_float_literal { + // `123.|` is parsed as a float but should actually be an integer. + always!(receiver_ty.as_ref().is_none_or(|receiver_ty| receiver_ty.original.is_float())); + receiver_ty = Some(TypeInfo { original: hir::BuiltinType::i32().ty(sema.db), adjusted: None }); + } + let kind = NameRefKind::DotAccess(DotAccess { - receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)), + receiver_ty, kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal }, receiver, ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()) } diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index b2d18b796f..33f729f016 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -2241,3 +2241,37 @@ fn main() { "#, ); } + +#[test] +fn ambiguous_float_literal() { + check( + r#" +#![rustc_coherence_is_core] + +impl i32 { + pub fn int_method(self) {} +} +impl f64 { + pub fn float_method(self) {} +} + +fn foo() { + 1.$0 +} + "#, + expect![[r#" + me int_method() fn(self) + sn box Box::new(expr) + sn call function(expr) + sn const const {} + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn deref *expr + sn match match expr {} + sn ref &expr + sn refm &mut expr + sn return return expr + sn unsafe unsafe {} + "#]], + ); +}