proc-macro-workshop:seq-8

godme發表於2022-07-05
// The procedural macro API uses a type called Span to attach source location
// and hygiene information to every token. In order for compiler errors to
// appear underlining the right places, procedural macros are responsible for
// propagating and manipulating these spans correctly.
//
// The invocation below expands to code that mentions a value Missing0 which
// does not exist. When the compiler reports that it "cannot find value
// Missing0", we would like for the error to point directly to where the user
// wrote `Missing~N` in their macro input.
//
//     error[E0425]: cannot find value `Missing0` in this scope
//       |
//       |         let _ = Missing~N;
//       |                 ^^^^^^^ not found in this scope
//
// For this test to pass, ensure that the pasted-together identifier is created
// using the Span of the identifier written by the caller.
//
// If you are using a nightly toolchain, there is a nightly-only method called
// Span::join which would allow joining the three spans of `Missing`, `~`, `N`
// so that the resulting error is as follows, but I would recommend not
// bothering with this for the purpose of this project while it is unstable.
//
//     error[E0425]: cannot find value `Missing0` in this scope
//       |
//       |         let _ = Missing~N;
//       |                 ^^^^^^^^^ not found in this scope
//

use seq::seq;

seq!(N in 0..1 {
    fn main() {
        let _ = Missing~N;
    }
});

這裡考察的還是報錯位置的解析,也就是span

error[E0425]: cannot find value `Missing0` in this scope
  --> tests/08-ident-span.rs:34:17
   |
34 |         let _ = Missing~N;
   |                 ^^^^^^^ not found in this scope

因為對於N in 0..1後續{}內部的解析,我們都是基於標準的rust語法。
型別未定義這種情況,是必定能夠解析出來的。

從這裡也能夠看出來rust強大的一方面,靜態檢查能夠規避大多數開發問題。
編譯期間,只要有良好、準確的錯誤提示,即使是macro中的自定義語句,也能夠進行錯誤的定位。

雖然span資訊的處理讓人覺得雞肋,但是完整的檢查,可以讓使用者在開發過程中,在一無所知的宏定義中,得到正確的指引。

本作品採用《CC 協議》,轉載必須註明作者和本文連結