diff --git a/Cargo.lock b/Cargo.lock index 552b446a1e7..067f56d9c77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4631,6 +4631,7 @@ dependencies = [ name = "rustc_span" version = "0.0.0" dependencies = [ + "derivative", "indexmap", "itoa", "md-5", diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 98ed985738a..83a554fe31d 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +derivative = "2.2.0" indexmap = { version = "2.0.0" } itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 1df2b357ac1..18e735f1903 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -42,9 +42,15 @@ use std::hash::Hash; /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks". -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct SyntaxContext(u32); +// To ensure correctness of incremental compilation, +// `SyntaxContext` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for SyntaxContext {} +impl !PartialOrd for SyntaxContext {} + #[derive(Debug, Encodable, Decodable, Clone)] pub struct SyntaxContextData { outer_expn: ExpnId, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f749d4eb833..2339e02f888 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -469,46 +469,23 @@ pub fn into_local_path(self) -> Option { /// `SpanData` is public because `Span` uses a thread-local interner and can't be /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, derivative::Derivative)] +#[derivative(PartialOrd, Ord)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. + #[derivative(PartialOrd = "ignore", Ord = "ignore")] + // `SyntaxContext` does not implement `Ord`. + // The other fields are enough to determine in-file order. pub ctxt: SyntaxContext, + #[derivative(PartialOrd = "ignore", Ord = "ignore")] + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. pub parent: Option, } -// Order spans by position in the file. -impl Ord for SpanData { - fn cmp(&self, other: &Self) -> Ordering { - let SpanData { - lo: s_lo, - hi: s_hi, - ctxt: s_ctxt, - // `LocalDefId` does not implement `Ord`. - // The other fields are enough to determine in-file order. - parent: _, - } = self; - let SpanData { - lo: o_lo, - hi: o_hi, - ctxt: o_ctxt, - // `LocalDefId` does not implement `Ord`. - // The other fields are enough to determine in-file order. - parent: _, - } = other; - - (s_lo, s_hi, s_ctxt).cmp(&(o_lo, o_hi, o_ctxt)) - } -} - -impl PartialOrd for SpanData { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - impl SpanData { #[inline] pub fn span(&self) -> Span {