mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Rust: move to Label<T> and mark unsafety of from_untyped
This commit is contained in:
@@ -20,7 +20,7 @@ def _get_type(t: str) -> str:
|
|||||||
case "int":
|
case "int":
|
||||||
return "usize"
|
return "usize"
|
||||||
case _ if t[0].isupper():
|
case _ if t[0].isupper():
|
||||||
return f"{t}TrapLabel"
|
return f"trap::Label<{t}>"
|
||||||
case "boolean":
|
case "boolean":
|
||||||
assert False, "boolean unsupported"
|
assert False, "boolean unsupported"
|
||||||
case _:
|
case _:
|
||||||
|
|||||||
@@ -5,33 +5,6 @@
|
|||||||
use crate::trap;
|
use crate::trap;
|
||||||
{{#classes}}
|
{{#classes}}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
||||||
pub struct {{name}}TrapLabel(trap::UntypedLabel);
|
|
||||||
|
|
||||||
impl From<trap::UntypedLabel> for {{name}}TrapLabel {
|
|
||||||
fn from(value: trap::UntypedLabel) -> Self {
|
|
||||||
Self(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<{{name}}TrapLabel> for trap::TrapId<{{name}}> {
|
|
||||||
fn from(value: {{name}}TrapLabel) -> Self {
|
|
||||||
Self::Label(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl trap::Label for {{name}}TrapLabel {
|
|
||||||
fn as_untyped(&self) -> trap::UntypedLabel {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<{{name}}TrapLabel> for trap::Arg {
|
|
||||||
fn from(value: {{name}}TrapLabel) -> Self {
|
|
||||||
value.0.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{{#table_name}}
|
{{#table_name}}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct {{name}} {
|
pub struct {{name}} {
|
||||||
@@ -48,7 +21,7 @@ impl trap::TrapEntry for {{name}} {
|
|||||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(self, id: Self::Label, out: &mut trap::Writer) {
|
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||||
{{#single_field_entries}}
|
{{#single_field_entries}}
|
||||||
out.add_tuple("{{table_name}}", vec![id.into(){{#fields}}, self.{{field_name}}.into(){{/fields}}]);
|
out.add_tuple("{{table_name}}", vec![id.into(){{#fields}}, self.{{field_name}}.into(){{/fields}}]);
|
||||||
{{/single_field_entries}}
|
{{/single_field_entries}}
|
||||||
@@ -87,18 +60,14 @@ pub struct {{name}} {
|
|||||||
unused: ()
|
unused: ()
|
||||||
}
|
}
|
||||||
{{/table_name}}
|
{{/table_name}}
|
||||||
|
|
||||||
impl trap::TrapClass for {{name}} {
|
|
||||||
type Label = {{name}}TrapLabel;
|
|
||||||
}
|
|
||||||
{{/classes}}
|
|
||||||
|
|
||||||
// Conversions
|
|
||||||
{{#classes}}
|
|
||||||
{{#ancestors}}
|
{{#ancestors}}
|
||||||
impl From<{{name}}TrapLabel> for {{.}}TrapLabel {
|
|
||||||
fn from(value: {{name}}TrapLabel) -> Self {
|
impl From<trap::Label<{{name}}>> for trap::Label<{{.}}> {
|
||||||
value.0.into()
|
fn from(value: trap::Label<{{name}}>) -> Self {
|
||||||
|
// SAFETY: this is safe because in the dbscheme {{name}} is a subclass of {{.}}
|
||||||
|
unsafe {
|
||||||
|
Self::from_untyped(value.as_untyped())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{{/ancestors}}
|
{{/ancestors}}
|
||||||
|
|||||||
2
rust/extractor/src/generated/.generated.list
generated
2
rust/extractor/src/generated/.generated.list
generated
@@ -1,2 +1,2 @@
|
|||||||
mod.rs 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e
|
mod.rs 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e 7cdfedcd68cf8e41134daf810c1af78624082b0c3e8be6570339b1a69a5d457e
|
||||||
top.rs e06dc90de4abd57719786fd5e49e6ea3089ec3ec167c64446e25d95a16b1714c e06dc90de4abd57719786fd5e49e6ea3089ec3ec167c64446e25d95a16b1714c
|
top.rs 775cb04552f9242ff999b279a375f7a446124f4ef28668e42496751bf69e7dd3 775cb04552f9242ff999b279a375f7a446124f4ef28668e42496751bf69e7dd3
|
||||||
|
|||||||
4676
rust/extractor/src/generated/top.rs
generated
4676
rust/extractor/src/generated/top.rs
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
use crate::archive::Archiver;
|
use crate::archive::Archiver;
|
||||||
use crate::trap::{AsTrapKeyPart, Label, TrapFile, TrapId};
|
use crate::trap::{AsTrapKeyPart, Label, TrapEntry, TrapFile, TrapId};
|
||||||
use crate::{generated, trap_key};
|
use crate::{generated, trap_key};
|
||||||
use codeql_extractor::trap;
|
use codeql_extractor::trap;
|
||||||
use ra_ap_hir::db::{DefDatabase, InternDatabase};
|
use ra_ap_hir::db::{DefDatabase, InternDatabase};
|
||||||
@@ -71,9 +71,9 @@ impl CrateTranslator<'_> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_location_for_ast_ptr<L: Label, T: AstNode>(
|
fn emit_location_for_ast_ptr<E: TrapEntry, T: AstNode>(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: L,
|
label: Label<E>,
|
||||||
source: ra_ap_hir::InFile<ra_ap_syntax::AstPtr<T>>,
|
source: ra_ap_hir::InFile<ra_ap_syntax::AstPtr<T>>,
|
||||||
) {
|
) {
|
||||||
source
|
source
|
||||||
@@ -89,7 +89,7 @@ impl CrateTranslator<'_> {
|
|||||||
|
|
||||||
fn emit_location_for_expr(
|
fn emit_location_for_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: generated::ElementTrapLabel, // TODO: should be ExprTrapLabel
|
label: Label<generated::Element>, // TODO: should be ExprTrapLabel
|
||||||
expr: ra_ap_hir_def::hir::ExprId,
|
expr: ra_ap_hir_def::hir::ExprId,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) {
|
) {
|
||||||
@@ -101,7 +101,7 @@ impl CrateTranslator<'_> {
|
|||||||
fn emit_location_for_pat(
|
fn emit_location_for_pat(
|
||||||
&mut self,
|
&mut self,
|
||||||
// should be Pat, but we're using for other entities for now
|
// should be Pat, but we're using for other entities for now
|
||||||
label: generated::ElementTrapLabel,
|
label: Label<generated::Element>,
|
||||||
pat_id: ra_ap_hir_def::hir::PatId,
|
pat_id: ra_ap_hir_def::hir::PatId,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) {
|
) {
|
||||||
@@ -115,7 +115,7 @@ impl CrateTranslator<'_> {
|
|||||||
pat: &ra_ap_hir_def::hir::LiteralOrConst,
|
pat: &ra_ap_hir_def::hir::LiteralOrConst,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::PatTrapLabel {
|
) -> Label<generated::Pat> {
|
||||||
match pat {
|
match pat {
|
||||||
ra_ap_hir_def::hir::LiteralOrConst::Literal(_literal) => {
|
ra_ap_hir_def::hir::LiteralOrConst::Literal(_literal) => {
|
||||||
let expr = self.trap.emit(generated::LiteralExpr { id: TrapId::Star });
|
let expr = self.trap.emit(generated::LiteralExpr { id: TrapId::Star });
|
||||||
@@ -132,9 +132,9 @@ impl CrateTranslator<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_location_for_label<T: Label>(
|
fn emit_location_for_label<E: TrapEntry>(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: T,
|
label: Label<E>,
|
||||||
label_id: ra_ap_hir_def::hir::LabelId,
|
label_id: ra_ap_hir_def::hir::LabelId,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) {
|
) {
|
||||||
@@ -144,7 +144,7 @@ impl CrateTranslator<'_> {
|
|||||||
self.emit_location_for_ast_ptr(label, source)
|
self.emit_location_for_ast_ptr(label, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn emit_location<L: Label, T: HasSource>(&mut self, label: L, entity: T)
|
fn emit_location<E: TrapEntry, T: HasSource>(&mut self, label: Label<E>, entity: T)
|
||||||
where
|
where
|
||||||
T::Ast: AstNode,
|
T::Ast: AstNode,
|
||||||
{
|
{
|
||||||
@@ -157,9 +157,9 @@ impl CrateTranslator<'_> {
|
|||||||
self.emit_location_for_textrange(label, data, range);
|
self.emit_location_for_textrange(label, data, range);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn emit_location_for_textrange<L: Label>(
|
fn emit_location_for_textrange<E: TrapEntry>(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: L,
|
label: Label<E>,
|
||||||
data: FileData,
|
data: FileData,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
) {
|
) {
|
||||||
@@ -177,7 +177,7 @@ impl CrateTranslator<'_> {
|
|||||||
label_id: LabelId,
|
label_id: LabelId,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::LabelTrapLabel {
|
) -> Label<generated::Label> {
|
||||||
let label = &body.labels[label_id];
|
let label = &body.labels[label_id];
|
||||||
let ret = self.trap.emit(generated::Label {
|
let ret = self.trap.emit(generated::Label {
|
||||||
id: TrapId::Star,
|
id: TrapId::Star,
|
||||||
@@ -187,11 +187,11 @@ impl CrateTranslator<'_> {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unimplemented(&mut self) -> generated::UnimplementedTrapLabel {
|
fn emit_unimplemented(&mut self) -> Label<generated::Unimplemented> {
|
||||||
self.trap
|
self.trap
|
||||||
.emit(generated::Unimplemented { id: TrapId::Star })
|
.emit(generated::Unimplemented { id: TrapId::Star })
|
||||||
}
|
}
|
||||||
fn emit_path(&mut self, _path: &Path) -> generated::UnimplementedTrapLabel {
|
fn emit_path(&mut self, _path: &Path) -> Label<generated::Unimplemented> {
|
||||||
self.emit_unimplemented()
|
self.emit_unimplemented()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ impl CrateTranslator<'_> {
|
|||||||
field_pat: &RecordFieldPat,
|
field_pat: &RecordFieldPat,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::RecordFieldPatTrapLabel {
|
) -> Label<generated::RecordFieldPat> {
|
||||||
let RecordFieldPat { name, pat } = field_pat;
|
let RecordFieldPat { name, pat } = field_pat;
|
||||||
let pat_label = self.emit_pat(*pat, body, source_map);
|
let pat_label = self.emit_pat(*pat, body, source_map);
|
||||||
let ret = self.trap.emit(generated::RecordFieldPat {
|
let ret = self.trap.emit(generated::RecordFieldPat {
|
||||||
@@ -217,7 +217,7 @@ impl CrateTranslator<'_> {
|
|||||||
field_expr: &RecordLitField,
|
field_expr: &RecordLitField,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::RecordLitFieldTrapLabel {
|
) -> Label<generated::RecordLitField> {
|
||||||
let RecordLitField { name, expr } = field_expr;
|
let RecordLitField { name, expr } = field_expr;
|
||||||
let expr_label = self.emit_expr(*expr, body, source_map);
|
let expr_label = self.emit_expr(*expr, body, source_map);
|
||||||
let ret = self.trap.emit(generated::RecordLitField {
|
let ret = self.trap.emit(generated::RecordLitField {
|
||||||
@@ -234,9 +234,9 @@ impl CrateTranslator<'_> {
|
|||||||
pat_id: PatId,
|
pat_id: PatId,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::PatTrapLabel {
|
) -> Label<generated::Pat> {
|
||||||
let pat = &body.pats[pat_id];
|
let pat = &body.pats[pat_id];
|
||||||
let ret: generated::PatTrapLabel = match pat {
|
let ret: Label<generated::Pat> = match pat {
|
||||||
ra_ap_hir_def::hir::Pat::Missing => self
|
ra_ap_hir_def::hir::Pat::Missing => self
|
||||||
.trap
|
.trap
|
||||||
.emit(generated::MissingPat { id: TrapId::Star })
|
.emit(generated::MissingPat { id: TrapId::Star })
|
||||||
@@ -407,7 +407,7 @@ impl CrateTranslator<'_> {
|
|||||||
self.emit_location_for_pat(ret.into(), pat_id, source_map);
|
self.emit_location_for_pat(ret.into(), pat_id, source_map);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
fn emit_type_ref(&mut self, _type_ref: &TypeRef) -> generated::TypeRefTrapLabel {
|
fn emit_type_ref(&mut self, _type_ref: &TypeRef) -> Label<generated::TypeRef> {
|
||||||
self.emit_unimplemented().into()
|
self.emit_unimplemented().into()
|
||||||
}
|
}
|
||||||
fn emit_match_arm(
|
fn emit_match_arm(
|
||||||
@@ -415,7 +415,7 @@ impl CrateTranslator<'_> {
|
|||||||
arm: &MatchArm,
|
arm: &MatchArm,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::MatchArmTrapLabel {
|
) -> Label<generated::MatchArm> {
|
||||||
let pat = self.emit_pat(arm.pat, body, source_map);
|
let pat = self.emit_pat(arm.pat, body, source_map);
|
||||||
let guard = arm.guard.map(|g| self.emit_expr(g, body, source_map));
|
let guard = arm.guard.map(|g| self.emit_expr(g, body, source_map));
|
||||||
let expr = self.emit_expr(arm.expr, body, source_map);
|
let expr = self.emit_expr(arm.expr, body, source_map);
|
||||||
@@ -434,7 +434,7 @@ impl CrateTranslator<'_> {
|
|||||||
stmt: &Statement,
|
stmt: &Statement,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::StmtTrapLabel {
|
) -> Label<generated::Stmt> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::Let {
|
Statement::Let {
|
||||||
pat,
|
pat,
|
||||||
@@ -483,9 +483,9 @@ impl CrateTranslator<'_> {
|
|||||||
expr_id: ExprId,
|
expr_id: ExprId,
|
||||||
body: &Body,
|
body: &Body,
|
||||||
source_map: &BodySourceMap,
|
source_map: &BodySourceMap,
|
||||||
) -> generated::ExprTrapLabel {
|
) -> Label<generated::Expr> {
|
||||||
let expr = &body[expr_id];
|
let expr = &body[expr_id];
|
||||||
let ret: generated::ExprTrapLabel = match expr {
|
let ret: Label<generated::Expr> = match expr {
|
||||||
ra_ap_hir_def::hir::Expr::Missing => self
|
ra_ap_hir_def::hir::Expr::Missing => self
|
||||||
.trap
|
.trap
|
||||||
.emit(generated::MissingExpr { id: TrapId::Star })
|
.emit(generated::MissingExpr { id: TrapId::Star })
|
||||||
@@ -976,11 +976,11 @@ impl CrateTranslator<'_> {
|
|||||||
|
|
||||||
fn emit_definition(
|
fn emit_definition(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_label: generated::ModuleTrapLabel,
|
module_label: Label<generated::Module>,
|
||||||
id: ModuleDef,
|
id: ModuleDef,
|
||||||
labels: &mut Vec<generated::DeclarationTrapLabel>,
|
labels: &mut Vec<Label<generated::Declaration>>,
|
||||||
) {
|
) {
|
||||||
let label: generated::DeclarationTrapLabel = match id {
|
let label: Label<generated::Declaration> = match id {
|
||||||
ModuleDef::Module(_) => self.emit_unimplemented().into(),
|
ModuleDef::Module(_) => self.emit_unimplemented().into(),
|
||||||
ModuleDef::Function(function) => {
|
ModuleDef::Function(function) => {
|
||||||
let def: ra_ap_hir::DefWithBody = function.into();
|
let def: ra_ap_hir::DefWithBody = function.into();
|
||||||
@@ -1050,7 +1050,7 @@ impl CrateTranslator<'_> {
|
|||||||
labels.push(label);
|
labels.push(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_module(&mut self, label: generated::ModuleTrapLabel, module: Module) {
|
fn emit_module(&mut self, label: Label<generated::Module>, module: Module) {
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
for id in module.declarations(self.db) {
|
for id in module.declarations(self.db) {
|
||||||
self.emit_definition(label, id, &mut children);
|
self.emit_definition(label, id, &mut children);
|
||||||
@@ -1063,7 +1063,7 @@ impl CrateTranslator<'_> {
|
|||||||
|
|
||||||
pub fn emit_crate(&mut self) -> std::io::Result<()> {
|
pub fn emit_crate(&mut self) -> std::io::Result<()> {
|
||||||
self.emit_file(self.krate.root_file(self.db));
|
self.emit_file(self.krate.root_file(self.db));
|
||||||
let mut map = HashMap::<Module, generated::ModuleTrapLabel>::new();
|
let mut map = HashMap::<Module, Label<generated::Module>>::new();
|
||||||
for module in self.krate.modules(self.db) {
|
for module in self.krate.modules(self.db) {
|
||||||
let mut key = String::new();
|
let mut key = String::new();
|
||||||
if let Some(parent) = module.parent(self.db) {
|
if let Some(parent) = module.parent(self.db) {
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ use ra_ap_ide_db::line_index::LineCol;
|
|||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub use trap::Label as UntypedLabel;
|
pub use trap::Label as UntypedLabel;
|
||||||
pub use trap::{Arg, Writer};
|
pub use trap::Writer;
|
||||||
|
|
||||||
//TODO: typed labels
|
//TODO: typed labels
|
||||||
pub trait AsTrapKeyPart {
|
pub trait AsTrapKeyPart {
|
||||||
@@ -38,7 +39,7 @@ impl AsTrapKeyPart for &str {
|
|||||||
pub enum TrapId<T: TrapEntry> {
|
pub enum TrapId<T: TrapEntry> {
|
||||||
Star,
|
Star,
|
||||||
Key(String),
|
Key(String),
|
||||||
Label(T::Label),
|
Label(Label<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TrapEntry> From<String> for TrapId<T> {
|
impl<T: TrapEntry> From<String> for TrapId<T> {
|
||||||
@@ -53,9 +54,9 @@ impl<T: TrapEntry> From<&str> for TrapId<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TrapEntry> From<UntypedLabel> for TrapId<T> {
|
impl<T: TrapEntry> From<Label<T>> for TrapId<T> {
|
||||||
fn from(value: UntypedLabel) -> Self {
|
fn from(value: Label<T>) -> Self {
|
||||||
TrapId::Label(value.into())
|
Self::Label(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,36 +71,67 @@ macro_rules! trap_key {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Label: From<UntypedLabel> + Clone + Debug + Hash + Into<Arg> {
|
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||||
fn as_untyped(&self) -> UntypedLabel;
|
pub struct Label<T: TrapEntry> {
|
||||||
|
untyped: UntypedLabel,
|
||||||
|
phantom: PhantomData<T>, // otherwise Rust wants `T` to be used
|
||||||
|
}
|
||||||
|
|
||||||
|
// not deriving `Clone` and `Copy` because they require `T: Clone` and `T: Copy` respectively,
|
||||||
|
// even if `T` is not actually part of the fields.
|
||||||
|
// see https://github.com/rust-lang/rust/issues/108894
|
||||||
|
impl<T: TrapEntry> Clone for Label<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TrapEntry> Copy for Label<T> {}
|
||||||
|
|
||||||
|
impl<T: TrapEntry> Label<T> {
|
||||||
|
pub fn as_untyped(&self) -> UntypedLabel {
|
||||||
|
self.untyped
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// The user must make sure the label respects TRAP typing
|
||||||
|
pub unsafe fn from_untyped(untyped: UntypedLabel) -> Self {
|
||||||
|
Self {
|
||||||
|
untyped,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TrapEntry> AsTrapKeyPart for Label<T> {
|
||||||
fn as_key_part(&self) -> String {
|
fn as_key_part(&self) -> String {
|
||||||
self.as_untyped().as_key_part()
|
self.as_untyped().as_key_part()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TrapClass {
|
impl<T: TrapEntry> From<Label<T>> for trap::Arg {
|
||||||
type Label: Label;
|
fn from(value: Label<T>) -> Self {
|
||||||
|
trap::Arg::Label(value.as_untyped())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TrapEntry: std::fmt::Debug + TrapClass + Sized {
|
pub trait TrapEntry: std::fmt::Debug + Sized {
|
||||||
fn class_name() -> &'static str;
|
fn class_name() -> &'static str;
|
||||||
|
|
||||||
fn extract_id(&mut self) -> TrapId<Self>;
|
fn extract_id(&mut self) -> TrapId<Self>;
|
||||||
fn emit(self, id: Self::Label, out: &mut trap::Writer);
|
fn emit(self, id: Label<Self>, out: &mut Writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TrapFile {
|
pub struct TrapFile {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
writer: trap::Writer,
|
writer: Writer,
|
||||||
compression: Compression,
|
compression: Compression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrapFile {
|
impl TrapFile {
|
||||||
pub fn emit_location<L: Label>(
|
pub fn emit_location<T: TrapEntry>(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_label: UntypedLabel,
|
file_label: UntypedLabel,
|
||||||
entity_label: L,
|
entity_label: Label<T>,
|
||||||
start: LineCol,
|
start: LineCol,
|
||||||
end: LineCol,
|
end: LineCol,
|
||||||
) {
|
) {
|
||||||
@@ -127,21 +159,28 @@ impl TrapFile {
|
|||||||
extractor::populate_file(&mut self.writer, absolute_path)
|
extractor::populate_file(&mut self.writer, absolute_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label<T: TrapEntry>(&mut self, id: TrapId<T>) -> T::Label {
|
pub fn label<T: TrapEntry>(&mut self, id: TrapId<T>) -> Label<T> {
|
||||||
match id {
|
match id {
|
||||||
TrapId::Star => self.writer.fresh_id().into(),
|
TrapId::Star => {
|
||||||
TrapId::Key(s) => self
|
let untyped = self.writer.fresh_id();
|
||||||
.writer
|
// SAFETY: a `*` trap id is always safe for typing
|
||||||
.global_id(&format!("{},{}", T::class_name(), s))
|
unsafe { Label::from_untyped(untyped) }
|
||||||
.0
|
}
|
||||||
.into(),
|
TrapId::Key(s) => {
|
||||||
|
let untyped = self
|
||||||
|
.writer
|
||||||
|
.global_id(&format!("{},{}", T::class_name(), s))
|
||||||
|
.0;
|
||||||
|
// SAFETY: using type names as prefixes avoids labels having a conflicting type
|
||||||
|
unsafe { Label::from_untyped(untyped) }
|
||||||
|
}
|
||||||
TrapId::Label(l) => l,
|
TrapId::Label(l) => l,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit<T: TrapEntry>(&mut self, mut e: T) -> T::Label {
|
pub fn emit<T: TrapEntry>(&mut self, mut e: T) -> Label<T> {
|
||||||
let label = self.label(e.extract_id());
|
let label = self.label(e.extract_id());
|
||||||
e.emit(label.clone(), &mut self.writer);
|
e.emit(label, &mut self.writer);
|
||||||
label
|
label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user