Skip to content

add "probe" tests #251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/dada-compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ extension-trait = "1.0.2"
url = { workspace = true }
dada-codegen = { version = "0.1.0", path = "../dada-codegen" }
dada-ir-sym = { version = "0.1.0", path = "../dada-ir-sym" }
dada-probe = { version = "0.1.0", path = "../dada-probe" }
6 changes: 6 additions & 0 deletions components/dada-compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use dada_ir_ast::{
ast::{AstFunction, AstItem, AstMember, Identifier},
diagnostic::Diagnostic,
inputs::{CompilationRoot, Krate, SourceFile},
span::AbsoluteSpan,
};
use dada_util::{Fallible, FromImpls, Map, Set, bail, debug};
use salsa::{Database as _, Durability, Event, EventKind, Setter};
Expand Down Expand Up @@ -163,6 +164,11 @@ impl Compiler {
Self::deduplicated(check_all::accumulated::<Diagnostic>(self, source_file))
}

/// Return type of the variable found at the given `span` or `None` if there is no variable there.
pub fn probe_variable_type(&self, span: AbsoluteSpan) -> Option<String> {
self.attach(|db| dada_probe::probe_variable_type(db, span))
}

fn deduplicated(mut diagnostics: Vec<&Diagnostic>) -> Vec<&Diagnostic> {
let mut new = Set::default();
diagnostics.retain(|&d| new.insert(d));
Expand Down
4 changes: 2 additions & 2 deletions components/dada-debug/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ handlebars_helper!(index: |events: array, i: usize| events[i].clone());

pub(crate) fn try_asset(path: &str) -> anyhow::Result<String> {
let result = Assets::get(path).ok_or_else(|| anyhow::anyhow!("no asset `{path}` found"))?;
let s = str::from_utf8(&result.data)?;
Ok(s.to_string())
let s = String::from_utf8(result.data.to_vec())?;
Ok(s)
}
13 changes: 13 additions & 0 deletions components/dada-ir-ast/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ impl AbsoluteSpan {
end: Offset::from(self.end),
}
}

/// True if `self` contains all of `other`
pub fn contains(self, other: AbsoluteSpan) -> bool {
self.source_file == other.source_file && self.start <= other.start && self.end >= other.end
}
}

