@@ -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 {
@@ -3472,11 +3483,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3472
3483
module : & Option < ( EcoString , SrcSpan ) > ,
3473
3484
name : & EcoString ,
3474
3485
location : & SrcSpan ,
3486
+ var_usage : VarUsage ,
3475
3487
) -> Result < ValueConstructor , Error > {
3476
3488
self . do_infer_value_constructor (
3477
3489
module,
3478
3490
name,
3479
3491
location,
3492
+ var_usage,
3480
3493
ReferenceRegistration :: RegisterReferences ,
3481
3494
)
3482
3495
}
@@ -3486,6 +3499,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3486
3499
module : & Option < ( EcoString , SrcSpan ) > ,
3487
3500
name : & EcoString ,
3488
3501
location : & SrcSpan ,
3502
+ var_usage : VarUsage ,
3489
3503
register_reference : ReferenceRegistration ,
3490
3504
) -> Result < ValueConstructor , Error > {
3491
3505
let constructor = match module {
@@ -3494,7 +3508,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3494
3508
. environment
3495
3509
. get_variable ( name)
3496
3510
. cloned ( )
3497
- . ok_or_else ( || self . report_name_error ( name, location) ) ?,
3511
+ . ok_or_else ( || self . report_name_error ( name, location, var_usage ) ) ?,
3498
3512
3499
3513
// Look in an imported module for a binding with this name
3500
3514
Some ( ( module_name, module_location) ) => {
@@ -3622,7 +3636,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3622
3636
}
3623
3637
}
3624
3638
3625
- fn report_name_error ( & mut self , name : & EcoString , location : & SrcSpan ) -> Error {
3639
+ fn report_name_error (
3640
+ & mut self ,
3641
+ name : & EcoString ,
3642
+ location : & SrcSpan ,
3643
+ var_usage : VarUsage ,
3644
+ ) -> Error {
3626
3645
// First try to see if this is a module alias:
3627
3646
// `import gleam/io`
3628
3647
// `io.debug(io)`
@@ -3633,30 +3652,59 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3633
3652
location : * location,
3634
3653
name : name. clone ( ) ,
3635
3654
} ,
3636
- None => Error :: UnknownVariable {
3637
- location : * location,
3638
- name : name. clone ( ) ,
3639
- variables : self . environment . local_value_names ( ) ,
3640
- discarded_location : self
3641
- . environment
3642
- . discarded_names
3643
- . get ( & eco_format ! ( "_{name}" ) )
3644
- . cloned ( ) ,
3645
- type_with_name_in_scope : self
3646
- . environment
3647
- . module_types
3648
- . keys ( )
3649
- . any ( |typ| typ == name) ,
3650
- imported_modules_with_same_public_variable_name : self
3651
- . environment
3652
- . imported_modules
3653
- . iter ( )
3654
- . filter_map ( |( module_name, ( _, module) ) | {
3655
- module. get_public_value ( name) . map ( |_| module_name)
3656
- } )
3657
- . cloned ( )
3658
- . collect_vec ( ) ,
3659
- } ,
3655
+ None => {
3656
+ let imported_modules_with_same_public_variable_name = match var_usage {
3657
+ // This is a function call, we need to suggest a public
3658
+ // variable which is a function with the correct arity
3659
+ VarUsage :: Call { arity } => self
3660
+ . environment
3661
+ . imported_modules
3662
+ . iter ( )
3663
+ . filter_map ( |( module_name, ( _, module) ) | {
3664
+ module
3665
+ . get_public_value ( name)
3666
+ . filter ( |value_constructor| {
3667
+ match value_constructor. type_ . fn_types ( ) {
3668
+ Some ( ( fn_arguments_type, _) ) => {
3669
+ fn_arguments_type. len ( ) == arity
3670
+ }
3671
+ None => false ,
3672
+ }
3673
+ } )
3674
+ . map ( |_| module_name)
3675
+ } )
3676
+ . cloned ( )
3677
+ . collect_vec ( ) ,
3678
+ // This is a reference to a variable, we need to suggest
3679
+ // public variables of any type
3680
+ VarUsage :: Other => self
3681
+ . environment
3682
+ . imported_modules
3683
+ . iter ( )
3684
+ . filter_map ( |( module_name, ( _, module) ) | {
3685
+ module. get_public_value ( name) . map ( |_| module_name)
3686
+ } )
3687
+ . cloned ( )
3688
+ . collect_vec ( ) ,
3689
+ } ;
3690
+
3691
+ Error :: UnknownVariable {
3692
+ location : * location,
3693
+ name : name. clone ( ) ,
3694
+ variables : self . environment . local_value_names ( ) ,
3695
+ discarded_location : self
3696
+ . environment
3697
+ . discarded_names
3698
+ . get ( & eco_format ! ( "_{name}" ) )
3699
+ . cloned ( ) ,
3700
+ type_with_name_in_scope : self
3701
+ . environment
3702
+ . module_types
3703
+ . keys ( )
3704
+ . any ( |typ| typ == name) ,
3705
+ imported_modules_with_same_public_variable_name,
3706
+ }
3707
+ }
3660
3708
}
3661
3709
}
3662
3710
@@ -3714,7 +3762,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3714
3762
..
3715
3763
} if arguments. is_empty ( ) => {
3716
3764
// Type check the record constructor
3717
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3765
+ let constructor =
3766
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3718
3767
3719
3768
let ( tag, field_map) = match & constructor. variant {
3720
3769
ValueConstructorVariant :: Record {
@@ -3753,7 +3802,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3753
3802
// field_map, is always None here because untyped not yet unified
3754
3803
..
3755
3804
} => {
3756
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3805
+ let constructor = self . infer_value_constructor (
3806
+ & module,
3807
+ & name,
3808
+ & location,
3809
+ VarUsage :: Call {
3810
+ arity : arguments. len ( ) ,
3811
+ } ,
3812
+ ) ?;
3757
3813
3758
3814
let ( tag, field_map, variant_index) = match & constructor. variant {
3759
3815
ValueConstructorVariant :: Record {
@@ -3895,7 +3951,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3895
3951
..
3896
3952
} => {
3897
3953
// Infer the type of this constant
3898
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3954
+ let constructor =
3955
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3899
3956
match constructor. variant {
3900
3957
ValueConstructorVariant :: ModuleConstant { .. }
3901
3958
| ValueConstructorVariant :: LocalConstant { .. }
@@ -4072,6 +4129,30 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
4072
4129
kind : CallKind ,
4073
4130
) -> ( TypedExpr , Vec < TypedCallArg > , Arc < Type > ) {
4074
4131
let fun = match fun {
4132
+ UntypedExpr :: Var { location, name } => {
4133
+ // Because we are not calling infer / infer_or_error directly,
4134
+ // we do not warn if there was a previous panic. Check for that
4135
+ // here. Not perfect, but works.
4136
+ if self . previous_panics {
4137
+ self . warn_for_unreachable_code ( location, PanicPosition :: PreviousExpression ) ;
4138
+ }
4139
+
4140
+ match self . infer_var (
4141
+ name,
4142
+ location,
4143
+ VarUsage :: Call {
4144
+ arity : arguments. len ( ) ,
4145
+ } ,
4146
+ ReferenceRegistration :: RegisterReferences ,
4147
+ ) {
4148
+ Ok ( typed_expr) => typed_expr,
4149
+ Err ( error) => {
4150
+ self . problems . error ( error) ;
4151
+ self . error_expr ( location)
4152
+ }
4153
+ }
4154
+ }
4155
+
4075
4156
UntypedExpr :: FieldAccess {
4076
4157
label,
4077
4158
container,
0 commit comments