@@ -1990,6 +1990,8 @@ namespace {
19901990 }
19911991
19921992 bool diagnoseMoveOnly (TypeRepr *repr, Type genericArgTy);
1993+ bool diagnoseMoveOnlyMissingOwnership (TypeRepr *repr,
1994+ TypeResolutionOptions options);
19931995
19941996 bool diagnoseDisallowedExistential (TypeRepr *repr);
19951997
@@ -2044,7 +2046,7 @@ namespace {
20442046 Optional<SILResultInfo> &errorResult);
20452047 NeverNullType resolveDeclRefTypeRepr (DeclRefTypeRepr *repr,
20462048 TypeResolutionOptions options);
2047- NeverNullType resolveSpecifierTypeRepr (SpecifierTypeRepr *repr,
2049+ NeverNullType resolveOwnershipTypeRepr (OwnershipTypeRepr *repr,
20482050 TypeResolutionOptions options);
20492051 NeverNullType resolveIsolatedTypeRepr (IsolatedTypeRepr *repr,
20502052 TypeResolutionOptions options);
@@ -2250,6 +2252,51 @@ bool TypeResolver::diagnoseMoveOnly(TypeRepr *repr, Type genericArgTy) {
22502252 return false ;
22512253}
22522254
2255+ // / Assuming this repr has resolved to a move-only / noncopyable type, checks
2256+ // / to see if that resolution happened in a context requiring an ownership
2257+ // / annotation. If it did and there was no ownership specified, emits a
2258+ // / diagnostic.
2259+ // /
2260+ // / \returns true if an error diagnostic was emitted
2261+ bool TypeResolver::diagnoseMoveOnlyMissingOwnership (
2262+ TypeRepr *repr,
2263+ TypeResolutionOptions options) {
2264+ // only required on function inputs.
2265+ // we can ignore InoutFunctionInput since it's already got ownership.
2266+ if (!options.is (TypeResolverContext::FunctionInput))
2267+ return false ;
2268+
2269+ // enum cases don't need to specify ownership for associated values
2270+ if (options.hasBase (TypeResolverContext::EnumElementDecl))
2271+ return false ;
2272+
2273+ // otherwise, we require ownership.
2274+ if (options.contains (TypeResolutionFlags::HasOwnership))
2275+ return false ;
2276+
2277+ diagnose (repr->getLoc (),
2278+ diag::moveonly_parameter_missing_ownership);
2279+
2280+ // FIXME: this should be 'borrowing'
2281+ diagnose (repr->getLoc (), diag::moveonly_parameter_ownership_suggestion,
2282+ " __shared" , " for an immutable reference" )
2283+ .fixItInsert (repr->getStartLoc (), " __shared " );
2284+
2285+ diagnose (repr->getLoc (), diag::moveonly_parameter_ownership_suggestion,
2286+ " inout" , " for a mutable reference" )
2287+ .fixItInsert (repr->getStartLoc (), " inout " );
2288+
2289+ // FIXME: this should be 'consuming'
2290+ diagnose (repr->getLoc (), diag::moveonly_parameter_ownership_suggestion,
2291+ " __owned" , " to take the value from callers" )
2292+ .fixItInsert (repr->getStartLoc (), " __owned " );
2293+
2294+ // to avoid duplicate diagnostics
2295+ repr->setInvalid ();
2296+
2297+ return true ;
2298+ }
2299+
22532300NeverNullType TypeResolver::resolveType (TypeRepr *repr,
22542301 TypeResolutionOptions options) {
22552302 assert (repr && " Cannot validate null TypeReprs!" );
@@ -2284,7 +2331,7 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
22842331 case TypeReprKind::InOut:
22852332 case TypeReprKind::Shared:
22862333 case TypeReprKind::Owned:
2287- return resolveSpecifierTypeRepr (cast<SpecifierTypeRepr >(repr), options);
2334+ return resolveOwnershipTypeRepr (cast<OwnershipTypeRepr >(repr), options);
22882335
22892336 case TypeReprKind::Isolated:
22902337 return resolveIsolatedTypeRepr (cast<IsolatedTypeRepr>(repr), options);
@@ -4146,6 +4193,10 @@ TypeResolver::resolveDeclRefTypeRepr(DeclRefTypeRepr *repr,
41464193 }
41474194 }
41484195
4196+ // move-only types must have an ownership specifier when used as a parameter of a function.
4197+ if (result->isPureMoveOnly ())
4198+ diagnoseMoveOnlyMissingOwnership (repr, options);
4199+
41494200 // Hack to apply context-specific @escaping to a typealias with an underlying
41504201 // function type.
41514202 if (result->is <FunctionType>())
@@ -4155,9 +4206,9 @@ TypeResolver::resolveDeclRefTypeRepr(DeclRefTypeRepr *repr,
41554206}
41564207
41574208NeverNullType
4158- TypeResolver::resolveSpecifierTypeRepr (SpecifierTypeRepr *repr,
4209+ TypeResolver::resolveOwnershipTypeRepr (OwnershipTypeRepr *repr,
41594210 TypeResolutionOptions options) {
4160- // inout is only valid for (non-Subscript and non-EnumCaseDecl)
4211+ // ownership is only valid for (non-Subscript and non-EnumCaseDecl)
41614212 // function parameters.
41624213 if (!options.is (TypeResolverContext::FunctionInput) ||
41634214 options.hasBase (TypeResolverContext::SubscriptDecl) ||
@@ -4177,10 +4228,10 @@ TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
41774228 name = " inout" ;
41784229 break ;
41794230 case TypeReprKind::Shared:
4180- name = " __shared" ;
4231+ name = " __shared" ; // FIXME: use 'borrowing'
41814232 break ;
41824233 case TypeReprKind::Owned:
4183- name = " __owned" ;
4234+ name = " __owned" ; // FIXME: use 'consuming'
41844235 break ;
41854236 default :
41864237 llvm_unreachable (" unknown SpecifierTypeRepr kind" );
@@ -4195,6 +4246,9 @@ TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
41954246 options.setContext (TypeResolverContext::InoutFunctionInput);
41964247 }
41974248
4249+ // Remember that we've seen an ownership specifier for this base type.
4250+ options |= TypeResolutionFlags::HasOwnership;
4251+
41984252 return resolveType (repr->getBase (), options);
41994253}
42004254
0 commit comments