@@ -12,6 +12,7 @@ use crate::{
12
12
Signedness , UnaryOp , UnresolvedGeneric , UnresolvedGenerics , UnresolvedType ,
13
13
UnresolvedTypeData , UnresolvedTypeExpression , WILDCARD_TYPE ,
14
14
} ,
15
+ elaborator:: UnstableFeature ,
15
16
hir:: {
16
17
def_collector:: dc_crate:: CompilationError ,
17
18
def_map:: { ModuleDefId , fully_qualified_module_path} ,
@@ -141,8 +142,11 @@ impl Elaborator<'_> {
141
142
}
142
143
}
143
144
}
144
- MutableReference ( element) => {
145
- Type :: MutableReference ( Box :: new ( self . resolve_type_inner ( * element, kind) ) )
145
+ Reference ( element, mutable) => {
146
+ if !mutable {
147
+ self . use_unstable_feature ( UnstableFeature :: Ownership , location) ;
148
+ }
149
+ Type :: Reference ( Box :: new ( self . resolve_type_inner ( * element, kind) ) , mutable)
146
150
}
147
151
Parenthesized ( typ) => self . resolve_type_inner ( * typ, kind) ,
148
152
Resolved ( id) => self . interner . get_quoted_type ( id) . clone ( ) ,
@@ -845,7 +849,7 @@ impl Elaborator<'_> {
845
849
/// Insert as many dereference operations as necessary to automatically dereference a method
846
850
/// call object to its base value type T.
847
851
pub ( super ) fn insert_auto_dereferences ( & mut self , object : ExprId , typ : Type ) -> ( ExprId , Type ) {
848
- if let Type :: MutableReference ( element) = typ. follow_bindings ( ) {
852
+ if let Type :: Reference ( element, _mut ) = typ. follow_bindings ( ) {
849
853
let location = self . interner . id_location ( object) ;
850
854
851
855
let object = self . interner . push_expr ( HirExpression :: Prefix ( HirPrefixExpression {
@@ -1304,17 +1308,26 @@ impl Elaborator<'_> {
1304
1308
_ => Ok ( ( rhs_type. clone ( ) , true ) ) ,
1305
1309
}
1306
1310
}
1307
- crate :: ast:: UnaryOp :: MutableReference => {
1308
- Ok ( ( Type :: MutableReference ( Box :: new ( rhs_type. follow_bindings ( ) ) ) , false ) )
1311
+ crate :: ast:: UnaryOp :: Reference { mutable } => {
1312
+ let typ = Type :: Reference ( Box :: new ( rhs_type. follow_bindings ( ) ) , * mutable) ;
1313
+ Ok ( ( typ, false ) )
1309
1314
}
1310
1315
crate :: ast:: UnaryOp :: Dereference { implicitly_added : _ } => {
1311
1316
let element_type = self . interner . next_type_variable ( ) ;
1312
- let expected = Type :: MutableReference ( Box :: new ( element_type. clone ( ) ) ) ;
1313
- self . unify ( rhs_type, & expected, || TypeCheckError :: TypeMismatch {
1314
- expr_typ : rhs_type. to_string ( ) ,
1315
- expected_typ : expected. to_string ( ) ,
1316
- expr_location : location,
1317
- } ) ;
1317
+ let make_expected =
1318
+ |mutable| Type :: Reference ( Box :: new ( element_type. clone ( ) ) , mutable) ;
1319
+
1320
+ let immutable = make_expected ( false ) ;
1321
+ let mutable = make_expected ( true ) ;
1322
+
1323
+ // Both `&mut T` and `&T` should coerce to an expected `&T`.
1324
+ if !rhs_type. try_reference_coercion ( & immutable) {
1325
+ self . unify ( rhs_type, & mutable, || TypeCheckError :: TypeMismatch {
1326
+ expr_typ : rhs_type. to_string ( ) ,
1327
+ expected_typ : mutable. to_string ( ) ,
1328
+ expr_location : location,
1329
+ } ) ;
1330
+ }
1318
1331
Ok ( ( element_type, false ) )
1319
1332
}
1320
1333
}
@@ -1437,9 +1450,9 @@ impl Elaborator<'_> {
1437
1450
Type :: NamedGeneric ( _, _) => {
1438
1451
self . lookup_method_in_trait_constraints ( object_type, method_name, location)
1439
1452
}
1440
- // Mutable references to another type should resolve to methods of their element type.
1453
+ // References to another type should resolve to methods of their element type.
1441
1454
// This may be a data type or a primitive type.
1442
- Type :: MutableReference ( element) => {
1455
+ Type :: Reference ( element, _mutable ) => {
1443
1456
self . lookup_method ( & element, method_name, location, check_self_param)
1444
1457
}
1445
1458
@@ -1836,12 +1849,12 @@ impl Elaborator<'_> {
1836
1849
if let Some ( expected_object_type) = expected_object_type {
1837
1850
let actual_type = object_type. follow_bindings ( ) ;
1838
1851
1839
- if matches ! ( expected_object_type . follow_bindings ( ) , Type :: MutableReference ( _ ) ) {
1840
- if !matches ! ( actual_type, Type :: MutableReference ( _ ) ) {
1852
+ if let Type :: Reference ( _ , mutable ) = expected_object_type . follow_bindings ( ) {
1853
+ if !matches ! ( actual_type, Type :: Reference ( .. ) ) {
1841
1854
let location = self . interner . id_location ( * object) ;
1842
1855
self . check_can_mutate ( * object, location) ;
1843
1856
1844
- let new_type = Type :: MutableReference ( Box :: new ( actual_type) ) ;
1857
+ let new_type = Type :: Reference ( Box :: new ( actual_type) , mutable ) ;
1845
1858
* object_type = new_type. clone ( ) ;
1846
1859
1847
1860
// First try to remove a dereference operator that may have been implicitly
@@ -1852,7 +1865,7 @@ impl Elaborator<'_> {
1852
1865
* object = new_object. unwrap_or_else ( || {
1853
1866
let new_object =
1854
1867
self . interner . push_expr ( HirExpression :: Prefix ( HirPrefixExpression {
1855
- operator : UnaryOp :: MutableReference ,
1868
+ operator : UnaryOp :: Reference { mutable } ,
1856
1869
rhs : * object,
1857
1870
trait_method_id : None ,
1858
1871
} ) ) ;
@@ -1863,7 +1876,7 @@ impl Elaborator<'_> {
1863
1876
}
1864
1877
// Otherwise if the object type is a mutable reference and the method is not, insert as
1865
1878
// many dereferences as needed.
1866
- } else if matches ! ( actual_type, Type :: MutableReference ( _ ) ) {
1879
+ } else if matches ! ( actual_type, Type :: Reference ( .. ) ) {
1867
1880
let ( new_object, new_type) = self . insert_auto_dereferences ( * object, actual_type) ;
1868
1881
* object_type = new_type;
1869
1882
* object = new_object;
0 commit comments