@@ -55,64 +55,13 @@ versions of .NET, just like they could in preview builds.
55
55
56
56
## Scenarios and User Experience
57
57
58
- ### Enabling a preview runtime feature
59
-
60
- Maddy is building a Tye application. She reads in a blog post that the .NET
61
- runtime team is experimenting with a new GC mode, code named FancyGC.
62
-
63
- She wants to see how this improves the performance of her backend. She's glad to
64
- see that the new GC mode was shipped as part of .NET 6, so she doesn't need to
65
- figure out how to run a new version of .NET in her CI lab. So she creates a
66
- feature branch and enables the new GC mode simply by changing the service's
67
- project file as follows:
68
-
69
- ``` xml
70
- <Project Sdk =" Microsoft.NET.Sdk" >
71
-
72
- <PropertyGroup >
73
- <TargetFramework >net6.0</TargetFramework >
74
- <EnablePreviewFeatures >True</EnablePreviewFeatures >
75
- </PropertyGroup >
76
-
77
- </Project >
78
- ```
79
-
80
- She then submits a draft PR against ` main ` to trigger their CI/CD pipeline which
81
- also runs some performance tests.
82
-
83
- ### Enabling a preview language feature
84
-
85
- During lunch, Adriana discusses a design problem with one of the architects who
86
- mentions that the upcoming static interface members in C# might be able to solve
87
- this issue. Adriana does a quick web search and finds a blog post from the C#
88
- team that showcases how this feature might look like. She wonders how she can
89
- play with that. Optimistic, she copy & pastes the sample code into her project
90
- which immediately generates a compilation error:
91
-
92
- > The feature 'static interface members' is currently in Preview and
93
- > "unsupported". To use Preview features, use the 'preview' language version.
94
-
95
- The error displays a light-bulb in Visual Studio, suggesting to enable preview
96
- features, which modifies her project file as follows:
97
-
98
- ``` xml
99
- <Project Sdk =" Microsoft.NET.Sdk" >
100
-
101
- <PropertyGroup >
102
- <TargetFramework >net6.0</TargetFramework >
103
- <EnablePreviewFeatures >True</EnablePreviewFeatures >
104
- </PropertyGroup >
105
-
106
- </Project >
107
- ```
108
-
109
- ### Enabling a cross-cutting preview feature
58
+ ### Enabling a preview feature
110
59
111
60
Ainsley is working for the insurance company Fabrikam. As part of their work,
112
61
they are trying to figure out how they can integrate machine learning with
113
62
ML.NET more tightly with their services, but they struggle with data ingestion
114
- because a lot of the heavy computations are happening inside of an old C++ base.
115
- When that code was written, .NET wasn't fast enough to do heavy numerical
63
+ because a lot of the heavy computations are happening inside of an old C++ code
64
+ base. When that code was written, .NET wasn't fast enough to do heavy numerical
116
65
computations.
117
66
118
67
As part of their research into this problem space, they notice a recent blog
@@ -157,9 +106,8 @@ the library into the production instance of Fabrikam.
157
106
* We can deliver a reasonable experience even when a preview feature can't be
158
107
supported in all the workloads, for example, by failing with a sensible error
159
108
message.
160
- * We have a unified experience for enabling preview features, no matter whether
161
- they are in a runtime, a compiler, a library, or span multiple parts of the
162
- system.
109
+ * We have a simple experience for enabling preview features that span multiple
110
+ parts of the system.
163
111
* We don't have to do unnatural acts to expose a preview feature, by, for
164
112
example, having to build a plug-in based system that allows swapping in and
165
113
out files.
@@ -169,6 +117,8 @@ the library into the production instance of Fabrikam.
169
117
* Allowing Microsoft to turn features on or off remotely, e.g. A/B testing
170
118
* Designing a mechanism for shipping preview features as separate packages or
171
119
installers
120
+ * Modeling runtime-only preview features (see [ What about runtime-only preview
121
+ features?] ( #what-about-runtime-only-preview-features ) )
172
122
173
123
## Stakeholders and Reviewers
174
124
@@ -227,27 +177,39 @@ This means you can look at a binary and tell whether it was built using preview
227
177
features. This can be used for auditing and for detecting transitive
228
178
dependencies ([ discussed later] ( #api-analyzer ) ).
229
179
230
- ### runtime.json
231
-
232
- Whether or not ` EnablePreviewFeatures ` was set to true for the application
233
- should be written into the ` runtime.json ` file such that the host/runtime can
234
- use it to make decisions. Alternatively, we could say this is encoded by the
235
- fact that the assembly the host considers the entry point has the
236
- ` RequiresPreviewFeatures ` assembly level attribute.
237
-
238
180
### Compilation context
239
181
240
182
When ` EnablePreviewFeatures ` is true, the ` LangVersion ` property should be set
241
- to ` Preview ` . This avoids customers having to turn on preview features for the
242
- language separately.
183
+ to ` Preview ` (unless the customer has explicitly set ` LangVersion ` in their
184
+ project file already). This avoids customers having to turn on preview features
185
+ for the language separately.
243
186
244
187
In addition, the property ` EnablePreviewFeatures ` should be passed to the
245
188
compilation context (akin to how ` TargetFramework ` is passed in today). An
246
189
analyzer will use that to block use of APIs that are marked as preview as basing
247
- this off the language preview mode feels wrong .
190
+ this off the language preview mode is nonsensical .
248
191
249
192
*** Note:*** F# doesn't have this capability today.
250
193
194
+ Since we use a separate property the user can have preview features off, but
195
+ language is in preview mode. This would result in configuration where the user
196
+ can use runtime features that are in preview.
197
+
198
+ We have two options on how we can deal with this:
199
+
200
+ 1 . One option is to use ` RuntimeFeatures ` and mark the field as
201
+ ` [RequiresPreviewFeatures] ` that causes the compiler to enforce the
202
+ containing assembly/type/member to be marked as ` [RequiresPreviewFeatures] `
203
+ as well. Aleksey believes this check needs to be in-place regardless of
204
+ number of checks. Another option is to simply fail the build as an invalid
205
+ configuration.
206
+
207
+ 2 . The other option is to simply fail the build with an error instructing the
208
+ customer that this configuration is invalid. This could be in MSBuild and
209
+ doesn't require work in the compiler.
210
+
211
+ *** OPEN QUESTION** : Do we want to use the first or the second mechanism?*
212
+
251
213
### API Analyzer
252
214
253
215
We'll need an attribute to record whether or not the project was
@@ -290,6 +252,53 @@ capability to the compiler itself.
290
252
291
253
## Q & A
292
254
255
+ ### What about runtime-only preview features?
256
+
257
+ We already have runtime-only preview features and the way we have shipped them
258
+ is as environment variables, for example, [ tiered JIT] :
259
+
260
+ ``` text
261
+ COMPlus_TieredCompilation=1
262
+ ```
263
+
264
+ These can typically also be configured via ` runtimeconfig.json ` :
265
+
266
+ ``` json
267
+ {
268
+ "runtimeOptions" : {
269
+ "configProperties" : {
270
+ "System.Runtime.TieredCompilation" : true
271
+ }
272
+ }
273
+ }
274
+ ```
275
+
276
+ We have decided that we scope this feature to only track the use of preview
277
+ features that result in changes to the files distributed by the customer, such
278
+ as using preview compiler features or preview APIs.
279
+
280
+ Preview features that only impact the process, which is what runtime-only preview
281
+ features are, don't need to be traced through the library ecosystem and thus
282
+ aren't part of this work.
283
+
284
+ Also, we don't think that it makes sense for libraries to declare a dependency
285
+ on runtime-only preview features because those tend to be performance tweaks.
286
+
287
+ The existing mechanism via environment variables and ` runtimeconfig.json ` is
288
+ considered good enough. Also, for those features it is useful to be able to turn
289
+ individual features on an off in order to troubleshoot. Restricting those
290
+ features to the global preview mode is considered too restrictive an
291
+ unnecessary, considering that they are application-level concerns.
292
+
293
+ We discussed whether the environment variables or switches should include the
294
+ name "preview" or "unsupported" but this would be akin to naming preview APIs
295
+ differently which we generally don't want because it increases the friction for
296
+ customers that want to move from the preview to the supported version. Also,
297
+ historically we have not been able to rename them. We believe it sufficient to
298
+ document which of these switches are supported and which ones are in preview.
299
+
300
+ [ tiered-jit ] : https://devblogs.microsoft.com/dotnet/tiered-compilation-preview-in-net-core-2-1/
301
+
293
302
### Are preview features supported?
294
303
295
304
No. The entire point of preview feature is to gather feedback, and make changes
@@ -419,74 +428,26 @@ Originally I used the term *experimental* but we decided to change it to
419
428
* Overall, the goal is draw more people in and motivate them to try the
420
429
features. The term * preview* seems more helpful than * experimental* .
421
430
422
- ----------------------
423
-
424
- ## Notes
425
-
426
- * Should we support multiple feature flags _ as well_ ?
427
- - If a feature is runtime only, we use environment variables today quite
428
- successfully. Maybe we should only differentiate between features that
429
- impact the binary on disk (compiler, APIs) vs. process lifetime. For
430
- runtime features we often do perf work and we want to know whether it
431
- helps or not.
432
- - For runtime libraries, we generally don't believe a library can or should
433
- declare a hard dependency on runtime only features, because they are often
434
- perf tweaks.
435
- - We don't believe we can change names of feature flags because historically
436
- not been able to rename them.
437
- - Maybe documenting them on docs.microsoft.com as unsupported is good
438
- enough.
439
- - We generally don't use ` AppContext ` switches for preview features, but we
440
- use it for more than just compat switches, e.g. trimming.
441
- * Should we use ` LangVersion ` as the main switch?
442
- - For language features, it's well established that people set this
443
- property.
444
- - The ` LangVersion ` property doesn't have quite the right name and it would
445
- now cause transitivity requirements.
446
- - Using this property might not work well for VB and F#
447
- - The biggest counter argument is that the compiler can be in stable version
448
- but the TFM you're targeting is not.
449
- - If we use a separate property, then this means the user could have preview
450
- features off, but language is in preview mode. This would result in
451
- configuration where the user can use runtime features that are in preview.
452
- One option is to use ` RuntimeFeatures ` and mark the field as
453
- ` [RequiresPreviewFeatures] ` that causes the compiler to enforce the
454
- containing assembly/type/member to be marked as
455
- ` [RequiresPreviewFeatures] ` as well. Aleksey believes this check needs to
456
- be in-place regardless of number of checks. Another option is to simply
457
- fail the build as an invalid configuration.
458
- * Analyzer vs Compiler feature
459
- * VS releases
460
- * Multiple TFMs
461
-
462
- ## From Jeremy
463
-
464
- For the compiler versioning (and other languages) vs "API impacted platform
465
- features" (or whatever you want to call them):
466
-
467
- * Maybe it's OK if C#-2025 can't compile certain syntaxes against .NET 6 with
468
- experimental support .. e.g. we changed something in how generic math works
469
- and they've decided "its been a couple releases, time to move on".
470
- * Conversely, even if the compiler supports that combination, if we changed
471
- generic math then there may be a runtime break on assemblies compiled against
472
- net6-preview vs net7, so an explicit experimental gesture is still a
473
- requirement
474
-
475
- The three scenarios I commented on in chat may also be useful in addition to
476
- those points:
477
-
478
- * Preview language feature with experimental API: string8 str = 8"Hello, World";
479
- * Should generate the "I used experimental API, my callers need to accept that"
480
- attribute.
481
- * Stable language syntax with experimental API
482
- - ` Utf8String str = new Utf8String("Hello, World"); `
483
- * Should generate the attribute
484
- * Preview language features that would work on net5 or older: things like
485
- autoprops or records or required partial members.
486
- * The attribute doesn't seem needed here. Why should this necessarily dead-end
487
- your NuGet package?
488
-
489
- (To be clear: I don't think we need to make anything be smart enough that
490
- attribute generation is tied to actual usage, if making the gesture emits it
491
- even when you don't need it that's OK (except when it isn't) -- I'm just
492
- pointing out they're two different axes)
431
+ ### Why didn't we use the ` <LangVersion>Preview</LangVersion> ` ?
432
+
433
+ There is an existing property that allows customers to opt into preview
434
+ features of the language by setting this property in their project file:
435
+
436
+ ``` xml
437
+ <Project >
438
+
439
+ <PropertyGroup >
440
+ <LangVersion >Preview</LangVersion >
441
+ </PropertyGroup >
442
+
443
+ </Project >
444
+ ```
445
+
446
+ There are several issues with using this as the primary mechanism for enabling
447
+ preview features for the .NET platform:
448
+
449
+ * The ` LangVersion ` property doesn't have quite the right name and it would now
450
+ cause transitivity requirements.
451
+ * Using this property might not work well for VB and F#
452
+ * The biggest counter argument is that the compiler can be in stable version but
453
+ the TFM you're targeting is not.
0 commit comments