@@ -5,8 +5,8 @@ use rustc_hash::FxHashSet as HashSet;
5
5
6
6
use crate :: {
7
7
ast:: {
8
- ArrayLiteral , ConstructorExpression , IfExpression , InfixExpression , Lambda ,
9
- UnresolvedTypeExpression ,
8
+ ArrayLiteral , ConstructorExpression , IfExpression , InfixExpression , Lambda , UnaryOp ,
9
+ UnresolvedTypeData , UnresolvedTypeExpression ,
10
10
} ,
11
11
hir:: {
12
12
comptime:: { self , InterpreterError } ,
@@ -25,9 +25,9 @@ use crate::{
25
25
macros_api:: {
26
26
BlockExpression , CallExpression , CastExpression , Expression , ExpressionKind , HirLiteral ,
27
27
HirStatement , Ident , IndexExpression , Literal , MemberAccessExpression ,
28
- MethodCallExpression , PrefixExpression ,
28
+ MethodCallExpression , PrefixExpression , StatementKind ,
29
29
} ,
30
- node_interner:: { DefinitionKind , ExprId , FuncId , TraitMethodId } ,
30
+ node_interner:: { DefinitionKind , ExprId , FuncId , InternedStatementKind , TraitMethodId } ,
31
31
token:: Tokens ,
32
32
QuotedType , Shared , StructType , Type ,
33
33
} ;
@@ -67,6 +67,9 @@ impl<'context> Elaborator<'context> {
67
67
let expr = Expression :: new ( expr_kind. clone ( ) , expr. span ) ;
68
68
return self . elaborate_expression ( expr) ;
69
69
}
70
+ ExpressionKind :: InternedStatement ( id) => {
71
+ return self . elaborate_interned_statement_as_expr ( id, expr. span ) ;
72
+ }
70
73
ExpressionKind :: Error => ( HirExpression :: Error , Type :: Error ) ,
71
74
ExpressionKind :: Unquote ( _) => {
72
75
self . push_err ( ResolverError :: UnquoteUsedOutsideQuote { span : expr. span } ) ;
@@ -80,6 +83,29 @@ impl<'context> Elaborator<'context> {
80
83
( id, typ)
81
84
}
82
85
86
+ fn elaborate_interned_statement_as_expr (
87
+ & mut self ,
88
+ id : InternedStatementKind ,
89
+ span : Span ,
90
+ ) -> ( ExprId , Type ) {
91
+ match self . interner . get_statement_kind ( id) {
92
+ StatementKind :: Expression ( expr) | StatementKind :: Semi ( expr) => {
93
+ self . elaborate_expression ( expr. clone ( ) )
94
+ }
95
+ StatementKind :: Interned ( id) => self . elaborate_interned_statement_as_expr ( * id, span) ,
96
+ StatementKind :: Error => {
97
+ let expr = Expression :: new ( ExpressionKind :: Error , span) ;
98
+ self . elaborate_expression ( expr)
99
+ }
100
+ other => {
101
+ let statement = other. to_string ( ) ;
102
+ self . push_err ( ResolverError :: InvalidInternedStatementInExpr { statement, span } ) ;
103
+ let expr = Expression :: new ( ExpressionKind :: Error , span) ;
104
+ self . elaborate_expression ( expr)
105
+ }
106
+ }
107
+ }
108
+
83
109
pub ( super ) fn elaborate_block ( & mut self , block : BlockExpression ) -> ( HirExpression , Type ) {
84
110
let ( block, typ) = self . elaborate_block_expression ( block) ;
85
111
( HirExpression :: Block ( block) , typ)
@@ -248,10 +274,17 @@ impl<'context> Elaborator<'context> {
248
274
}
249
275
250
276
fn elaborate_prefix ( & mut self , prefix : PrefixExpression , span : Span ) -> ( ExprId , Type ) {
277
+ let rhs_span = prefix. rhs . span ;
278
+
251
279
let ( rhs, rhs_type) = self . elaborate_expression ( prefix. rhs ) ;
252
280
let trait_id = self . interner . get_prefix_operator_trait_method ( & prefix. operator ) ;
253
281
254
282
let operator = prefix. operator ;
283
+
284
+ if let UnaryOp :: MutableReference = operator {
285
+ self . check_can_mutate ( rhs, rhs_span) ;
286
+ }
287
+
255
288
let expr =
256
289
HirExpression :: Prefix ( HirPrefixExpression { operator, rhs, trait_method_id : trait_id } ) ;
257
290
let expr_id = self . interner . push_expr ( expr) ;
@@ -264,6 +297,26 @@ impl<'context> Elaborator<'context> {
264
297
( expr_id, typ)
265
298
}
266
299
300
+ fn check_can_mutate ( & mut self , expr_id : ExprId , span : Span ) {
301
+ let expr = self . interner . expression ( & expr_id) ;
302
+ match expr {
303
+ HirExpression :: Ident ( hir_ident, _) => {
304
+ if let Some ( definition) = self . interner . try_definition ( hir_ident. id ) {
305
+ if !definition. mutable {
306
+ self . push_err ( TypeCheckError :: CannotMutateImmutableVariable {
307
+ name : definition. name . clone ( ) ,
308
+ span,
309
+ } ) ;
310
+ }
311
+ }
312
+ }
313
+ HirExpression :: MemberAccess ( member_access) => {
314
+ self . check_can_mutate ( member_access. lhs , span) ;
315
+ }
316
+ _ => ( ) ,
317
+ }
318
+ }
319
+
267
320
fn elaborate_index ( & mut self , index_expr : IndexExpression ) -> ( HirExpression , Type ) {
268
321
let span = index_expr. index . span ;
269
322
let ( index, index_type) = self . elaborate_expression ( index_expr. index ) ;
@@ -436,22 +489,43 @@ impl<'context> Elaborator<'context> {
436
489
& mut self ,
437
490
constructor : ConstructorExpression ,
438
491
) -> ( HirExpression , Type ) {
492
+ let span = constructor. typ . span ;
493
+
494
+ // A constructor type can either be a Path or an interned UnresolvedType.
495
+ // We represent both as UnresolvedType (with Path being a Named UnresolvedType)
496
+ // and error if we don't get a Named path.
497
+ let mut typ = constructor. typ . typ ;
498
+ if let UnresolvedTypeData :: Interned ( id) = typ {
499
+ typ = self . interner . get_unresolved_type_data ( id) . clone ( ) ;
500
+ }
501
+ let UnresolvedTypeData :: Named ( mut path, generics, _) = typ else {
502
+ self . push_err ( ResolverError :: NonStructUsedInConstructor { typ : typ. to_string ( ) , span } ) ;
503
+ return ( HirExpression :: Error , Type :: Error ) ;
504
+ } ;
505
+
506
+ let last_segment = path. segments . last_mut ( ) . unwrap ( ) ;
507
+ if !generics. ordered_args . is_empty ( ) {
508
+ last_segment. generics = Some ( generics. ordered_args ) ;
509
+ }
510
+
439
511
let exclude_last_segment = true ;
440
- self . check_unsupported_turbofish_usage ( & constructor . type_name , exclude_last_segment) ;
512
+ self . check_unsupported_turbofish_usage ( & path , exclude_last_segment) ;
441
513
442
- let span = constructor. type_name . span ( ) ;
443
- let last_segment = constructor. type_name . last_segment ( ) ;
514
+ let last_segment = path. last_segment ( ) ;
444
515
let is_self_type = last_segment. ident . is_self_type_name ( ) ;
445
516
446
517
let ( r#type, struct_generics) = if let Some ( struct_id) = constructor. struct_type {
447
518
let typ = self . interner . get_struct ( struct_id) ;
448
519
let generics = typ. borrow ( ) . instantiate ( self . interner ) ;
449
520
( typ, generics)
450
521
} else {
451
- match self . lookup_type_or_error ( constructor . type_name ) {
522
+ match self . lookup_type_or_error ( path ) {
452
523
Some ( Type :: Struct ( r#type, struct_generics) ) => ( r#type, struct_generics) ,
453
524
Some ( typ) => {
454
- self . push_err ( ResolverError :: NonStructUsedInConstructor { typ, span } ) ;
525
+ self . push_err ( ResolverError :: NonStructUsedInConstructor {
526
+ typ : typ. to_string ( ) ,
527
+ span,
528
+ } ) ;
455
529
return ( HirExpression :: Error , Type :: Error ) ;
456
530
}
457
531
None => return ( HirExpression :: Error , Type :: Error ) ,
0 commit comments