impl<'db> Span<'db> {
Expand Down Expand Up @@ -199,6 +204,14 @@ pub trait Spanned<'db> {
fn span(&self, db: &'db dyn crate::Db) -> Span<'db>;
}

/// Returns the span of this item in the source.
///
/// This is distinct from the [`Spanned`] impl, which returns
/// the span best used in error reporting.
pub trait SourceSpanned<'db> {
fn source_span(&self, db: &'db dyn crate::Db) -> Span<'db>;
}

/// Either `Span` or `Option<Span>`.
pub trait IntoOptionSpan<'db> {
fn into_opt_span(self) -> Option<Span<'db>>;
Expand Down
2 changes: 1 addition & 1 deletion components/dada-ir-sym/src/check/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
},
};
use dada_ir_ast::{
ast::{AstTy, VariableDecl},
ast::VariableDecl,
diagnostic::{Diagnostic, Err, Reported},
span::Span,
};
Expand Down
5 changes: 3 additions & 2 deletions components/dada-ir-sym/src/check/env/combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<'db> Env<'db> {
async move {
let this = &*self;
let test_fn = &test_fn;
let mut unordered = FuturesUnordered::new();
let unordered = FuturesUnordered::new();
for (item, index) in items.into_iter().zip(0..) {
unordered.push(async move {
let mut env = this.fork(|handle| {
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<'db> Env<'db> {
async move {
let this = &*self;
let test_fn = &test_fn;
let mut unordered = FuturesUnordered::new();
let unordered = FuturesUnordered::new();
for (item, index) in items.into_iter().zip(0..) {
unordered.push(async move {
let mut env = this.fork(|handle| {
Expand Down Expand Up @@ -291,6 +291,7 @@ impl<'db> Env<'db> {
/// You get back bounds from the direction you provide or from
/// either direction if you provide `None`. Multiple bounds from the same direction
/// indicate that the bounds got tighter.
#[expect(dead_code)]
pub fn red_ty_bounds(
&self,
infer: InferVarIndex,
Expand Down
1 change: 0 additions & 1 deletion components/dada-ir-sym/src/check/env/infer_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::pin::pin;

use dada_util::FromImpls;
use either::Either;

use crate::{
check::{
Expand Down
4 changes: 1 addition & 3 deletions components/dada-ir-sym/src/check/functions.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::process::Output;

use crate::{
check::{CheckTyInEnv, signature::PreparedEnv},
ir::{
classes::SymAggregate,
functions::{SymFunction, SymFunctionSource, SymInputOutput},
functions::{SymFunction, SymFunctionSource},
},
};
use dada_ir_ast::{
Expand Down
2 changes: 2 additions & 0 deletions components/dada-ir-sym/src/check/predicates.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![expect(dead_code)]

pub mod is_provably_copy;
pub mod is_provably_lent;
pub mod is_provably_move;
Expand Down
5 changes: 1 addition & 4 deletions components/dada-ir-sym/src/check/predicates/var_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ use crate::{
ir::{indices::InferVarIndex, variables::SymVariable},
};

use super::{
is_provably_copy::term_is_provably_copy, is_provably_lent::term_is_provably_lent,
is_provably_owned::term_is_provably_owned, require_term_is,
};
use super::require_term_is;

pub fn test_var_is_provably<'db>(
env: &mut Env<'db>,
Expand Down
10 changes: 9 additions & 1 deletion components/dada-ir-sym/src/check/red.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde::Serialize;

use crate::ir::{
indices::{FromInfer, InferVarIndex},
types::{SymGenericTerm, SymPerm, SymPlace, SymTy, SymTyKind, SymTyName},
types::{SymGenericTerm, SymPerm, SymPlace, SymTy, SymTyName},
variables::SymVariable,
};

Expand Down Expand Up @@ -41,6 +41,7 @@ impl<'db> RedPerm<'db> {
Ok(true)
}

#[expect(dead_code)]
pub fn is_our(self, env: &Env<'db>) -> Errors<bool> {
Ok(self.is_provably(env, Predicate::Copy)? && self.is_provably(env, Predicate::Owned)?)
}
Expand Down Expand Up @@ -72,6 +73,7 @@ impl<'db> RedChain<'db> {
RedChain::new(db, [RedLink::Our])
}

#[expect(dead_code)]
pub fn is_provably(self, env: &Env<'db>, predicate: Predicate) -> Errors<bool> {
let db = env.db();
match predicate {
Expand Down Expand Up @@ -117,6 +119,7 @@ impl<'db> RedLink<'db> {
first.is_copy(env)
}

#[expect(dead_code)]
pub fn are_move(env: &Env<'db>, links: &[Self]) -> Errors<bool> {
for link in links {
if !link.is_move(env)? {
Expand All @@ -126,6 +129,7 @@ impl<'db> RedLink<'db> {
Ok(true)
}

#[expect(dead_code)]
pub fn are_owned(env: &Env<'db>, links: &[Self]) -> Errors<bool> {
for link in links {
if !link.is_owned(env)? {
Expand All @@ -135,6 +139,7 @@ impl<'db> RedLink<'db> {
Ok(true)
}

#[expect(dead_code)]
pub fn are_lent(env: &Env<'db>, links: &[Self]) -> Errors<bool> {
for link in links {
if !link.is_lent(env)? {
Expand All @@ -144,6 +149,7 @@ impl<'db> RedLink<'db> {
Ok(false)
}

#[expect(dead_code)]
pub fn is_owned(&self, env: &Env<'db>) -> Errors<bool> {
match self {
RedLink::Our => Ok(true),
Expand All @@ -153,6 +159,7 @@ impl<'db> RedLink<'db> {
}
}

#[expect(dead_code)]
pub fn is_lent(&self, env: &Env<'db>) -> Errors<bool> {
match self {
RedLink::Ref(..) | RedLink::Mut(..) => Ok(true),
Expand All @@ -162,6 +169,7 @@ impl<'db> RedLink<'db> {
}
}

#[expect(dead_code)]
pub fn is_move(&self, env: &Env<'db>) -> Errors<bool> {
match self {
RedLink::Mut(..) => Ok(true),
Expand Down
15 changes: 0 additions & 15 deletions components/dada-ir-sym/src/check/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,6 @@ pub enum Because<'db> {
/// program that caused a conflict with the current value
InferredPermBound(Direction, RedPerm<'db>, ArcOrElse<'db>),

/// Inference determined that the variable cannot be
/// known to be `Predicate` "or else" the given error would occur.
InferredIsnt(Predicate, ArcOrElse<'db>),

/// Inference determined that the variable must have
/// this lower bound "or else" the given error would occur.
InferredLowerBound(RedTy<'db>, ArcOrElse<'db>),
Expand Down Expand Up @@ -296,17 +292,6 @@ impl<'db> Because<'db> {
.child(or_else_diagnostic),
)
}
Because::InferredIsnt(predicate, or_else) => {
let or_else_diagnostic = or_else.or_else(env, Because::JustSo);
Some(Diagnostic::info(
db,
span,
format!(
"I inferred that `{predicate}` must not be true because otherwise it would cause this error"
),
)
.child(or_else_diagnostic))
}
Because::InferredLowerBound(red_ty, or_else) => {
let or_else_diagnostic = or_else.or_else(env, Because::JustSo);
Some(Diagnostic::info(
Expand Down
4 changes: 2 additions & 2 deletions components/dada-ir-sym/src/check/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use dada_ir_ast::{
inputs::Krate,
span::{Span, Spanned},
};
use dada_util::{FromImpls, boxed_async_fn, indirect};
use dada_util::{FromImpls, boxed_async_fn};
use salsa::Update;
use serde::Serialize;

Expand All @@ -19,7 +19,7 @@ use crate::{
module::SymModule,
primitive::{SymPrimitive, primitives},
types::{SymGenericKind, SymGenericTerm},
variables::{FromVar, SymVariable},
variables::SymVariable,
},
prelude::Symbol,
};
Expand Down
1 change: 0 additions & 1 deletion components/dada-ir-sym/src/check/subtype/is_numeric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::{
env::Env,
inference::Direction,
live_places::LivePlaces,
predicates::{Predicate, var_infer::require_infer_is},
red::RedTy,
report::{Because, OrElse, OrElseHelper},
to_red::ToRedTy,
Expand Down
3 changes: 1 addition & 2 deletions components/dada-ir-sym/src/check/subtype/terms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use crate::{
ir::{
classes::SymAggregateStyle,
indices::{FromInfer, InferVarIndex},
types::{SymGenericKind, SymGenericTerm, SymPerm, SymTy, SymTyKind, SymTyName, Variance},
variables,
types::{SymGenericKind, SymGenericTerm, SymPerm, SymTy, SymTyKind, SymTyName},
},
};

Expand Down
33 changes: 27 additions & 6 deletions components/dada-ir-sym/src/ir/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;

use dada_ir_ast::{
ast::{AstAggregate, AstAggregateKind, AstFieldDecl, AstMember, Identifier, SpannedIdentifier},
span::{Span, Spanned},
span::{SourceSpanned, Span, Spanned},
};
use dada_parser::prelude::*;
use dada_util::{FromImpls, SalsaSerialize};
Expand Down Expand Up @@ -254,6 +254,18 @@ impl<'db> ScopeTreeNode<'db> for SymAggregate<'db> {
}
}

impl<'db> Spanned<'db> for SymAggregate<'db> {
fn span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
self.name_span(db)
}
}

impl<'db> SourceSpanned<'db> for SymAggregate<'db> {
fn source_span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
self.source(db).span(db)
}
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum SymAggregateStyle {
Struct,
Expand Down Expand Up @@ -289,6 +301,15 @@ impl<'db> Spanned<'db> for SymClassMember<'db> {
}
}

impl<'db> SourceSpanned<'db> for SymClassMember<'db> {
fn source_span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
match self {
SymClassMember::SymField(f) => f.source_span(db),
SymClassMember::SymFunction(f) => f.source_span(db),
}
}
}

/// Symbol for a field of a class, struct, or enum
#[derive(SalsaSerialize)]
#[salsa::tracked(debug)]
Expand Down Expand Up @@ -327,15 +348,15 @@ impl<'db> SymField<'db> {
}
}

impl<'db> Spanned<'db> for SymAggregate<'db> {
fn span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
impl<'db> Spanned<'db> for SymField<'db> {
fn span(&self, db: &'db dyn dada_ir_ast::Db) -> dada_ir_ast::span::Span<'db> {
self.name_span(db)
}
}

impl<'db> Spanned<'db> for SymField<'db> {
fn span(&self, db: &'db dyn dada_ir_ast::Db) -> dada_ir_ast::span::Span<'db> {
self.name_span(db)
impl<'db> SourceSpanned<'db> for SymField<'db> {
fn source_span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
self.source(db).span(db)
}
}

Expand Down
8 changes: 7 additions & 1 deletion components/dada-ir-sym/src/ir/exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
use dada_ir_ast::{
ast::{AstBinaryOp, PermissionOp},
diagnostic::{Err, Reported},
span::Span,
span::{SourceSpanned, Span},
};
use dada_util::SalsaSerialize;
use ordered_float::OrderedFloat;
Expand Down Expand Up @@ -88,6 +88,12 @@ impl<'db> SymExpr<'db> {
}
}

impl<'db> SourceSpanned<'db> for SymExpr<'db> {
fn source_span(&self, db: &'db dyn dada_ir_ast::Db) -> Span<'db> {
self.span(db)
}
}

impl<'db> Err<'db> for SymExpr<'db> {
fn err(db: &'db dyn dada_ir_ast::Db, r: Reported) -> Self {
SymExpr::new(db, r.span(db), SymTy::err(db, r), SymExprKind::Error(r))
Expand Down
Loading
Loading