Skip to content

Commit 1dd1ec5

Browse files
committed
Fix resolution of call of imported enum tuple variant constructor
1 parent 1469529 commit 1dd1ec5

File tree

11 files changed

+136
-71
lines changed

11 files changed

+136
-71
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/driver/src/db.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ impl DriverDataBase {
243243

244244
pub struct DiagnosticsCollection<'db>(Vec<Box<dyn DiagnosticVoucher<'db> + 'db>>);
245245
impl<'db> DiagnosticsCollection<'db> {
246+
pub fn is_empty(&self) -> bool {
247+
self.0.is_empty()
248+
}
249+
246250
pub fn emit(&self, db: &'db DriverDataBase) {
247251
let writer = BufferWriter::stderr(ColorChoice::Auto);
248252
let mut buffer = writer.buffer();

crates/hir-analysis/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ test-utils.workspace = true
2424
hir.workspace = true
2525

2626
[dev-dependencies]
27+
camino.workspace = true
2728
codespan-reporting.workspace = true
2829
dir-test.workspace = true
2930
# TODO move cs diagnostics utils

crates/hir-analysis/src/name_resolution/path_resolver.rs

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use super::{
1515
use crate::{
1616
name_resolution::{NameResKind, QueryDirective},
1717
ty::{
18-
adt_def::{lower_adt, AdtRef, AdtRefId},
19-
func_def::lower_func,
18+
adt_def::{lower_adt, AdtRefId},
19+
binder::Binder,
20+
func_def::{lower_func, FuncDef, HirFuncDefKind},
2021
trait_def::TraitDef,
2122
trait_lower::lower_trait,
2223
ty_def::{InvalidCause, TyId},
@@ -249,6 +250,10 @@ pub struct ResolvedVariant<'db> {
249250
}
250251

251252
impl<'db> ResolvedVariant<'db> {
253+
pub fn new(ty: TyId<'db>, idx: usize, path: PathId<'db>) -> Self {
254+
Self { ty, idx, path }
255+
}
256+
252257
pub fn variant_def(&self, db: &'db dyn HirAnalysisDb) -> &'db VariantDef<'db> {
253258
&self.enum_(db).variants(db.as_hir_db()).data(db.as_hir_db())[self.idx]
254259
}
@@ -258,14 +263,59 @@ impl<'db> ResolvedVariant<'db> {
258263
}
259264

260265
pub fn enum_(&self, db: &'db dyn HirAnalysisDb) -> Enum<'db> {
261-
let AdtRef::Enum(enum_) = self.ty.adt_ref(db).unwrap().data(db) else {
262-
unreachable!()
263-
};
264-
enum_
266+
self.ty.as_enum(db).unwrap()
265267
}
266268

267-
pub fn new(ty: TyId<'db>, idx: usize, path: PathId<'db>) -> Self {
268-
Self { ty, idx, path }
269+
pub fn iter_field_types(
270+
&self,
271+
db: &'db dyn HirAnalysisDb,
272+
) -> impl Iterator<Item = Binder<TyId<'db>>> {
273+
self.ty
274+
.adt_def(db)
275+
.unwrap()
276+
.fields(db)
277+
.get(self.idx)
278+
.unwrap()
279+
.iter_types(db)
280+
}
281+
282+
pub fn constructor_func_ty(&self, db: &'db dyn HirAnalysisDb) -> Option<TyId<'db>> {
283+
let mut ty = TyId::func(db, self.to_funcdef(db)?);
284+
285+
for &arg in self.ty.generic_args(db) {
286+
if ty.applicable_ty(db).is_some() {
287+
ty = TyId::app(db, ty, arg);
288+
}
289+
}
290+
Some(ty)
291+
}
292+
293+
pub fn to_funcdef(&self, db: &'db dyn HirAnalysisDb) -> Option<FuncDef<'db>> {
294+
if !matches!(self.variant_kind(db), VariantKind::Tuple(_)) {
295+
return None;
296+
}
297+
298+
let adt = self.ty.adt_def(db).unwrap();
299+
let arg_tys = adt
300+
.fields(db)
301+
.get(self.idx)
302+
.unwrap()
303+
.iter_types(db)
304+
.collect();
305+
306+
let adt_param_set = adt.param_set(db);
307+
308+
let mut ret_ty = TyId::adt(db, adt);
309+
ret_ty = TyId::foldl(db, ret_ty, adt.param_set(db).params(db));
310+
311+
Some(FuncDef::new(
312+
db,
313+
HirFuncDefKind::VariantCtor(self.enum_(db), self.idx),
314+
*self.variant_def(db).name.unwrap(),
315+
*adt_param_set,
316+
arg_tys,
317+
Binder::bind(ret_ty),
318+
))
269319
}
270320
}
271321

crates/hir-analysis/src/ty/method_table.rs

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
use hir::hir_def::{Enum, IdentId, Impl, IngotId, VariantKind};
1+
use hir::hir_def::{IdentId, Impl, IngotId};
22
use rustc_hash::FxHashMap;
33

44
use super::{
5-
adt_def::{lower_adt, AdtRefId},
65
binder::Binder,
76
canonical::Canonical,
8-
func_def::{lower_func, FuncDef, HirFuncDefKind},
7+
func_def::{lower_func, FuncDef},
98
ty_def::{InvalidCause, TyBase, TyId},
109
ty_lower::lower_hir_ty,
1110
unify::UnificationTable,
1211
};
13-
use crate::{
14-
ty::{ty_def::TyData, ty_lower::GenericParamTypeSet},
15-
HirAnalysisDb,
16-
};
12+
use crate::{ty::ty_def::TyData, HirAnalysisDb};
1713

1814
#[salsa::tracked(return_ref)]
1915
pub(crate) fn collect_methods<'db>(
@@ -22,11 +18,7 @@ pub(crate) fn collect_methods<'db>(
2218
) -> MethodTable<'db> {
2319
let mut collector = MethodCollector::new(db, ingot);
2420

25-
let enums = ingot.all_enums(db.as_hir_db());
26-
collector.collect_variant_ctors(enums);
27-
2821
let impls = ingot.all_impls(db.as_hir_db());
29-
3022
collector.collect_impls(impls);
3123
collector.finalize()
3224
}
@@ -150,47 +142,6 @@ impl<'db> MethodCollector<'db> {
150142
}
151143
}
152144

153-
fn collect_variant_ctors(&mut self, enums: &[Enum<'db>]) {
154-
let hir_db = self.db.as_hir_db();
155-
for &enum_ in enums {
156-
let adt_ref = AdtRefId::new(self.db, enum_.into());
157-
let adt = lower_adt(self.db, adt_ref);
158-
for (i, variant) in enum_.variants(hir_db).data(hir_db).iter().enumerate() {
159-
if !matches!(variant.kind, VariantKind::Tuple(_)) {
160-
continue;
161-
};
162-
let (Some(name), Some(variant)) =
163-
(variant.name.to_opt(), adt.fields(self.db).get(i))
164-
else {
165-
continue;
166-
};
167-
168-
let arg_tys = variant.iter_types(self.db).collect();
169-
let mut ret_ty = TyId::adt(self.db, adt);
170-
let adt_param_set = adt.param_set(self.db);
171-
ret_ty = TyId::foldl(self.db, ret_ty, adt.param_set(self.db).params(self.db));
172-
173-
let param_set = GenericParamTypeSet::new(
174-
self.db,
175-
adt_param_set.params_precursor(self.db).to_vec(),
176-
adt_param_set.scope(self.db),
177-
adt_param_set.len(self.db),
178-
);
179-
180-
let func = FuncDef::new(
181-
self.db,
182-
HirFuncDefKind::VariantCtor(enum_, i),
183-
name,
184-
param_set,
185-
arg_tys,
186-
Binder::bind(ret_ty),
187-
);
188-
189-
self.insert(ret_ty, func)
190-
}
191-
}
192-
}
193-
194145
fn collect_impls(&mut self, impls: &[Impl<'db>]) {
195146
for impl_ in impls {
196147
let ty = match impl_.ty(self.db.as_hir_db()).to_opt() {

crates/hir-analysis/src/ty/ty_check/expr.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,10 @@ impl<'db> TyChecker<'db> {
447447
PathRes::EnumVariant(variant) => {
448448
let ty = match variant.variant_kind(self.db) {
449449
VariantKind::Unit => variant.ty,
450-
VariantKind::Tuple(_) => self
451-
.select_method_candidate_for_path(variant.ty, *path, span.path())
452-
.unwrap_or_else(|| TyId::invalid(self.db, InvalidCause::Other)),
450+
VariantKind::Tuple(_) => {
451+
let ty = variant.constructor_func_ty(self.db).unwrap();
452+
self.table.instantiate_to_term(ty)
453+
}
453454
VariantKind::Record(_) => {
454455
let diag = BodyDiag::unit_variant_expected(
455456
self.db,

crates/hir-analysis/src/ty/ty_lower.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,6 @@ impl<'db> GenericParamTypeSet<'db> {
285285
Self::new(db, Vec::new(), scope, 0)
286286
}
287287

288-
pub(crate) fn len(self, db: &dyn HirAnalysisDb) -> usize {
289-
self.params_precursor(db).len()
290-
}
291-
292288
pub(crate) fn trait_self(&self, db: &'db dyn HirAnalysisDb) -> Option<TyId<'db>> {
293289
let params = self.params_precursor(db);
294290
let cand = params.first()?;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use core::{Option, panic}
2+
3+
fn f() -> u32 {
4+
let x = Option::Some(10)
5+
x.unwrap() // FIXME
6+
7+
let y: Option<u8> = Option::none() // FIXME
8+
let z: Option<u8> = Option::default()
9+
10+
match x {
11+
Option::Some(x) => x
12+
Option::None => panic()
13+
}
14+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
source: crates/uitest/tests/name_resolution.rs
3+
expression: diags
4+
input_file: fixtures/name_resolution/imported_enum_constructor.fe
5+
---
6+
error[8-0029]: `unwrap` is not found
7+
┌─ imported_enum_constructor.fe:5:7
8+
9+
5x.unwrap() // FIXME
10+
^^^^^^ `unwrap` is not found in `Option`
11+
12+
error[8-0029]: `none` is not found
13+
┌─ imported_enum_constructor.fe:7:33
14+
15+
7let y: Option<u8> = Option::none() // FIXME
16+
^^^^ `none` is not found in `Option`

crates/uitest/tests/name_resolution.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ fn run_name_resolution(fixture: Fixture<&str>) {
1111
let mut db = DriverDataBase::default();
1212
let path = Utf8Path::new(fixture.path());
1313

14-
let (ingot, file) = db.standalone_no_core(path, fixture.content());
14+
let (core, _) = db.static_core_ingot();
15+
let (ingot, file) = db.standalone(path, fixture.content(), core);
1516
let top_mod = db.top_mod(ingot, file);
1617

1718
let diags = db.run_on_top_mod(top_mod);
@@ -37,7 +38,8 @@ mod wasm {
3738
let mut db = DriverDataBase::default();
3839
let path = Utf8Path::new(fixture.path());
3940

40-
let (ingot, file) = db.standalone_no_core(path, fixture.content());
41+
let (core, _) = db.static_core_ingot();
42+
let (ingot, file) = db.standalone(path, fixture.content(), core);
4143
let top_mod = db.top_mod(ingot, file);
4244
db.run_on_top_mod(top_mod);
4345
}

0 commit comments

Comments
 (0)