@@ -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,
@@ -1139,10 +1142,16 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
1139
1142
& mut self ,
1140
1143
name : EcoString ,
1141
1144
location : SrcSpan ,
1145
+ var_usage : VarUsage ,
1142
1146
register_reference : ReferenceRegistration ,
1143
1147
) -> Result < TypedExpr , Error > {
1144
- let constructor =
1145
- self . do_infer_value_constructor ( & None , & name, & location, register_reference) ?;
1148
+ let constructor = self . do_infer_value_constructor (
1149
+ & None ,
1150
+ & name,
1151
+ & location,
1152
+ var_usage,
1153
+ register_reference,
1154
+ ) ?;
1146
1155
self . narrow_implementations ( location, & constructor. variant ) ?;
1147
1156
Ok ( TypedExpr :: Var {
1148
1157
constructor,
@@ -1237,6 +1246,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
1237
1246
UntypedExpr :: Var { location, name } => self . infer_var (
1238
1247
name,
1239
1248
location,
1249
+ VarUsage :: Other ,
1240
1250
ReferenceRegistration :: DoNotRegisterReferences ,
1241
1251
) ,
1242
1252
_ => self . infer_or_error ( container) ,
@@ -2202,7 +2212,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
2202
2212
fn infer_clause_guard ( & mut self , guard : UntypedClauseGuard ) -> Result < TypedClauseGuard , Error > {
2203
2213
match guard {
2204
2214
ClauseGuard :: Var { location, name, .. } => {
2205
- let constructor = self . infer_value_constructor ( & None , & name, & location) ?;
2215
+ let constructor =
2216
+ self . infer_value_constructor ( & None , & name, & location, VarUsage :: Other ) ?;
2206
2217
2207
2218
// We cannot support all values in guard expressions as the BEAM does not
2208
2219
let definition_location = match & constructor. variant {
@@ -3352,11 +3363,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3352
3363
module : & Option < ( EcoString , SrcSpan ) > ,
3353
3364
name : & EcoString ,
3354
3365
location : & SrcSpan ,
3366
+ var_usage : VarUsage ,
3355
3367
) -> Result < ValueConstructor , Error > {
3356
3368
self . do_infer_value_constructor (
3357
3369
module,
3358
3370
name,
3359
3371
location,
3372
+ var_usage,
3360
3373
ReferenceRegistration :: RegisterReferences ,
3361
3374
)
3362
3375
}
@@ -3366,6 +3379,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3366
3379
module : & Option < ( EcoString , SrcSpan ) > ,
3367
3380
name : & EcoString ,
3368
3381
location : & SrcSpan ,
3382
+ var_usage : VarUsage ,
3369
3383
register_reference : ReferenceRegistration ,
3370
3384
) -> Result < ValueConstructor , Error > {
3371
3385
let constructor = match module {
@@ -3374,7 +3388,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3374
3388
. environment
3375
3389
. get_variable ( name)
3376
3390
. cloned ( )
3377
- . ok_or_else ( || self . report_name_error ( name, location) ) ?,
3391
+ . ok_or_else ( || self . report_name_error ( name, location, var_usage ) ) ?,
3378
3392
3379
3393
// Look in an imported module for a binding with this name
3380
3394
Some ( ( module_name, module_location) ) => {
@@ -3502,7 +3516,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3502
3516
}
3503
3517
}
3504
3518
3505
- fn report_name_error ( & mut self , name : & EcoString , location : & SrcSpan ) -> Error {
3519
+ fn report_name_error (
3520
+ & mut self ,
3521
+ name : & EcoString ,
3522
+ location : & SrcSpan ,
3523
+ var_usage : VarUsage ,
3524
+ ) -> Error {
3506
3525
// First try to see if this is a module alias:
3507
3526
// `import gleam/io`
3508
3527
// `io.debug(io)`
@@ -3513,30 +3532,59 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3513
3532
location : * location,
3514
3533
name : name. clone ( ) ,
3515
3534
} ,
3516
- None => Error :: UnknownVariable {
3517
- location : * location,
3518
- name : name. clone ( ) ,
3519
- variables : self . environment . local_value_names ( ) ,
3520
- discarded_location : self
3521
- . environment
3522
- . discarded_names
3523
- . get ( & eco_format ! ( "_{name}" ) )
3524
- . cloned ( ) ,
3525
- type_with_name_in_scope : self
3526
- . environment
3527
- . module_types
3528
- . keys ( )
3529
- . any ( |typ| typ == name) ,
3530
- imported_modules_with_same_public_variable_name : self
3531
- . environment
3532
- . imported_modules
3533
- . iter ( )
3534
- . filter_map ( |( module_name, ( _, module) ) | {
3535
- module. get_public_value ( name) . map ( |_| module_name)
3536
- } )
3537
- . cloned ( )
3538
- . collect_vec ( ) ,
3539
- } ,
3535
+ None => {
3536
+ let imported_modules_with_same_public_variable_name = match var_usage {
3537
+ // This is a function call, we need to suggest a public
3538
+ // variable which is a function with the correct arity
3539
+ VarUsage :: Call { arity } => self
3540
+ . environment
3541
+ . imported_modules
3542
+ . iter ( )
3543
+ . filter_map ( |( module_name, ( _, module) ) | {
3544
+ module
3545
+ . get_public_value ( name)
3546
+ . filter ( |value_constructor| {
3547
+ match value_constructor. type_ . fn_types ( ) {
3548
+ Some ( ( fn_arguments_type, _) ) => {
3549
+ fn_arguments_type. len ( ) == arity
3550
+ }
3551
+ None => false ,
3552
+ }
3553
+ } )
3554
+ . map ( |_| module_name)
3555
+ } )
3556
+ . cloned ( )
3557
+ . collect_vec ( ) ,
3558
+ // This is a reference to a variable, we need to suggest
3559
+ // public variables of any type
3560
+ VarUsage :: Other => self
3561
+ . environment
3562
+ . imported_modules
3563
+ . iter ( )
3564
+ . filter_map ( |( module_name, ( _, module) ) | {
3565
+ module. get_public_value ( name) . map ( |_| module_name)
3566
+ } )
3567
+ . cloned ( )
3568
+ . collect_vec ( ) ,
3569
+ } ;
3570
+
3571
+ Error :: UnknownVariable {
3572
+ location : * location,
3573
+ name : name. clone ( ) ,
3574
+ variables : self . environment . local_value_names ( ) ,
3575
+ discarded_location : self
3576
+ . environment
3577
+ . discarded_names
3578
+ . get ( & eco_format ! ( "_{name}" ) )
3579
+ . cloned ( ) ,
3580
+ type_with_name_in_scope : self
3581
+ . environment
3582
+ . module_types
3583
+ . keys ( )
3584
+ . any ( |typ| typ == name) ,
3585
+ imported_modules_with_same_public_variable_name,
3586
+ }
3587
+ }
3540
3588
}
3541
3589
}
3542
3590
@@ -3594,7 +3642,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3594
3642
..
3595
3643
} if arguments. is_empty ( ) => {
3596
3644
// Type check the record constructor
3597
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3645
+ let constructor =
3646
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3598
3647
3599
3648
let ( tag, field_map) = match & constructor. variant {
3600
3649
ValueConstructorVariant :: Record {
@@ -3633,7 +3682,14 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3633
3682
// field_map, is always None here because untyped not yet unified
3634
3683
..
3635
3684
} => {
3636
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3685
+ let constructor = self . infer_value_constructor (
3686
+ & module,
3687
+ & name,
3688
+ & location,
3689
+ VarUsage :: Call {
3690
+ arity : arguments. len ( ) ,
3691
+ } ,
3692
+ ) ?;
3637
3693
3638
3694
let ( tag, field_map, variant_index) = match & constructor. variant {
3639
3695
ValueConstructorVariant :: Record {
@@ -3775,7 +3831,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3775
3831
..
3776
3832
} => {
3777
3833
// Infer the type of this constant
3778
- let constructor = self . infer_value_constructor ( & module, & name, & location) ?;
3834
+ let constructor =
3835
+ self . infer_value_constructor ( & module, & name, & location, VarUsage :: Other ) ?;
3779
3836
match constructor. variant {
3780
3837
ValueConstructorVariant :: ModuleConstant { .. }
3781
3838
| ValueConstructorVariant :: LocalConstant { .. }
@@ -3952,6 +4009,30 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
3952
4009
kind : CallKind ,
3953
4010
) -> ( TypedExpr , Vec < TypedCallArg > , Arc < Type > ) {
3954
4011
let fun = match fun {
4012
+ UntypedExpr :: Var { location, name } => {
4013
+ // Because we are not calling infer / infer_or_error directly,
4014
+ // we do not warn if there was a previous panic. Check for that
4015
+ // here. Not perfect, but works.
4016
+ if self . previous_panics {
4017
+ self . warn_for_unreachable_code ( location, PanicPosition :: PreviousExpression ) ;
4018
+ }
4019
+
4020
+ match self . infer_var (
4021
+ name,
4022
+ location,
4023
+ VarUsage :: Call {
4024
+ arity : arguments. len ( ) ,
4025
+ } ,
4026
+ ReferenceRegistration :: RegisterReferences ,
4027
+ ) {
4028
+ Ok ( typed_expr) => typed_expr,
4029
+ Err ( error) => {
4030
+ self . problems . error ( error) ;
4031
+ self . error_expr ( location)
4032
+ }
4033
+ }
4034
+ }
4035
+
3955
4036
UntypedExpr :: FieldAccess {
3956
4037
label,
3957
4038
container,
0 commit comments