@@ -432,9 +432,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
432
432
message,
433
433
} => Ok ( self . infer_echo ( location, keyword_end, expression, message) ) ,
434
434
435
- UntypedExpr :: Var { location, name, .. } => {
436
- self . infer_var ( name, location, ReferenceRegistration :: RegisterReferences )
437
- }
435
+ UntypedExpr :: Var { location, name, .. } => self . infer_var (
436
+ name,
437
+ location,
438
+ VarUsage :: Other ,
439
+ ReferenceRegistration :: RegisterReferences ,
440
+ ) ,
438
441
439
442
UntypedExpr :: Int {
440
443
location,
@@ -1247,10 +1250,16 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
1247
1250
& mut self ,
1248
1251
name : EcoString ,
1249
1252
location : SrcSpan ,
1253
+ var_usage : VarUsage ,
1250
1254
register_reference : ReferenceRegistration ,
1251
1255
) -> Result < TypedExpr , Error > {
1252
- let constructor =
1253
- self . do_infer_value_constructor ( & None , & name, & location, register_reference) ?;
1256
+ let constructor = self . do_infer_value_constructor (
1257
+ & None ,
1258
+ & name,
1259
+ & location,
1260
+ var_usage,
1261
+ register_reference,
1262
+ ) ?;
1254
1263
self . narrow_implementations ( location, & constructor. variant ) ?;
1255
1264
Ok ( TypedExpr :: Var {
1256
1265
constructor,
@@ -1345,6 +1354,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
1345
1354
UntypedExpr :: Var { location, name } => self . infer_var (
1346
1355
name,
1347
1356
location,
1357
+ VarUsage :: Other ,
1348
1358
ReferenceRegistration :: DoNotRegisterReferences ,
1349
1359
) ,
1350
1360
_ => self . infer_or_error ( container) ,
@@ -2309,7 +2319,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
2309
2319
fn infer_clause_guard ( & mut self , guard : UntypedClauseGuard ) -> Result < TypedClauseGuard , Error > {
2310
2320
match guard {
2311
2321
ClauseGuard :: Var { location, name, .. } => {
2312
- let constructor = self . infer_value_constructor ( & None , & name, & location) ?;
2322
+ let constructor =
2323
+ self . infer_value_constructor ( & None , & name, & location, VarUsage :: Other ) ?;
2313
2324
2314
2325
// We cannot support all values in guard expressions as the BEAM does not
2315
2326
let definition_location = match & constructor. variant {
@@ -3459,11 +3470,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3459
3470
module : & Option < ( EcoString , SrcSpan ) > ,
3460
3471
name : & EcoString ,
3461
3472
location : & SrcSpan ,
3473
+ var_usage : VarUsage ,
3462
3474
) -> Result < ValueConstructor , Error > {
3463
3475
self . do_infer_value_constructor (
3464
3476
module,
3465
3477
name,
3466
3478
location,
3479
+ var_usage,
3467
3480
ReferenceRegistration :: RegisterReferences ,
3468
3481
)
3469
3482
}
@@ -3473,6 +3486,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3473
3486
module : & Option < ( EcoString , SrcSpan ) > ,
3474
3487
name : & EcoString ,
3475
3488
location : & SrcSpan ,
3489
+ var_usage : VarUsage ,
3476
3490
register_reference : ReferenceRegistration ,
3477
3491
) -> Result < ValueConstructor , Error > {
3478
3492
let constructor = match module {
@@ -3481,7 +3495,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3481
3495
. environment
3482
3496
. get_variable ( name)
3483
3497
. cloned ( )
3484
- . ok_or_else ( || self . report_name_error ( name, location) ) ?,
3498
+ . ok_or_else ( || self . report_name_error ( name, location, var_usage ) ) ?,
3485
3499
3486
3500
// Look in an imported module for a binding with this name
3487
3501
Some ( ( module_name, module_location) ) => {
@@ -3609,7 +3623,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3609
3623
}
3610
3624
}
3611
3625
3612
- fn report_name_error ( & mut self , name : & EcoString , location : & SrcSpan ) -> Error {
3626
+ fn report_name_error (
3627
+ & mut self ,
3628
+ name : & EcoString ,
3629
+ location : & SrcSpan ,
3630
+ var_usage : VarUsage ,
3631
+ ) -> Error {
3613
3632
// First try to see if this is a module alias:
3614
3633
// `import gleam/io`
3615
3634
// `io.debug(io)`
@@ -3620,30 +3639,59 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3620
3639
location : * location,
3621
3640
name : name. clone ( ) ,
3622
3641
} ,
3623
- None => Error :: UnknownVariable {
3624
- location : * location,
3625
- name : name. clone ( ) ,
3626
- variables : self . environment . local_value_names ( ) ,
3627
- discarded_location : self
3628
- . environment
3629
- . discarded_names
3630
- . get ( & eco_format ! ( "_{name}" ) )
3631
- . cloned ( ) ,
3632
- type_with_name_in_scope : self
3633
- . environment
3634
- . module_types
3635
- . keys ( )
3636
- . any ( |typ| typ == name) ,
3637
- imported_modules_with_same_public_variable_name : self
3638
- . environment
3639
- . imported_modules
3640
- . iter ( )
3641
- . filter_map ( |( module_name, ( _, module) ) | {
3642
- module. get_public_value ( name) . map ( |_| module_name)
3643
- } )
3644
- . cloned ( )
3645
- . collect_vec ( ) ,
3646
- } ,
3642
+ None => {
3643
+ let imported_modules_with_same_public_variable_name = match var_usage {
3644
+ // This is a function call, we need to suggest a public
3645
+ // variable which is a function with the correct arity
3646
+ VarUsage :: Call { arity } => self
3647
+ . environment
3648
+ . imported_modules
3649
+ . iter ( )
3650
+ . filter_map ( |( module_name, ( _, module) ) | {
3651
+ module
3652
+ . get_public_value ( name)
3653
+ . filter ( |value_constructor| {
3654
+ match value_constructor. type_ . fn_types ( ) {
3655
+ Some ( ( fn_arguments_type, _) ) => {
3656
+ fn_arguments_type. len ( ) == arity
3657
+ }
3658
+ None => false ,
3659
+ }
3660
+ } )
3661
+ . map ( |_| module_name)
3662
+ } )
3663
+ . cloned ( )
3664
+ . collect_vec ( ) ,
3665
+ // This is a reference to a variable, we need to suggest
3666
+ // public variables of any type
3667
+ VarUsage :: Other => self
3668
+ . environment
3669
+ . imported_modules
3670
+ . iter ( )
3671
+ . filter_map ( |( module_name, ( _, module) ) | {
3672
+ module. get_public_value ( name) . map ( |_| module_name)
3673
+ } )
3674
+ . cloned ( )
3675
+ . collect_vec ( ) ,
3676
+ } ;
3677
+
3678
+ Error :: UnknownVariable {
3679
+ location : * location,
3680
+ name : name. clone ( ) ,
3681
+ variables : self . environment . local_value_names ( ) ,
3682
+ discarded_location : self
3683
+ . environment
3684
+ . discarded_names
3685
+ . get ( & eco_format ! ( "_{name}" ) )
3686
+ . cloned ( ) ,
3687
+ type_with_name_in_scope : self
3688
+ . environment
3689
+ . module_types
3690
+ . keys ( )
3691
+ . any ( |typ| typ == name) ,
3692
+ imported_modules_with_same_public_variable_name,
3693
+ }
3694
+ }
3647
3695
}
3648
3696
}
3649
3697
@@ -3701,7 +3749,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3701
3749
..
3702
3750
} if arguments. is_empty ( ) => {
3703
3751
// Type check the record constructor
3704
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3752
+ let constructor =
3753
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3705
3754
3706
3755
let ( tag, field_map) = match & constructor. variant {
3707
3756
ValueConstructorVariant :: Record {
@@ -3740,7 +3789,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3740
3789
// field_map, is always None here because untyped not yet unified
3741
3790
..
3742
3791
} => {
3743
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3792
+ let constructor = self . infer_value_constructor (
3793
+ & module,
3794
+ & name,
3795
+ & location,
3796
+ VarUsage :: Call {
3797
+ arity : arguments. len ( ) ,
3798
+ } ,
3799
+ ) ?;
3744
3800
3745
3801
let ( tag, field_map, variant_index) = match & constructor. variant {
3746
3802
ValueConstructorVariant :: Record {
@@ -3882,7 +3938,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3882
3938
..
3883
3939
} => {
3884
3940
// Infer the type of this constant
3885
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3941
+ let constructor =
3942
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3886
3943
match constructor. variant {
3887
3944
ValueConstructorVariant :: ModuleConstant { .. }
3888
3945
| ValueConstructorVariant :: LocalConstant { .. }
@@ -4059,6 +4116,30 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
4059
4116
kind : CallKind ,
4060
4117
) -> ( TypedExpr , Vec < TypedCallArg > , Arc < Type > ) {
4061
4118
let fun = match fun {
4119
+ UntypedExpr :: Var { location, name } => {
4120
+ // Because we are not calling infer / infer_or_error directly,
4121
+ // we do not warn if there was a previous panic. Check for that
4122
+ // here. Not perfect, but works.
4123
+ if self . previous_panics {
4124
+ self . warn_for_unreachable_code ( location, PanicPosition :: PreviousExpression ) ;
4125
+ }
4126
+
4127
+ match self . infer_var (
4128
+ name,
4129
+ location,
4130
+ VarUsage :: Call {
4131
+ arity : arguments. len ( ) ,
4132
+ } ,
4133
+ ReferenceRegistration :: RegisterReferences ,
4134
+ ) {
4135
+ Ok ( typed_expr) => typed_expr,
4136
+ Err ( error) => {
4137
+ self . problems . error ( error) ;
4138
+ self . error_expr ( location)
4139
+ }
4140
+ }
4141
+ }
4142
+
4062
4143
UntypedExpr :: FieldAccess {
4063
4144
label,
4064
4145
container,
0 commit comments