@@ -2854,47 +2854,64 @@ bool TypeChecker::isSubstitutableFor(Type type, ArchetypeType *archetype,
2854
2854
return true ;
2855
2855
}
2856
2856
2857
- Expr *TypeChecker::coerceToMaterializable (Expr *expr) {
2857
+ Expr *TypeChecker::coerceToMaterializable (Expr *expr,
2858
+ llvm::function_ref<Type(Expr *)> getType,
2859
+ llvm::function_ref<void(Expr *, Type)> setType) {
2860
+ Type exprTy = getType (expr);
2861
+
2858
2862
// If expr has no type, just assume it's the right expr.
2863
+ if (!exprTy)
2864
+ return expr;
2865
+
2859
2866
// If the type is already materializable, then we're already done.
2860
- if (!expr-> getType () || expr-> getType () ->isMaterializable ())
2867
+ if (exprTy ->isMaterializable ())
2861
2868
return expr;
2862
2869
2863
2870
// Load lvalues.
2864
- if (auto lvalue = expr-> getType () ->getAs <LValueType>()) {
2871
+ if (auto lvalue = exprTy ->getAs <LValueType>()) {
2865
2872
expr->propagateLValueAccessKind (AccessKind::Read);
2866
- return new (Context) LoadExpr (expr, lvalue->getObjectType ());
2873
+ auto result = new (Context) LoadExpr (expr, lvalue->getObjectType ());
2874
+ setType (result, lvalue->getObjectType ());
2875
+ return result;
2867
2876
}
2868
2877
2869
2878
// Walk into parenthesized expressions to update the subexpression.
2870
2879
if (auto paren = dyn_cast<IdentityExpr>(expr)) {
2871
- auto sub = coerceToMaterializable (paren->getSubExpr ());
2880
+ auto sub = coerceToMaterializable (paren->getSubExpr (), getType, setType );
2872
2881
paren->setSubExpr (sub);
2873
- paren-> setType (sub-> getType ());
2882
+ setType (paren, getType (sub ));
2874
2883
return paren;
2875
2884
}
2876
2885
2877
2886
// Walk into 'try' and 'try!' expressions to update the subexpression.
2878
2887
if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
2879
- auto sub = coerceToMaterializable (tryExpr->getSubExpr ());
2888
+ auto sub = coerceToMaterializable (tryExpr->getSubExpr (), getType, setType );
2880
2889
tryExpr->setSubExpr (sub);
2881
- if (isa<OptionalTryExpr>(tryExpr) && !sub-> getType ()->hasError ())
2882
- tryExpr-> setType (OptionalType::get (sub-> getType ()));
2890
+ if (isa<OptionalTryExpr>(tryExpr) && !getType (sub )->hasError ())
2891
+ setType (tryExpr, OptionalType::get (getType (sub )));
2883
2892
else
2884
- tryExpr-> setType (sub-> getType ());
2893
+ setType (tryExpr, getType (sub ));
2885
2894
return tryExpr;
2886
2895
}
2887
2896
2897
+ // Can't load from an inout value.
2898
+ if (auto inoutExpr = dyn_cast<InOutExpr>(expr)) {
2899
+ diagnose (expr->getLoc (), diag::load_of_explicit_lvalue,
2900
+ exprTy->castTo <InOutType>()->getObjectType ())
2901
+ .fixItRemove (SourceRange (inoutExpr->getLoc ()));
2902
+ return coerceToMaterializable (inoutExpr->getSubExpr (), getType, setType);
2903
+ }
2904
+
2888
2905
// Walk into tuples to update the subexpressions.
2889
2906
if (auto tuple = dyn_cast<TupleExpr>(expr)) {
2890
2907
bool anyChanged = false ;
2891
2908
for (auto &elt : tuple->getElements ()) {
2892
2909
// Materialize the element.
2893
- auto oldType = elt-> getType ();
2894
- elt = coerceToMaterializable (elt);
2910
+ auto oldType = getType (elt );
2911
+ elt = coerceToMaterializable (elt, getType, setType );
2895
2912
2896
2913
// If the type changed at all, make a note of it.
2897
- if (elt-> getType ().getPointer () != oldType.getPointer ()) {
2914
+ if (getType (elt ).getPointer () != oldType.getPointer ()) {
2898
2915
anyChanged = true ;
2899
2916
}
2900
2917
}
@@ -2904,11 +2921,11 @@ Expr *TypeChecker::coerceToMaterializable(Expr *expr) {
2904
2921
SmallVector<TupleTypeElt, 4 > elements;
2905
2922
elements.reserve (tuple->getElements ().size ());
2906
2923
for (unsigned i = 0 , n = tuple->getNumElements (); i != n; ++i) {
2907
- Type type = tuple->getElement (i)-> getType ( );
2924
+ Type type = getType ( tuple->getElement (i));
2908
2925
Identifier name = tuple->getElementName (i);
2909
2926
elements.push_back (TupleTypeElt (type, name));
2910
2927
}
2911
- tuple-> setType (TupleType::get (elements, Context));
2928
+ setType (tuple, TupleType::get (elements, Context));
2912
2929
}
2913
2930
2914
2931
return tuple;
0 commit comments