Skip to content

Single tilde ~ in expressions compiles, but shouldn't #16135

Closed

Description

@brianrourkeboll

Using the .NET 7 SDK and above, a single tilde ~ can be used in nearly any expression context and will compile (and can even make otherwise nonsensical syntax compile), but such an expression will fail or behave unintuitively at runtime.

Repro steps

  1. Put a single tilde ~ in nearly any expression context: prefix, infix, postfix, circumfix...
  2. The code compiles, but either:
    a. Fails at runtime with a System.NullReferenceException.
    b. Fails at runtime with Fatal error. Internal CLR error. (0x80131506), which crashes the runtime altogether. Exciting!
    b. Generates a default value (0, null, etc.)—neat shorthand for Unchecked.defaultof<_>!
// These all compile...
let f x = ~x
let g x y = x ~ y
let h x y = (x ~) y
let p x = x~
let q x = x ~
let x : int = ~
let _ : int = ~ ~ ~ ~
let _ = ~1
let _ = 1~
let _ = ~1~
let _ = (~) 1
let _ = (~) 1 1 1 1
let _ = ~ 1 1 1 1
let _ = 1 1 1 1 ~
let _ = 1 1 ~ 1 1
let _ = ~ DDD ~
let _ = ~ _._. ~
let _ = ~ ``(👉゚ヮ゚)👉`` ~
let _ = ~ <int> ~
let () = ignore ~
let zero = ~ + ~

Expected behavior

I don't believe that any code using a single ~ should compile (prefix operators involving ~ always have at least one other character).

Actual behavior

The code compiles—including outlandish code that would otherwise never compile—and strange things happen at runtime.

Known workarounds

Don't accidentally type ~ anywhere.

Related information

This behavior happens for me when compiling with the .NET 7 and 8 SDKs, but not with .NET 6, so it seems likely that it was introduced in 7.

Activity

  1. added this to the Backlog milestone on Oct 17, 2023
  2. T-Gro commented on Oct 23, 2023

    @T-Gro
    Member

    (to be bisected to find what has introduced it)

  3. added
    Impact-High(Internal MS Team use only) Describes an issue with extreme impact on existing code.
    and removed on Oct 23, 2023
  4. vzarytovskii commented on Oct 23, 2023

    @vzarytovskii
    Member

    I remember something was done around arithmetics in literals, wondering if it could've affected it.

    But basically what's happening with it is

    ldnull
    ldc.i4.1

  5. abonie commented on Oct 27, 2023

    @abonie
    Member

    Bisecting leads me to believe this was introduced by 7ea48f0
    Although it isn't immediately obvious to me why

  6. auduchinok commented on Oct 27, 2023

    @auduchinok
    Member

    @abonie Interesting, thanks for checking! I see why it could be related, but I'd expect an error there anyway. I'll take a look.

  7. abelbraaksma commented on Dec 23, 2023

    @abelbraaksma
    Contributor

    but not with .NET 6, so it seems likely that it was introduced in 7.

    I saw this happen in .NET 6 (in Visual Studio 17.8.3, Dec 5th, 2023):

    Microsoft (R) F# Interactive version 12.8.0.0 for F# 8.0

    <PropertyGroup>
      <TargetFramework>net6.0</TargetFramework>
    </PropertyGroup>

    Project had code like this (by accident, simplified):

    let x = [1;2] |> List.minBy (~1)
    let f x = (~2) x

    Taking the snippet of the OP, it compiles in my .NET 6 project. I also tested a NETStandard 2.1 project, where the same code "just compiles", but throws at runtime.

    I'll try once the fix is public, if it fixes the bug in these projects as well.

  8. brianrourkeboll commented on Dec 23, 2023

    @brianrourkeboll
    ContributorAuthor

    I saw this happen in .NET 6 (in Visual Studio 17.8.0)

    It's the tooling version (not the target framework) that matters for this. If you have the .NET 6 SDK installed, and specify that it be used in a global.json file, the examples above shouldn't compile (they don't for me).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugImpact-High(Internal MS Team use only) Describes an issue with extreme impact on existing code.Regression

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions