-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c599c1
commit 5a6a18f
Showing
12 changed files
with
2,098 additions
and
2 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
<html> | ||
<head> | ||
<meta http-equiv="refresh" content="0; URL=P3390R0.html"> | ||
<meta http-equiv="refresh" content="0; URL=draft.html"> | ||
</head> | ||
<body> | ||
Automatic redirection failed, please go to | ||
<a href="P3390R0.html">P3390R0.html</a>. | ||
<a href="draft.html">draft.html</a>. | ||
</body> | ||
</html> |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#feature on safety | ||
|
||
// Function parameters have different lifetime parameters. | ||
// Return type is constrained by x's lifetime. | ||
auto f1/(a, b)(int^/a x, int^/b y, bool pred) safe -> int^/a { | ||
// Error: | ||
// function auto f1/(a, b)(int^/a, int^/b) -> int^/a returns | ||
// object with lifetime b, but b doesn't outlive a | ||
// return y; | ||
return pred ? x : y; | ||
} | ||
|
||
// Function parameters have a common lifetime parameter. | ||
auto f2/(a)(int^/a x, int^/a y, bool pred) safe -> int^/a { | ||
// Ok | ||
return pred ? x : y; | ||
} | ||
|
||
// Error: | ||
// cannot use lifetime elision for return type int^ | ||
auto f3(int^ x, int^ y) safe -> int^; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#feature on safety | ||
|
||
// New elision rules: | ||
// All parameters are constrained by a common lifetime. | ||
// The common lifetime constrains the return type. | ||
int% f4(int% x, int% y, bool pred) safe { | ||
// Can return either x or y, because they outlive the common lifetime | ||
// and the common lifetime outlives the result object. | ||
return pred ? x : y; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#feature on safety | ||
|
||
const int% f1(const int% x, const int% y, bool pred) safe { | ||
// The return reference is constrained by all reference parameters: x and y. | ||
return pred ? x : y; | ||
} | ||
|
||
struct Obj { | ||
const int% f2(const int% arg) const % safe { | ||
// Non-static member functions are constrained by the implicit | ||
// object lifetime. | ||
// It's OK to return `x`, because self outlives the return. | ||
return %x; | ||
} | ||
|
||
const int% f3(const int% arg) const % safe { | ||
// Error: arg does not outlive the return reference. | ||
return arg; | ||
} | ||
|
||
const int% f4(const self%, const int% arg) safe { | ||
// OK - f4 is a free function with an explicit self parameter. | ||
return arg; | ||
} | ||
|
||
int x; | ||
}; | ||
|
||
int main() { | ||
int x = 1, y = 2; | ||
f1(x, y, true); // OK | ||
|
||
Obj obj { }; | ||
obj.f2(x); // OK | ||
obj.f3(x); // Error | ||
obj.f4(x); // OK. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#feature on safety |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#feature on safety | ||
|
||
class string_view/(a) { | ||
// Keep a borrow to a slice over the string data. | ||
const [char; dyn]^/a p_; | ||
public: | ||
}; | ||
|
||
class info/(a) { | ||
// The handle has lifetime /a. | ||
string_view/a sv; | ||
|
||
public: | ||
void swap(self^, info^ rhs) safe { | ||
string_view temp = self->sv; | ||
self->sv = rhs->sv; | ||
rhs->sv = temp; | ||
} | ||
}; | ||
|
||
void func/(a)(info/a^ lhs, info/a^ rhs) safe { | ||
lhs.swap(rhs); | ||
} | ||
|
||
void func2(info^ lhs, info^ rhs) safe { | ||
lhs.swap(rhs); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <vector> | ||
|
||
void f1(std::vector<float>& vec, float& x) { | ||
// Do vec and x alias? If so, the push_back may invalidate x. | ||
vec.push_back(6); | ||
|
||
// Potential UB: x may have been invalidated by the push_back. | ||
x = 6; | ||
} | ||
|
||
int main() { | ||
std::vector<float> vec; | ||
vec.push_back(1): | ||
|
||
// Legacy references permit aliasing. | ||
f1(vec, vec[0]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#feature on safety | ||
#include <cstdint> | ||
|
||
template<typename T> | ||
class Vec { | ||
public: | ||
void push_back(T value) % safe; | ||
|
||
const T% operator[](size_t idx) const % safe; | ||
T% operator[](size_t idx) % safe; | ||
}; | ||
|
||
void f2(Vec<float>% vec, float% x) safe { | ||
// Does push_back potentially invalidate x? | ||
// No! Exclusivity prevents vec and x from aliasing. | ||
vec.push_back(7); | ||
|
||
// Okay to store to x, because it doesn't point into vec's data. | ||
*x = 7; | ||
} | ||
|
||
int main() safe { | ||
Vec<float> vec { }; | ||
mut vec.push_back(1); | ||
|
||
// Ill-formed: shared borrow of vec between its mutable borrow and its use | ||
f2(mut vec, mut vec[0]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#feature on safety | ||
|
||
template<typename Key, typename Value> | ||
class Map { | ||
public: | ||
// Non-static member functions do not constrain the result object to | ||
// the function parameters. | ||
auto get1(const Key% key) % safe -> Value%; | ||
|
||
// Free function do constrain the result object to the f unction praameters. | ||
auto get2(self%, const Key% key) safe -> Value%; | ||
}; | ||
|
||
int main() safe { | ||
Map<float, long> map { }; | ||
|
||
// Bind the key reference to a materialized temporary. | ||
// The temporary expires at the end of this statement. | ||
long% value1 = mut map.get1(3.14f); | ||
|
||
// We can still access value, because it's not constrained on the | ||
// key argument. | ||
*value1 = 1001; | ||
|
||
// The call to get2 constrains the returned reference to the lifetime | ||
// of the key temporary. | ||
long% value2 = mut map.get2(1.6186f); | ||
|
||
// This is ill-formed, because get2's key argument is out of scope. | ||
*value2 = 1002; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#feature on safety | ||
|
||
template<typename Key, typename Value> | ||
class Map { | ||
public: | ||
// Lifetime elision rules constrain the return by self. | ||
auto get1(self^, const Key^ key) safe -> Value^; | ||
|
||
// Use explicit parameterizations for alternate constraints. | ||
auto get2/(a)(self^/a, const Key^/a key) safe -> Value^/a; | ||
}; | ||
|
||
int main() safe { | ||
Map<float, long> map { }; | ||
|
||
// Bind the key reference to a materialized temporary. | ||
// The temporary expires at the end of this statement. | ||
long^ value1 = mut map.get1(3.14f); | ||
|
||
// We can still access value, because it's not constrained on the | ||
// key argument. | ||
*value1 = 1001; | ||
|
||
// The call to get2 constrains the returned reference to the lifetime | ||
// of the key temporary. | ||
long^ value2 = mut map.get2(1.6186f); | ||
|
||
// This is ill-formed, because get2's key argument is out of scope. | ||
*value2 = 1002; | ||
} |