Skip to content

Commit

Permalink
Add no_std Support (#374)
Browse files Browse the repository at this point in the history
* Switch to edition 2021 and resolver 2

This is effectively required for `no_std` support, as without it, dev-dependencies will enable features on regular dependencies, making it impossible to have `std` tests in `no_std` crates.

* Add useful `no_std` lints

These clippy lints highlight cases where an import is referencing `std` or `alloc` when it instead could import from `alloc` or `core`. This helps expose the "true" extent of `std` usage in a crate.

* Update dependencies and features

`termcolor` is incompatible with `no_std`, but `codespan` and `codespan-reporting` have valid use even without this crate. Making it optional allows `no_std` to be entirely decided by the contents of the codespan crates themselves.

Serde is also `no_std` compatible, as long as we disable default features.

* Increase MSRV to 1.67

During testing, `unicode-width` caused `cargo msrv find` to report `codespan-reporting`'s MSRV was 1.66, violating the current MSRV of 1.46. Since this is already the case, and there are features in 1.67, such as ilog10, which are desired within this crate, I have increased the MSRV to 1.67.

* Switch to derived `Default`

Before making substantive changes, `clippy` reported that these implementations for default can be derived. I have done so to silence the lint.

* Suppress `clippy::should_implement_trait`

`Span::from_str` shadows `FromStr::from_str`. Instead of breaking the public API, I added an explicit `allow`

* Remove redundant `into()` calls

Caught by clippy, and actioned to reduce warnings

* Suppress `clippy::too_many_arguments`

`Renderer::render_snippet_source` has too many arguments. Instead of breaking the public API, I'm suppressing this lint.

* Remove redundant references

These double-references are automatically dereferenced anyway.

* Use `ilog10` in `count_digits`

Increasing MSRV allows using the new `ilog10` method, solving a long-standing TODO

* Use of `format` is redundant

`ToString::to_string()` is preferred by `clippy` for converting `str` to `String`

* Simplify `assert_eq!` statements

`assert_eq` on a boolean is linted against by `clippy`, suggesting to use `assert!` instead.

* Implement `termcolor` feature gating

The `Styles` type is only needed for controlling colour, which is only needed with `termcolor`. Since we only deal with UTF8 strings, `std::fmt::Write` is equivalent to `WriteColor` when colour isn't required.

* Add `no_std` support

Switch imports to relying on `core` and `alloc`. `std::io::Write` can be replaced by `core::fmt::Write` since we deal exclusively with UTF8 strings.

* Added `check-no-std` to CI

This checks for `no_std` compatibility on 3 key targets:
- `x86_64-unknown-none`: represents desktop `no_std`, such as in kernels
- `wasm32v1-none`: represents Web builds using the most broadly support WASM target
-`thumbv6m-none-eabi`: represents typical embedded targets, such as the Raspberry Pi Pico

Testing on all three platforms ensures the widest possible compatibility.

* Fixes from CI run

- `cargo fmt`
- Fix typo in `ci.yml` which misused the matrix

* Switch from underscore to `allow(unused)`

Co-Authored-By: Ben <[email protected]>

* Document clippy lints

Co-Authored-By: Ben <[email protected]>

* Fix `check-no-std`

`wasm32v1-none` was only added in 1.84, so I've set that as the earliest Rust version used for testing `no_std` compatibility. Note that it's typical for embedded development to be done on nightly anyway, so `no_std` will usually happen on the very latest version of Rust.

* Format

* Remove  `serde/rc` from `codespan-reporting/serialization`

Not currently used and is incompatible with `thumbv6m-none-eabi`

* Test all combinations before giving up on `check-no-std`

Co-Authored-By: Ben <[email protected]>

---------

Co-authored-by: Ben <[email protected]>
  • Loading branch information
bushrat011899 and kaleidawave authored Mar 8, 2025
1 parent d282af1 commit 0f2450a
Show file tree
Hide file tree
Showing 26 changed files with 361 additions and 141 deletions.
38 changes: 35 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
rust: ["1.46.0", "stable", "beta", "nightly"]
rust: ["1.67.0", "stable", "beta", "nightly"]
name: Check (${{ matrix.rust }})
steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -53,11 +53,43 @@ jobs:
command: check
args: --manifest-path "codespan-lsp/Cargo.toml"

check-no-std:
name: Check
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust:
- "1.84.0"
- "stable"
- "beta"
- "nightly"
target:
- "x86_64-unknown-none"
- "wasm32v1-none"
- "thumbv6m-none-eabi"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- name: Run cargo check for codespan-reporting
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path "codespan-reporting/Cargo.toml" --no-default-features --features "serialization" --target ${{ matrix.target }}
- name: Run cargo check for codespan
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path "codespan/Cargo.toml" --no-default-features --features "serialization" --target ${{ matrix.target }}

test:
runs-on: ubuntu-20.04
strategy:
matrix:
rust: ["1.46.0", "stable", "beta", "nightly"]
rust: ["1.67.0", "stable", "beta", "nightly"]
name: Test Suite (${{ matrix.rust }})
steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -95,7 +127,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
rust: ["1.46.0", "stable", "beta", "nightly"]
rust: ["1.67.0", "stable", "beta", "nightly"]
name: Rustfmt (${{ matrix.rust }})
steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ members = [
"./codespan-reporting",
"./codespan-lsp",
]
resolver = "2"
2 changes: 1 addition & 1 deletion codespan-lsp/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

The minimum supported rustc version is now `1.46.0` (was `1.40.0`).
The minimum supported rustc version is now `1.67.0` (was `1.40.0`).
This is because some dependencies now require this Rust version.

### Changed
Expand Down
18 changes: 16 additions & 2 deletions codespan-lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,28 @@ description = "Conversions between codespan types and Language Server Protocol t
homepage = "https://github.com/brendanzab/codespan"
repository = "https://github.com/brendanzab/codespan"
documentation = "https://docs.rs/codespan-lsp"
edition = "2018"
edition = "2021"
rust-version = "1.67"

[dependencies]
codespan-reporting = { version = "0.11.1", path = "../codespan-reporting" }
codespan-reporting = { version = "0.11.1", path = "../codespan-reporting", features = [
"std",
"termcolor",
] }
# WARNING: Be extremely careful when expanding this version range.
# We should be confident that all of the uses of `lsp-types` in `codespan-lsp`
# will be valid for all the versions in this range. Getting this range wrong
# could potentially break down-stream builds on a `cargo update`. This is an
# absolute no-no, breaking much of what we enjoy about Cargo!
lsp-types = ">=0.84, <0.92"
url = "2"

[lints.clippy]
# Certain items from `core` are re-exported in `alloc` and `std`, and likewise `alloc` has items
# re-exported in `std`.
# `core` is available on all platforms, `alloc` is available on almost all, and `std` is only
# available on some.
# These lints ensure we don't import from a "less available" crate without reason.
alloc_instead_of_core = "warn"
std_instead_of_alloc = "warn"
std_instead_of_core = "warn"
8 changes: 7 additions & 1 deletion codespan-lsp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
//! Utilities for translating from codespan types into Language Server Protocol (LSP) types
#![forbid(unsafe_code)]
#![no_std]

use std::ops::Range;
#[cfg(test)]
extern crate alloc;

use core::ops::Range;

use codespan_reporting::files::{Error, Files};

Expand Down Expand Up @@ -139,6 +143,8 @@ where

#[cfg(test)]
mod tests {
use alloc::string::ToString;

use codespan_reporting::files::{Location, SimpleFiles};

use super::*;
Expand Down
4 changes: 2 additions & 2 deletions codespan-reporting/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

The minimum supported rustc version is now `1.46.0` (was `1.40.0`).
This is because some testing dependencies now require this Rust version.
The minimum supported rustc version is now `1.67.0` (was `1.40.0`).
This is because some dependencies now require this Rust version.

### Added

Expand Down
22 changes: 18 additions & 4 deletions codespan-reporting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ homepage = "https://github.com/brendanzab/codespan"
repository = "https://github.com/brendanzab/codespan"
documentation = "https://docs.rs/codespan-reporting"
exclude = ["assets/**"]
edition = "2018"
edition = "2021"
rust-version = "1.67"

[dependencies]
serde = { version = "1", optional = true, features = ["derive"] }
termcolor = "1.0.4"
serde = { version = "1", default-features = false, optional = true, features = ["derive", "alloc"] }
termcolor = { version = "1.0.4", optional = true }
unicode-width = ">=0.1,<0.3"

[dev-dependencies]
Expand All @@ -26,5 +27,18 @@ rustyline = "6"
unindent = "0.1"

[features]
serialization = ["serde", "serde/rc"]
default = ["std", "termcolor"]
std = ["serde?/std"]
termcolor = ["std", "dep:termcolor"]
serialization = ["serde"]
ascii-only = []

[lints.clippy]
# Certain items from `core` are re-exported in `alloc` and `std`, and likewise `alloc` has items
# re-exported in `std`.
# `core` is available on all platforms, `alloc` is available on almost all, and `std` is only
# available on some.
# These lints ensure we don't import from a "less available" crate without reason.
alloc_instead_of_core = "warn"
std_instead_of_alloc = "warn"
std_instead_of_core = "warn"
8 changes: 4 additions & 4 deletions codespan-reporting/examples/custom_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use std::ops::Range;
use core::ops::Range;

fn main() -> anyhow::Result<()> {
let mut files = files::Files::new();
Expand Down Expand Up @@ -42,7 +42,7 @@ fn main() -> anyhow::Result<()> {
/// A module containing the file implementation
mod files {
use codespan_reporting::files;
use std::ops::Range;
use core::ops::Range;

/// A file that is backed by an `Arc<String>`.
#[derive(Debug, Clone)]
Expand All @@ -57,7 +57,7 @@ mod files {

impl File {
fn line_start(&self, line_index: usize) -> Result<usize, files::Error> {
use std::cmp::Ordering;
use core::cmp::Ordering;

match line_index.cmp(&self.line_starts.len()) {
Ordering::Less => Ok(*self
Expand Down Expand Up @@ -95,7 +95,7 @@ mod files {
name: impl Into<String>,
source: impl Into<String>,
) -> Option<FileId> {
use std::convert::TryFrom;
use core::convert::TryFrom;

let file_id = FileId(u32::try_from(self.files.len()).ok()?);
let name = name.into();
Expand Down
3 changes: 2 additions & 1 deletion codespan-reporting/examples/readme_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fn main() -> anyhow::Result<()> {
let mut buffer = Vec::new();
let mut writer = HtmlEscapeWriter::new(SvgWriter::new(&mut buffer));
let config = codespan_reporting::term::Config {
#[cfg(feature = "termcolor")]
styles: codespan_reporting::term::Styles::with_blue(Color::Blue),
..codespan_reporting::term::Config::default()
};
Expand Down Expand Up @@ -187,7 +188,7 @@ fn main() -> anyhow::Result<()> {
)?;
}
Opts::Stderr { color } => {
let writer = StandardStream::stderr(color.into());
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in &diagnostics {
term::emit(&mut writer.lock(), &config, &file, diagnostic)?;
Expand Down
4 changes: 2 additions & 2 deletions codespan-reporting/examples/reusable_diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use codespan_reporting::diagnostic::{Diagnostic, Label};
use codespan_reporting::files::SimpleFile;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use codespan_reporting::term::{self};
use std::ops::Range;
use core::ops::Range;

#[derive(Debug)]
pub struct Opts {
Expand Down Expand Up @@ -39,7 +39,7 @@ fn main() -> anyhow::Result<()> {
];

let Opts { color } = parse_args()?;
let writer = StandardStream::stderr(color.into());
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in errors.iter().map(Error::report) {
term::emit(&mut writer.lock(), &config, &file, &diagnostic)?;
Expand Down
2 changes: 1 addition & 1 deletion codespan-reporting/examples/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn main() -> anyhow::Result<()> {
)]),
];

let writer = StandardStream::stderr(color.into());
let writer = StandardStream::stderr(color);
let config = codespan_reporting::term::Config::default();
for diagnostic in &diagnostics {
term::emit(&mut writer.lock(), &config, &files, diagnostic)?;
Expand Down
22 changes: 16 additions & 6 deletions codespan-reporting/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
//! Diagnostic data structures.
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::ops::Range;

#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::ops::Range;
use std::string::ToString;

/// A severity level for diagnostic messages.
///
Expand Down Expand Up @@ -188,9 +192,12 @@ impl<FileId> Diagnostic<FileId> {
self.labels.append(&mut labels);
self
}

/// Add some labels to the diagnostic.
pub fn with_labels_iter(mut self, labels: impl IntoIterator<Item = Label<FileId>>) -> Diagnostic<FileId> {
pub fn with_labels_iter(
mut self,
labels: impl IntoIterator<Item = Label<FileId>>,
) -> Diagnostic<FileId> {
self.labels.extend(labels);
self
}
Expand All @@ -206,9 +213,12 @@ impl<FileId> Diagnostic<FileId> {
self.notes.append(&mut notes);
self
}

/// Add some notes to the diagnostic.
pub fn with_notes_iter(mut self, notes: impl IntoIterator<Item = String>) -> Diagnostic<FileId> {
pub fn with_notes_iter(
mut self,
notes: impl IntoIterator<Item = String>,
) -> Diagnostic<FileId> {
self.notes.extend(notes);
self
}
Expand Down
Loading

0 comments on commit 0f2450a

Please sign in to comment.