Open TessenR opened 2 years ago
Agree this is an issue but more on the minor side. It's a case where the user is incorrectly replicating the source for types the compiler depends on. There are many examples in the language where this will produce errors. For instance the compiler just assumes that many parts of IEnumerable
are or are not generic. When you violate that the compiler will often generate invalid IL. Where possible and reasonable we fix these but they tend to be on the lower priority end of the equation.
Version Used:
Steps to Reproduce:
Compile the following code as
.dll
withpreview
language versionReference this
.dll
in another project, compile it withpreview
language version and run the following code:Expected Behavior: Compilation error for
return ref x;
inUnscopedRefBug.M
Actual Behavior: Both projects compile and the second program runs and corrupts stack memory
Notes: Note that if the argument is provided explicitly i.e.
[UnscopedRef(false)]
, Roslyn will not treatout x
as unscoped and correctly produce an error when compiling the.dll
projectThe problem here is that
[UnscopedRef]
attribute in the.dll
project actually invokes a constructor with a default argument, which is saved in metadata. Consequently, the attribute is not recognized as a well-known attribute when the.dll
is referenced in the second project. However, when the first project is being compiled, Roslyn doesn't check for default arguments and treats[UnscopedRef]
as a well known constructor usage.This leads to a situation when at compile time
UnscopedRefBug.M.out x
is treated as unscoped, allowing returning a reference to this parameter, whereas when the signature is read from metadata the attribute is ignored, so Roslyn treats this parameter asscoped
and doesn't use arguments passed to this parameter to verify the ref-safe-to-escape scope of the invocation.Note that it also makes
[UnsocpedRef(false)]
and[UnsocpedRef]
behave differently in the source code, as the latter is treated as a special attribute by the compiler and the former isn't, even though they result in exactly the same metadata when compiled.