From b8ab0d209617e55b9b5604702f52e838fc5d6d7e Mon Sep 17 00:00:00 2001 From: Adrian Rebola-Pardo <adrian.rebola@tuwien.ac.at> Date: Mon, 24 Mar 2025 09:41:34 +0100 Subject: [PATCH] design principles --- design-principles/TU_Signet.jpg | Bin 0 -> 35811 bytes design-principles/beamerthemetuw.sty | 315 +++++++++++++++++++++++++++ design-principles/presentation.tex | 139 ++++++++++++ design-principles/tuw-logo.pdf | Bin 0 -> 7098 bytes no-unsafe-no-bugs/Cargo.toml | 6 + no-unsafe-no-bugs/src/main.rs | 21 ++ safe-means-safe/Cargo.toml | 6 + safe-means-safe/src/main.rs | 29 +++ unsafe-rust-is-cpp/Cargo.toml | 6 + unsafe-rust-is-cpp/src/main.rs | 49 +++++ 10 files changed, 571 insertions(+) create mode 100644 design-principles/TU_Signet.jpg create mode 100644 design-principles/beamerthemetuw.sty create mode 100644 design-principles/presentation.tex create mode 100644 design-principles/tuw-logo.pdf create mode 100644 no-unsafe-no-bugs/Cargo.toml create mode 100644 no-unsafe-no-bugs/src/main.rs create mode 100644 safe-means-safe/Cargo.toml create mode 100644 safe-means-safe/src/main.rs create mode 100644 unsafe-rust-is-cpp/Cargo.toml create mode 100644 unsafe-rust-is-cpp/src/main.rs diff --git a/design-principles/TU_Signet.jpg b/design-principles/TU_Signet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0d3df92f4235fe5d94ffc554c3bf4d52e592c94 GIT binary patch literal 35811 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 Pnvvw!lHcq9wf27iKe*<- literal 0 HcmV?d00001 diff --git a/design-principles/beamerthemetuw.sty b/design-principles/beamerthemetuw.sty new file mode 100644 index 0000000..ec54988 --- /dev/null +++ b/design-principles/beamerthemetuw.sty @@ -0,0 +1,315 @@ +%% +% @file beamerthemeTUW.sty +% @date 2016-08-30 +% @author Wolfgang Puffitsch, Denise Ratasich +% +% @brief Beamer LaTeX template matching the corporate design of TU Wien. +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{beamerthemeTUW}[2016/08/30 Beamer template that fits the TU Wien corporate design (adopted styles from powerpoint presentation template in CD manual)] + +\RequirePackage{graphicx} +\RequirePackage{tikz} + +\def\beamer@tuwDefault{default} +\def\beamer@tuwPlain{plain} +\def\beamer@tuwSidebar{sidebar} +\def\beamer@tuwHelvetica{helvetica} +\def\beamer@tuwNoImage{none} +\def\beamer@tuwLogo{tuw-logo} +\def\beamer@tuwLogoWhite{TU_Logo_white} +\def\beamer@tuwSecondLogo{none} +\def\beamer@tuwSecondLogoWidth{.5\textwidth} + +%%% options +% The user may choose other fonts (TU Wien CD says to use helvetica). +\DeclareOptionBeamer{font}{\def\beamer@tuwFont{#1}} +% Another outer theme may be chosen, however it may not fit the TU Wien colors. +\DeclareOptionBeamer{outer}{\def\beamer@tuwOuter{#1}} +% Width of the sidebar. +\DeclareOptionBeamer{width}{\def\beamer@tuwWidth{#1}} +% Background image of TU Wien building on title page. +\newif\ifbeamer@tuwBackground +\DeclareOptionBeamer{tuw_background}{\beamer@tuwBackgroundtrue} +% Individual background image on title page. +\DeclareOptionBeamer{tuw_image}{\def\beamer@tuwImage{#1}} +% White logo (if tuw_image is dark the logo should be set to be white). +\newif\ifbeamer@tuwWhiteLogo +\DeclareOptionBeamer{tuw_whitelogo}{\beamer@tuwWhiteLogotrue} +% Print frame title beside the logo to save space. +\newif\ifbeamer@tuwFrametitleToTop +\DeclareOptionBeamer{tuw_frametitletotop}{\beamer@tuwFrametitleToToptrue} +% Second logo in case we need more than one +\DeclareOptionBeamer{second_logo}{\def\beamer@tuwSecondLogo{#1}} +\DeclareOptionBeamer{second_logo_width}{\def\beamer@tuwSecondLogoWidth{#1}} + +% defaults +\ExecuteOptionsBeamer{outer=default} +\ExecuteOptionsBeamer{width=1.6cm} +\ExecuteOptionsBeamer{font=\familydefault} +\beamer@tuwBackgroundfalse +\ExecuteOptionsBeamer{tuw_image=none} +\ExecuteOptionsBeamer{second_logo=none} +\beamer@tuwWhiteLogofalse +\beamer@tuwFrametitleToTopfalse + +\ProcessOptionsBeamer + +\ifx\beamer@tuwFont\beamer@tuwHelvetica +\RequirePackage{helvet} +\fi + +\mode<presentation> + +%%% colors +% For some reason the logo is not in TU-blue (0,102,153). The powerpoint +% presentation has TU-blue as background and the logo with a different color +% (doesn't look nice). We align the TU-blue to the logo, like in the CD manual. +\definecolor{tuwBlue}{RGB}{0,116,178} +\definecolor{tuwGray}{RGB}{102,102,102} +\definecolor{iceBlue}{RGB}{222,231,236} + +\def\tuwBlue{tuwBlue} +\def\tuwGray{tuwGray} +\def\iceBlue{iceBlue} +\def\tuwLightBlue{tuwBlue!20!white} +\def\tuwMediumBlue{tuwBlue!45!white} +\def\tuwDarkBlue{tuwBlue!70!black} +\def\alertred{red!50!black} + +% content page +\setbeamercolor{normal text}{fg=black,bg=white} +\setbeamercolor{alerted text}{fg=\alertred} +\setbeamercolor{structure}{fg=\tuwBlue} +\setbeamercolor{frametitle}{fg=black} + +\setbeamercolor{palette primary}{fg=\tuwDarkBlue,bg=\tuwLightBlue} +\setbeamercolor{palette secondary}{fg=\tuwBlue!50!black,bg=\tuwMediumBlue} +\setbeamercolor{palette tertiary}{fg=white,bg=\tuwBlue} + +\setbeamercolor{section in toc}{parent=normal text} +\setbeamercolor{subsection in toc}{parent=section in toc} + +\setbeamercolor{block title}{fg=white, bg=\tuwBlue} +\setbeamercolor{block title example}{fg=white, bg=\tuwBlue} +\setbeamercolor{block title alerted}{fg=white, bg=\alertred} +\setbeamercolor{block body}{bg=\iceBlue} +\setbeamercolor{block body example}{parent=block body} +\setbeamercolor{block body alerted}{parent=block body, fg=\alertred} + +\setbeamercolor{title in head/foot}{fg=\tuwBlue} +\setbeamercolor{page number in head/foot}{fg=\tuwBlue} +\setbeamercolor{footline}{fg=\tuwBlue} + +% color difference of default and other outer styles +\ifx\beamer@tuwOuter\beamer@tuwDefault +% default style - this is the CD of TU Wien +% title page +\setbeamercolor{title}{fg=white} +\setbeamercolor{subtitle}{fg=white} +\setbeamercolor{author}{fg=white} +\setbeamercolor{institute}{fg=white} +\setbeamercolor{date}{fg=white} +% content page +% keep defaults (black) +\else +% other outer styles (e.g., sidebar) +% title page +\setbeamercolor{title}{fg=\tuwGray} +\setbeamercolor{subtitle}{fg=\tuwGray} +\setbeamercolor{author}{fg=black} +\setbeamercolor{institute}{fg=black} +\setbeamercolor{date}{fg=black} +% content page +\setbeamercolor{frametitle}{fg=\tuwGray} +\setbeamercolor{headline}{fg=\tuwGray} +\setbeamercolor{footline}{fg=\tuwGray} +\fi + +% sidebar +\setbeamercolor{sidebar}{bg=\tuwBlue,fg=white} +\setbeamercolor{palette sidebar primary}{fg=\tuwDarkBlue,bg=\tuwLightBlue} +\setbeamercolor{palette sidebar secondary}{fg=\tuwDarkBlue,bg=\tuwLightBlue} +\setbeamercolor{palette sidebar tertiary}{fg=white,bg=\tuwBlue} +\setbeamercolor{title in sidebar}{fg=white,bg=\tuwBlue} +\setbeamercolor{section in sidebar}{fg=\tuwDarkBlue} +\setbeamercolor{section in sidebar shaded}{fg=white,bg=\tuwBlue} +\setbeamercolor{subsection in sidebar}{fg=\tuwDarkBlue} +\setbeamercolor{subsection in sidebar shaded}{fg=white,bg=\tuwBlue} + +%%% fonts + +% font weight +\setbeamerfont{title}{series=\bfseries} +\setbeamerfont{author}{series=\mdseries} +\setbeamerfont{institute}{series=\mdseries} +\setbeamerfont{date}{series=\mdseries} +\setbeamerfont{frametitle}{series=\mdseries} +\setbeamerfont{headline}{series=\mdseries} +\setbeamerfont{footline}{series=\mdseries} + +% font size difference of default and other outer styles +\ifx\beamer@tuwOuter\beamer@tuwDefault +% default style - this is the CD of TU Wien +\setbeamerfont{title}{size=\huge} +\setbeamerfont{author}{size=\normalsize} +\setbeamerfont{institute}{size=\normalsize} +\setbeamerfont{date}{size=\normalsize} +\setbeamerfont{frametitle}{size=\Large} +\setbeamerfont{framesubtitle}{size=\large} +\setbeamerfont{headline}{size=\scriptsize} +\setbeamerfont{footline}{size=\scriptsize} +\else +% other outer styles (e.g., sidebar) +% keep defaults +\fi + +\setbeamerfont{section in toc}{parent=normal text} +\setbeamerfont{subsection in toc}{parent=section in toc} + +% sidebar +\setbeamerfont{title in sidebar}{series=\bfseries} +\setbeamerfont{section in sidebar}{series=\bfseries,size=\tiny} +\setbeamerfont{subsection in sidebar}{size=\tiny} + +%%% outer +\setbeamersize{text margin left=1.2cm} +\setbeamersize{text margin right=1.5cm} +\beamertemplatenavigationsymbolsempty + + +\ifx\beamer@tuwOuter\beamer@tuwDefault +% default outher theme - this is the CD of TU Wien + +% background +\setbeamertemplate{background}{ + \begin{tikzpicture} + \useasboundingbox (0,0) rectangle(\the\paperwidth,\the\paperheight); + % title page + \ifbeamer@tuwBackground % tu building background selected + \node[anchor=south west] (background) at (-0.15cm,-0.15cm) {\includegraphics[width=1.01\paperwidth]{TU_Background}}; + \else\ifx\beamer@tuwImage\beamer@tuwNoImage % no background image specified + \fill[white] (0,0) rectangle (\the\paperwidth,\the\paperheight); + \else % individual background image + \node[anchor=north west] (background) at (-0.15cm,-0.15cm) {\includegraphics[width=1.01\paperwidth]{\beamer@tuwImage}}; + \fi\fi + \fill[\tuwBlue, rounded corners=0.5cm] (-1cm,-1cm) rectangle (\paperwidth-0.5cm,\paperheight-3cm); + \ifbeamer@tuwWhiteLogo % white logo option specified + \node[anchor=north west] (logo) at (0.3cm,\paperheight-0.1cm) {\includegraphics[width=.5\textwidth]{\beamer@tuwLogoWhite}}; + \else + \node[anchor=north west] (logo) at (0.2cm,\paperheight-0.2cm) {\includegraphics[height=2cm]{\beamer@tuwLogo}}; + \fi + \ifx\beamer@tuwSecondLogo\beamer@tuwNoImage + \else + \node[anchor=north east] (logo2) at (\paperwidth-0.2cm,\paperheight-0.2cm) {\includegraphics[width=\beamer@tuwSecondLogoWidth]{\beamer@tuwSecondLogo}}; + \fi + % content page + \ifnum\thepage>1\relax% + \fill[\iceBlue] (0,0) rectangle (\the\paperwidth,\the\paperheight); + \fill[white, rounded corners=0.5cm] (-1cm,-1cm) rectangle(\paperwidth-0.4cm,\paperheight-0.8cm); + \node[anchor=west] (logo) at (0.3cm,\paperheight-0.4cm) {\includegraphics[height=0.5cm]{TU_Signet}}; + \fi + \end{tikzpicture} +} + +% title page +\def\beamer@titlepageLeft{1.6cm} +\setbeamertemplate{title page}{ + \vskip 4cm% + \begin{beamercolorbox}[leftskip=\beamer@titlepageLeft]{title}% + \usebeamerfont{title}\inserttitle% + \end{beamercolorbox}% + \vskip 0.5cm% + \begin{beamercolorbox}[leftskip=\beamer@titlepageLeft]{subtitle} + \usebeamerfont{subtitle}\insertsubtitle% + \end{beamercolorbox} + \vskip 0.25cm% + \vfill% + \begin{beamercolorbox}[leftskip=\beamer@titlepageLeft]{author} + \usebeamerfont{author}\insertauthor% + \end{beamercolorbox} + \begin{beamercolorbox}[leftskip=\beamer@titlepageLeft]{date} + \usebeamerfont{date}\insertdate% + \end{beamercolorbox} +} + +% frametitle +\setbeamertemplate{frametitle} +{% + \ifbeamer@tuwFrametitleToTop % frametitle should be printed beside the logo + % vbox to keep the baseline + \vbox{}\vskip -0.43cm% + \else + \vbox{}\vskip 0.7cm% + \fi + \begin{beamercolorbox}[leftskip=0cm]{frametitle} + \usebeamerfont{frametitle}\insertframetitle% + \ifbeamer@tuwFrametitleToTop + \vbox{}\vskip 0.3cm% + \else + \vbox{}\vskip 0.2cm% + \fi + \usebeamerfont{framesubtitle}\insertframesubtitle% + \end{beamercolorbox} +} + +% footline +\setbeamertemplate{footline}{% + \vspace{0.1cm} + \ifnum\thepage>1 + \begin{beamercolorbox}[wd=\paperwidth,ht=2.25ex,dp=1ex]{footline} + \hskip 1.2cm% + \usebeamerfont{footline}\insertshortdate% + \hfill% + \insertshorttitle, \insertshortauthor% + \hfill% + \insertframenumber\:/\:\inserttotalframenumber% + \hspace*{1.5cm}% + \end{beamercolorbox} + \else + \begin{beamercolorbox}[wd=\paperwidth,ht=2.25ex,dp=1ex,center]{}% + % empty environment to raise height + \end{beamercolorbox} + \fi + \vspace{0.1cm} +} + +\else\ifx\beamer@tuwOuter\beamer@tuwSidebar +% sidebar outer theme +\useoutertheme[width=\beamer@tuwWidth,height=0pt]{\beamer@tuwOuter} + +% footline +\setbeamertemplate{footline}{ + \ifnum\thepage>1 + \vspace{-1cm} + \hfill{\scriptsize\insertframenumber\:/\:\inserttotalframenumber~~} + \vspace{0.1cm} + \fi +} +\else +\useoutertheme{\beamer@tuwOuter} +\fi\fi % if outer=default or outer=sidebar + + +%%% inner +\ifx\beamer@tuwOuter\beamer@tuwDefault +\setbeamertemplate{itemize items}[circle] +\else +% defaults +\fi % if outer=default + +\setlength{\parskip}{6pt} + +% blocks +\setbeamertemplate{blocks}[rounded] +\pgfdeclareverticalshading{bmb@transition}{\the\paperwidth}{color(0pt)=(\iceBlue); color(3.0pt)=(\iceBlue)} + +\setbeamercovered{invisible} + +% emphasize +\renewcommand<>{\emph}[1]{{\only#2{\color{\tuwBlue}}#1}} + +\hypersetup{colorlinks=true,linkcolor=fg,citecolor=\tuwGray,urlcolor=\tuwGray} + +\mode<all> diff --git a/design-principles/presentation.tex b/design-principles/presentation.tex new file mode 100644 index 0000000..05a6d97 --- /dev/null +++ b/design-principles/presentation.tex @@ -0,0 +1,139 @@ + +\documentclass[10pt]{beamer} + +\usetheme[font=helvetica]{TUW} + +\title{Rust Design Principles} +\author{Florian Sextl \and Mark Chimes \and Adrian Rebola-Pardo} +\date{2025-03-25} + +\begin{document} + +\begin{frame} +\titlepage +\end{frame} + +\begin{frame}{Rust in a nutshell} + Rust is a systems programming language. + \begin{itemize} + \item fine-grained control of memory and resources + \item high-level abstractions to do so + \item abstractions with different cost structures (including zero-cost) + \end{itemize} + + Yes, Rust has pointers. But you will \textit{actively avoid} using them.\\ + {\small\url{https://doc.rust-lang.org/std/primitive.pointer.html\#method.add-1}} + + Custom allocation is \textit{still} experimental!\\ + {\small\url{https://doc.rust-lang.org/std/alloc/trait.Allocator.html}} +\end{frame} + +\begin{frame}{The goals of Rust} + At this point a meme: \emph{blazingly fast} + + Full resource control behind locked-down interfaces. + + Highly long-term maintainable code, at the expense of short-term development time. + + Well-designed APIs do not need the developer to mind the gap; + \emph{memory safety} as the ultimate gap. + + Extensive \textit{and} extensible ecosystem (Cargo, rustdoc). +\end{frame} + +\begin{frame}{Buzzwords for Rust} +Buzzwords that apply to Rust +\begin{itemize} + \item \emph{Procedural}: explicit control flow + \item \emph{Statically typed}: with generics but not dependent types + \item \emph{Concurrent}: async in the type system, futures/atomics through std + \item \emph{RAII}: low-key the cornerstone of Rust +\end{itemize} + +Buzzwords that only sort of apply to Rust +\begin{itemize} + \item \emph{Declarative}: only for type bounds (but strongly so) + \item \emph{Functional}: strong use of closures, unique function typing, + function ``types'' as interfaces + \item \emph{Metaprogramming}: generics implemented through templates, + but modeled through constraint problems +\end{itemize} +\end{frame} + +\begin{frame}{Rust is data-oriented} +Rust follows the RAII paradigm: +\begin{itemize} + \item No constructors: any function returning a value is responsible for resource allocation + \item Visibility control enforces correct resource allocation + \item Everything is an ``object'': privileged traits control byte-clone correctness (Copy) + and resource deallocation (Drop). + \item Types have associated methods. + \item Traits (interfaces) control specialization. +\end{itemize} + +In Rust there are no ``objects'', there are only values. +\end{frame} + +\begin{frame}{Rust is not object-oriented} +Rust is not OO, with full intent: +\begin{itemize} + \item Associated methods are just functions. + \item No inheritance, no subclassing: interface relations expressed through bounds. + \item The diamond problem is a compile error. + \item Dynamic dispatch imposes additional restrictions on traits. +\end{itemize} + +OO: types are data and the methods that operate on it. + +Rust: types are \emph{control over} data and \emph{invariants} over the methods that operate on it. +\end{frame} + +\begin{frame}{Ownership} + A value \emph{recursively owns} resources: those resources can only be accessed by borrowing from the value. + \begin{itemize} + \item \emph{Shared borrowing}: several immutable borrows are simultaneously possible + \item \emph{Mutable borrowing}: a unique mutable borrow is simultaneously possible + \item \emph{The golden rule of Rust}: shared XOR mutable (else a compile-time error) + \item \emph{Not so obvious conclusion}: borrowing \textit{is a resource}. + \end{itemize} +\end{frame} + +\begin{frame}{Spicy pass-by-value} + Rust values free their allocated resources when they go out of scope. + + Rust arguments are \textit{always} pass-by-value (so they go out of scope at return). + + References are values that own borrows for a given \emph{lifetime}: + \begin{itemize} + \item \texttt{\&'a T}: immutable borrow of a \texttt{T} value for lifetime \texttt{'a} + \item \texttt{\&'a mut T}: mutable borrow of a \texttt{T} value for lifetime \texttt{'a} + \end{itemize} + + \emph{Your task as a Rust programmer}: convincing the borrow checker that the way you are accessing + data does indeed agree with \emph{shared XOR mutable}. +\end{frame} + +\begin{frame}{Safe vs unsafe Rust} +\emph{Your task as a Rust programmer}: convincing the borrow checker that the way you are accessing +data does indeed agree with \emph{shared XOR mutable} + +The borrow checker is overprotective: sometimes what you want to do is \emph{sound} (respects the borrow rules) +but \emph{unsafe} (cannot be guaranteed by the compiler) + +\emph{An escape hatch}: \texttt{unsafe} blocks allow the developer to avoid compiler oversight +(but \emph{absolutely not} the borrow rules). +\end{frame} + +\begin{frame}{Zero-cost abstractions} +Rust encourages composition to enforce invariants. + +\emph{Typical case}: your type is a tower of wrappers, each enforcing a stronger invariant + +\emph{Zero-cost abstraction} +\begin{itemize} +\item Memory layout and internal representation are (mostly) handled by the compiler +\item Simple call-passing is often compiled away +\item Simple generics and trait-based implementations often compile away into mere control flow (e.g. iterators) +\end{itemize} +\end{frame} +\end{document} \ No newline at end of file diff --git a/design-principles/tuw-logo.pdf b/design-principles/tuw-logo.pdf new file mode 100644 index 0000000000000000000000000000000000000000..77796289c36ff06396de70cc496fd0edbb597a9b GIT binary patch literal 7098 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 literal 0 HcmV?d00001 diff --git a/no-unsafe-no-bugs/Cargo.toml b/no-unsafe-no-bugs/Cargo.toml new file mode 100644 index 0000000..db74d9e --- /dev/null +++ b/no-unsafe-no-bugs/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no-unsafe-no-bugs" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/no-unsafe-no-bugs/src/main.rs b/no-unsafe-no-bugs/src/main.rs new file mode 100644 index 0000000..776257b --- /dev/null +++ b/no-unsafe-no-bugs/src/main.rs @@ -0,0 +1,21 @@ +use std::cell::RefCell; + +fn main() { + + let vec = Vec::<i32>::new(); + + // `RefCell<T>` allows runtime-checked mutable access to a `T`. + let cell = RefCell::new(vec); + + // I can take a mutable borrow. + let mut borrow1 = cell.borrow_mut(); + + // But I cannot take two! + let mut borrow2 = cell.borrow_mut(); + + // If you don't write unsafe, you won't UB... + // so instead you crash and burn. + + borrow1.push(1); + borrow2.push(2); +} diff --git a/safe-means-safe/Cargo.toml b/safe-means-safe/Cargo.toml new file mode 100644 index 0000000..9a71f86 --- /dev/null +++ b/safe-means-safe/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "safe-means-safe" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/safe-means-safe/src/main.rs b/safe-means-safe/src/main.rs new file mode 100644 index 0000000..c77f653 --- /dev/null +++ b/safe-means-safe/src/main.rs @@ -0,0 +1,29 @@ +#[forbid(unsafe_code)] +fn main() { + // Let's swap two items in a `Vec`. + let mut vec = Vec::from([1985, 2025]); + + // First try: grab mutable references to the items, then swap them. + let first = vec.get_mut(0).unwrap(); + let second = vec.get_mut(1).unwrap(); + std::mem::swap(first, second); + + // // Second try: use a standard library function + // vec.swap(0, 1); + + // Much safe! Very concurrency! + println!("OUTPUT: {:?}", &vec); +} + +// Claim 1: Creating two mutable references to (different) places +// within the memory owned by the same object is only possible +// through unsafe Rust. +// +// Claim 2: #[forbid(unsafe_code)] guarantees that no unsafe +// code is ever used. +// +// Claim 3: I need two mutable references to places in the +// memory owned by a `Vec` in order to swap them. +// +// +// Pick two. \ No newline at end of file diff --git a/unsafe-rust-is-cpp/Cargo.toml b/unsafe-rust-is-cpp/Cargo.toml new file mode 100644 index 0000000..8499352 --- /dev/null +++ b/unsafe-rust-is-cpp/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unsafe-rust-is-cpp" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/unsafe-rust-is-cpp/src/main.rs b/unsafe-rust-is-cpp/src/main.rs new file mode 100644 index 0000000..3db7aac --- /dev/null +++ b/unsafe-rust-is-cpp/src/main.rs @@ -0,0 +1,49 @@ +// Example by Jack O'Connor +// https://www.youtube.com/watch?v=DG-VLezRkYQ + +pub fn main() { + rust_like_its_1985(); +} + +pub fn rust_like_its_1985() { + let mut n = 0; + + // Taking a raw pointer is safe! + let n_ptr = &mut n as *mut i32; + + // Dereferencing a pointer is unsafe, but not necessarily UB. + let n_mut1 = unsafe { &mut *n_ptr }; + + // UB: Multiple mutable references to the same place + let n_mut2 = unsafe { &mut *n_ptr }; + + // Or is it? I can just remember not to operate on them at the same time. + *n_mut1 = 42; + + // Right? + *n_mut2 = 0; + + // "It works for me" + println!("OUTPUT: {}", *n_mut1); +} + +pub fn rust_like_its_2025() { + let mut n = 0; + let n_ptr = &mut n as *mut i32; + let n_mut1 = unsafe { &mut *n_ptr }; + let n_mut2 = unsafe { &mut *n_ptr }; + + // So far this is the same. Let's move the rest to a function. + println!("OUTPUT: {}", foo(n_mut1, n_mut2)); + + // You can't code in unsafe Rust like it's C++. + // Unsafe Rust does not allow you to jump over the borrow rules. + // It merely stops preventing you from trying. +} + +// #[inline(never)] +pub fn foo(x: &mut i32, y: &mut i32) -> i32 { + *x = 42; + *y = 0; + *x +} \ No newline at end of file -- GitLab