Files
swift-mirror/test/Interop/Cxx/class/nonescapable-errors.swift
Gabor Horvath 6b24af65f0 [cxx-interop] Always import the lifetime annotations
Importing these annotations were behind the LifetimeDependence
experimental flag. However, this feature flag is intended to guard the
use of @lifetime annotations on the Swift side and lifetime inference.
The checking of imported lifetime contracts should work even when this
flag is off. Removing the flag from the importer caused some fallout.
This was mostly due to calling getInterfaceType functions before the
import of some Swift declarations were fully done so the code was
slightly improved to make decisions only based on the C++ types.
There was also a crash when on-member functions imported as methods into
Swift. That is worked around in this PR.

There is one last feature check that we cannot remove yet, we generate
@lifetime annotations in the SwiftifyImport macro.
2025-03-05 15:36:59 +00:00

166 lines
7.2 KiB
Swift

// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: not %target-swift-frontend -typecheck -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift -enable-experimental-feature LifetimeDependence -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 | %FileCheck %s
// RUN: not %target-swift-frontend -typecheck -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift -cxx-interoperability-mode=default -diagnostic-style llvm 2>&1 | %FileCheck %s -check-prefix=CHECK-NO-LIFETIMES
// REQUIRES: swift_feature_LifetimeDependence
//--- Inputs/module.modulemap
module Test {
header "nonescapable.h"
requires cplusplus
}
//--- Inputs/nonescapable.h
#include "swift/bridging"
#include <vector>
struct SWIFT_NONESCAPABLE View {
View() : member(nullptr) {}
View(const int *p [[clang::lifetimebound]]) : member(p) {}
View(const View&) = default;
private:
const int *member;
};
struct SWIFT_ESCAPABLE Owner {
int data;
};
Owner f(int* x [[clang::lifetimebound]]) {
return Owner{0};
}
Owner f2(int* x [[clang::lifetimebound]], int* y [[clang::lifetimebound]]) {
return Owner{0};
}
View g(int* x) {
return View(x);
}
template<typename F, typename S>
struct SWIFT_ESCAPABLE_IF(F, S) MyPair {
F first;
S second;
};
MyPair<View, Owner> h1(int* x);
MyPair<Owner, View> h2(int* x);
MyPair<Owner, Owner> h3(int* x);
template<typename F, typename S>
struct SWIFT_ESCAPABLE_IF(F, Missing) MyPair2 {
F first;
S second;
};
template<typename F, int S>
struct SWIFT_ESCAPABLE_IF(F, S) MyType {
F field;
};
MyPair2<Owner, Owner> i1();
MyType<Owner, 0> i2();
template<typename T>
struct Outer {
struct NonTemplated {
template <typename S>
struct SWIFT_ESCAPABLE_IF(T, S) Inner {
T t;
S s;
};
};
};
Outer<View>::NonTemplated::Inner<Owner> j1();
Outer<Owner>::NonTemplated::Inner<View> j2();
Outer<Owner>::NonTemplated::Inner<Owner> j3();
template<typename... Ts>
struct SWIFT_ESCAPABLE_IF(Ts) MyTuple {};
MyTuple<View> k1();
MyTuple<Owner, View> k2();
MyTuple<Owner, Owner> k3();
using ViewVector = std::vector<View>;
using OwnerVector = std::vector<Owner>;
ViewVector l1();
OwnerVector l2();
const View* usedToCrash(const View* p) {
return p;
}
//--- test.swift
import Test
import CxxStdlib
// CHECK: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: test.swift:6:32: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
public func noAnnotations() -> View {
// CHECK: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies
// CHECK-NO-LIFETIMES: nonescapable.h:16:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies
f(nil)
// CHECK: nonescapable.h:20:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies
// CHECK-NO-LIFETIMES: nonescapable.h:20:7: warning: the returned type 'Owner' is annotated as escapable; it cannot have lifetime dependencies
// No duplicate warning for f2:
// CHECK-NOT: nonescapable.h:20
f2(nil, nil)
// CHECK: nonescapable.h:24:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated
// CHECK: nonescapable.h:24:6: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:24:6: warning: the returned type 'View' is annotated as non-escapable; its lifetime dependencies must be annotated
// CHECK-NO-LIFETIMES: nonescapable.h:24:6: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
g(nil)
h1(nil)
// CHECK: nonescapable.h:34:21: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:34:21: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
h2(nil)
// CHECK: nonescapable.h:35:21: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:35:21: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
h3(nil)
i1()
// CHECK: nonescapable.h:39:39: error: template parameter 'Missing' does not exist
// CHECK-NO-LIFETIMES: nonescapable.h:39:39: error: template parameter 'Missing' does not exist
i2()
// CHECK: nonescapable.h:45:33: error: template parameter 'S' expected to be a type parameter
// CHECK-NO-LIFETIMES: nonescapable.h:45:33: error: template parameter 'S' expected to be a type parameter
j1()
// CHECK: nonescapable.h:63:41: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:63:41: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
j2()
// CHECK: nonescapable.h:64:41: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:64:41: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
j3()
k1();
// CHECK: nonescapable.h:70:15: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:70:15: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
k2();
// CHECK: nonescapable.h:71:22: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:71:22: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
k3();
l1();
// CHECK: nonescapable.h:77:12: error: cannot infer lifetime dependence, no parameters found that are either ~Escapable or Escapable with a borrowing ownership
// CHECK-NO-LIFETIMES: nonescapable.h:77:12: error: returning ~Escapable type requires '-enable-experimental-feature LifetimeDependence'
l2();
return View()
}
public func test3(_ x: inout View) {
usedToCrash(&x)
// CHECK: error: cannot find 'usedToCrash' in scope
// CHECK: note: function 'usedToCrash' unavailable (cannot import)
// CHECK: note: return type unavailable (cannot import)
// CHECK: pointer to non-escapable type 'View' cannot be imported
// CHECK-NO-LIFETIMES: error: cannot find 'usedToCrash' in scope
// CHECK-NO-LIFETIMES: note: function 'usedToCrash' unavailable (cannot import)
// CHECK-NO-LIFETIMES: note: return type unavailable (cannot import)
// CHECK-NO-LIFETIMES: pointer to non-escapable type 'View' cannot be imported
}
// CHECK-NOT: error
// CHECK-NOT: warning
// CHECK-NO-LIFETIMES-NOT: error
// CHECK-NO-LIFETIMES-NOT: warning